1
0
Fork 0
forked from wry/wry

opengl: implement AsyncShmGfxTexture

This commit is contained in:
Julian Orth 2024-09-07 21:35:21 +02:00
parent f213372b8e
commit 0a0caf3800
5 changed files with 111 additions and 8 deletions

View file

@ -537,8 +537,8 @@ pub trait ShmGfxTexture: GfxTexture {
fn into_texture(self: Rc<Self>) -> Rc<dyn GfxTexture>;
}
#[expect(dead_code)]
pub trait AsyncShmGfxTextureCallback {
#[expect(dead_code)]
fn completed(self: Rc<Self>, res: Result<(), GfxError>);
}
@ -560,7 +560,6 @@ pub trait AsyncShmGfxTexture: GfxTexture {
damage: Region,
) -> Result<Option<PendingShmUpload>, GfxError>;
#[expect(dead_code)]
fn sync_upload(self: Rc<Self>, shm: &[Cell<u8>], damage: Region) -> Result<(), GfxError>;
#[expect(dead_code)]

View file

@ -67,6 +67,7 @@ macro_rules! dynload {
use {
crate::{
clientmem::ClientMemError,
gfx_api::{
AcquireSync, CopyTexture, FillRect, GfxApiOpt, GfxContext, GfxError, GfxTexture,
ReleaseSync, SyncFile,
@ -196,6 +197,8 @@ enum RenderError {
WaitSync,
#[error("Buffer format {0} is not supported for shm buffers in OpenGL context")]
UnsupportedShmFormat(&'static str),
#[error("Could not access the client memory")]
AccessFailed(#[source] ClientMemError),
}
#[derive(Default)]
@ -318,6 +321,10 @@ fn fill_boxes3(ctx: &GlRenderContext, boxes: &[[f32; 2]], color: &Color) {
fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
let texture = tex.tex.as_gl();
if !texture.gl.contents_valid.get() {
log::error!("Ignoring texture with invalid contents");
return;
}
assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx));
let gles = ctx.ctx.dpy.gles;
unsafe {

View file

@ -21,8 +21,10 @@ pub struct GlTexture {
pub tex: GLuint,
pub width: i32,
pub height: i32,
pub stride: i32,
pub external_only: bool,
pub format: &'static Format,
pub contents_valid: Cell<bool>,
}
pub fn image_target(external_only: bool) -> GLenum {
@ -60,8 +62,10 @@ impl GlTexture {
tex,
width: img.dmabuf.width,
height: img.dmabuf.height,
stride: 0,
external_only: img.external_only,
format: img.dmabuf.format,
contents_valid: Cell::new(true),
})
}
@ -108,8 +112,10 @@ impl GlTexture {
tex,
width,
height,
stride,
external_only: false,
format,
contents_valid: Cell::new(true),
})
}
}

View file

@ -282,13 +282,32 @@ impl GfxContext for GlRenderContext {
fn async_shmem_texture(
self: Rc<Self>,
_format: &'static Format,
_width: i32,
_height: i32,
_stride: i32,
format: &'static Format,
width: i32,
height: i32,
stride: i32,
_cpu_worker: &Rc<CpuWorker>,
) -> Result<Rc<dyn AsyncShmGfxTexture>, GfxError> {
todo!()
let tex = self.ctx.with_current(|| unsafe {
let mut tex = 0;
(self.ctx.dpy.gles.glGenTextures)(1, &mut tex);
Ok(tex)
})?;
Ok(Rc::new(Texture {
gl: GlTexture {
ctx: self.ctx.clone(),
img: None,
tex,
width,
height,
stride,
external_only: false,
format,
contents_valid: Cell::new(false),
},
ctx: self,
format,
}))
}
fn allocator(&self) -> Rc<dyn Allocator> {

View file

@ -1,12 +1,21 @@
use {
crate::{
clientmem::ClientMemOffset,
format::Format,
gfx_api::{GfxError, GfxTexture, ShmGfxTexture},
gfx_api::{
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxError, GfxTexture, PendingShmUpload,
ShmGfxTexture,
},
gfx_apis::gl::{
gl::texture::GlTexture,
renderer::{context::GlRenderContext, framebuffer::Framebuffer},
sys::{
GLint, GL_CLAMP_TO_EDGE, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T,
GL_UNPACK_ROW_LENGTH_EXT,
},
RenderError,
},
rect::Region,
video::dmabuf::DmaBuf,
},
std::{
@ -88,3 +97,66 @@ impl ShmGfxTexture for Texture {
self
}
}
impl AsyncShmGfxTexture for Texture {
fn async_upload(
self: Rc<Self>,
_callback: Rc<dyn AsyncShmGfxTextureCallback>,
mem: &Rc<ClientMemOffset>,
damage: Region,
) -> Result<Option<PendingShmUpload>, GfxError> {
mem.access(|data| self.clone().sync_upload(data, damage))
.map_err(RenderError::AccessFailed)??;
Ok(None)
}
fn sync_upload(self: Rc<Self>, data: &[Cell<u8>], _damage: Region) -> Result<(), GfxError> {
let shm_info = self.format.shm_info.as_ref().unwrap();
if (self.gl.stride * self.gl.height) as usize > data.len() {
return Err(RenderError::SmallImageBuffer.into());
}
let gles = self.ctx.ctx.dpy.gles;
self.ctx.ctx.with_current(|| unsafe {
(gles.glBindTexture)(GL_TEXTURE_2D, self.gl.tex);
(gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
(gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
(gles.glPixelStorei)(
GL_UNPACK_ROW_LENGTH_EXT,
self.gl.stride / shm_info.bpp as GLint,
);
(gles.glTexImage2D)(
GL_TEXTURE_2D,
0,
shm_info.gl_format,
self.gl.width,
self.gl.height,
0,
shm_info.gl_format as _,
shm_info.gl_type as _,
data.as_ptr() as _,
);
(gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, 0);
(gles.glBindTexture)(GL_TEXTURE_2D, 0);
Ok(())
})?;
self.gl.contents_valid.set(true);
Ok(())
}
fn compatible_with(
&self,
format: &'static Format,
width: i32,
height: i32,
stride: i32,
) -> bool {
format == self.gl.format
&& width == self.gl.width
&& height == self.gl.height
&& stride == self.gl.stride
}
fn into_texture(self: Rc<Self>) -> Rc<dyn GfxTexture> {
self
}
}