use super::device::Device;
use super::surface::Surface;
use crate::context::ContextID;
use crate::egl;
use crate::egl::types::EGLint;
use crate::platform::generic::egl::context::{self, CurrentContextGuard, EGLBackedContext};
use crate::{ContextAttributes, Error, Gl, SurfaceInfo};
use std::os::raw::c_void;
pub use crate::platform::generic::egl::context::{ContextDescriptor, NativeContext};
pub struct Context(pub(crate) EGLBackedContext, pub(crate) Gl);
impl Device {
#[inline]
pub fn create_context_descriptor(
&self,
attributes: &ContextAttributes,
) -> Result<ContextDescriptor, Error> {
self.adapter.set_environment_variables();
unsafe {
ContextDescriptor::new(
self.native_connection.egl_display,
attributes,
&[
egl::SURFACE_TYPE as EGLint,
egl::WINDOW_BIT as EGLint,
egl::RENDERABLE_TYPE as EGLint,
egl::OPENGL_BIT as EGLint,
],
)
}
}
#[inline]
pub fn create_context(
&self,
descriptor: &ContextDescriptor,
share_with: Option<&Context>,
) -> Result<Context, Error> {
unsafe {
let context = EGLBackedContext::new(
self.native_connection.egl_display,
descriptor,
share_with.map(|ctx| &ctx.0),
self.gl_api(),
)?;
context.make_current(self.native_connection.egl_display)?;
Ok(Context(
context,
Gl::from_loader_function(context::get_proc_address),
))
}
}
#[inline]
pub unsafe fn create_context_from_native_context(
&self,
native_context: NativeContext,
) -> Result<Context, Error> {
Ok(Context(
EGLBackedContext::from_native_context(native_context),
Gl::from_loader_function(context::get_proc_address),
))
}
pub fn destroy_context(&self, context: &mut Context) -> Result<(), Error> {
if let Ok(Some(mut surface)) = self.unbind_surface_from_context(context) {
self.destroy_surface(context, &mut surface)?;
}
unsafe {
context.0.destroy(self.native_connection.egl_display);
Ok(())
}
}
#[inline]
pub fn native_context(&self, context: &Context) -> NativeContext {
context.0.native_context()
}
#[inline]
pub fn context_descriptor(&self, context: &Context) -> ContextDescriptor {
unsafe {
ContextDescriptor::from_egl_context(
&context.1,
self.native_connection.egl_display,
context.0.egl_context,
)
}
}
#[inline]
pub fn make_context_current(&self, context: &Context) -> Result<(), Error> {
unsafe { context.0.make_current(self.native_connection.egl_display) }
}
#[inline]
pub fn make_no_context_current(&self) -> Result<(), Error> {
unsafe { context::make_no_context_current(self.native_connection.egl_display) }
}
#[inline]
pub(crate) fn temporarily_make_context_current(
&self,
context: &Context,
) -> Result<CurrentContextGuard, Error> {
let guard = CurrentContextGuard::new();
self.make_context_current(context)?;
Ok(guard)
}
#[inline]
pub fn context_descriptor_attributes(
&self,
context_descriptor: &ContextDescriptor,
) -> ContextAttributes {
unsafe { context_descriptor.attributes(self.native_connection.egl_display) }
}
#[inline]
pub fn get_proc_address(&self, _: &Context, symbol_name: &str) -> *const c_void {
context::get_proc_address(symbol_name)
}
#[inline]
pub fn bind_surface_to_context(
&self,
context: &mut Context,
surface: Surface,
) -> Result<(), (Error, Surface)> {
unsafe {
context
.0
.bind_surface(self.native_connection.egl_display, surface.0)
.map_err(|(err, surface)| (err, Surface(surface)))
}
}
pub fn unbind_surface_from_context(
&self,
context: &mut Context,
) -> Result<Option<Surface>, Error> {
unsafe {
context
.0
.unbind_surface(&context.1, self.native_connection.egl_display)
.map(|maybe_surface| maybe_surface.map(Surface))
}
}
#[inline]
pub fn context_id(&self, context: &Context) -> ContextID {
context.0.id
}
#[inline]
pub fn context_surface_info(&self, context: &Context) -> Result<Option<SurfaceInfo>, Error> {
context.0.surface_info()
}
}