use super::context::Context;
use super::device::Device;
use crate::gl;
use crate::platform::generic::egl::surface::{EGLBackedSurface, EGLSurfaceTexture};
use crate::{Error, SurfaceAccess, SurfaceInfo, SurfaceType};
use euclid::default::Size2D;
use glow::Texture;
use std::marker::PhantomData;
const SURFACE_GL_TEXTURE_TARGET: u32 = gl::TEXTURE_2D;
#[derive(Debug)]
pub struct Surface(pub(crate) EGLBackedSurface);
#[derive(Debug)]
pub struct SurfaceTexture(pub(crate) EGLSurfaceTexture);
#[derive(Clone)]
pub struct NativeWidget;
unsafe impl Send for Surface {}
impl Device {
pub fn create_surface(
&self,
context: &Context,
_: SurfaceAccess,
surface_type: SurfaceType<NativeWidget>,
) -> Result<Surface, Error> {
match surface_type {
SurfaceType::Generic { size } => self.create_generic_surface(context, &size),
SurfaceType::Widget { .. } => Err(Error::UnsupportedOnThisPlatform),
}
}
fn create_generic_surface(
&self,
context: &Context,
size: &Size2D<i32>,
) -> Result<Surface, Error> {
let _guard = self.temporarily_make_context_current(context)?;
let context_descriptor = self.context_descriptor(context);
let context_attributes = self.context_descriptor_attributes(&context_descriptor);
Ok(Surface(EGLBackedSurface::new_generic(
&context.1,
self.native_connection.egl_display,
context.0.egl_context,
context.0.id,
&context_attributes,
size,
)))
}
pub fn create_surface_texture(
&self,
context: &mut Context,
surface: Surface,
) -> Result<SurfaceTexture, (Error, Surface)> {
let _guard = match self.temporarily_make_context_current(context) {
Ok(guard) => guard,
Err(err) => return Err((err, surface)),
};
match surface.0.to_surface_texture(&context.1) {
Ok(surface_texture) => Ok(SurfaceTexture(surface_texture)),
Err((err, surface)) => Err((err, Surface(surface))),
}
}
pub fn destroy_surface(
&self,
context: &mut Context,
surface: &mut Surface,
) -> Result<(), Error> {
let egl_display = self.native_connection.egl_display;
let window = surface.0.destroy(&context.1, egl_display, context.0.id)?;
debug_assert!(window.is_none());
Ok(())
}
pub fn destroy_surface_texture(
&self,
context: &mut Context,
surface_texture: SurfaceTexture,
) -> Result<Surface, (Error, SurfaceTexture)> {
match self.temporarily_make_context_current(context) {
Ok(_guard) => Ok(Surface(surface_texture.0.destroy(&context.1))),
Err(err) => Err((err, surface_texture)),
}
}
pub fn present_surface(&self, context: &Context, surface: &mut Surface) -> Result<(), Error> {
surface
.0
.present(self.native_connection.egl_display, context.0.egl_context)
}
pub fn resize_surface(
&self,
_context: &Context,
surface: &mut Surface,
size: Size2D<i32>,
) -> Result<(), Error> {
surface.0.size = size;
Ok(())
}
#[inline]
pub fn lock_surface_data<'s>(&self, _: &'s mut Surface) -> Result<SurfaceDataGuard<'s>, Error> {
Err(Error::Unimplemented)
}
#[inline]
pub fn surface_gl_texture_target(&self) -> u32 {
SURFACE_GL_TEXTURE_TARGET
}
pub fn surface_info(&self, surface: &Surface) -> SurfaceInfo {
surface.0.info()
}
#[inline]
pub fn surface_texture_object(&self, surface_texture: &SurfaceTexture) -> Option<Texture> {
surface_texture.0.texture_object
}
}
pub struct SurfaceDataGuard<'a> {
phantom: PhantomData<&'a ()>,
}