opengl: implement AsyncShmGfxTexture
This commit is contained in:
parent
f213372b8e
commit
0a0caf3800
5 changed files with 111 additions and 8 deletions
|
|
@ -537,8 +537,8 @@ pub trait ShmGfxTexture: GfxTexture {
|
||||||
fn into_texture(self: Rc<Self>) -> Rc<dyn GfxTexture>;
|
fn into_texture(self: Rc<Self>) -> Rc<dyn GfxTexture>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[expect(dead_code)]
|
|
||||||
pub trait AsyncShmGfxTextureCallback {
|
pub trait AsyncShmGfxTextureCallback {
|
||||||
|
#[expect(dead_code)]
|
||||||
fn completed(self: Rc<Self>, res: Result<(), GfxError>);
|
fn completed(self: Rc<Self>, res: Result<(), GfxError>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,7 +560,6 @@ pub trait AsyncShmGfxTexture: GfxTexture {
|
||||||
damage: Region,
|
damage: Region,
|
||||||
) -> Result<Option<PendingShmUpload>, GfxError>;
|
) -> Result<Option<PendingShmUpload>, GfxError>;
|
||||||
|
|
||||||
#[expect(dead_code)]
|
|
||||||
fn sync_upload(self: Rc<Self>, shm: &[Cell<u8>], damage: Region) -> Result<(), GfxError>;
|
fn sync_upload(self: Rc<Self>, shm: &[Cell<u8>], damage: Region) -> Result<(), GfxError>;
|
||||||
|
|
||||||
#[expect(dead_code)]
|
#[expect(dead_code)]
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ macro_rules! dynload {
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
clientmem::ClientMemError,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, CopyTexture, FillRect, GfxApiOpt, GfxContext, GfxError, GfxTexture,
|
AcquireSync, CopyTexture, FillRect, GfxApiOpt, GfxContext, GfxError, GfxTexture,
|
||||||
ReleaseSync, SyncFile,
|
ReleaseSync, SyncFile,
|
||||||
|
|
@ -196,6 +197,8 @@ enum RenderError {
|
||||||
WaitSync,
|
WaitSync,
|
||||||
#[error("Buffer format {0} is not supported for shm buffers in OpenGL context")]
|
#[error("Buffer format {0} is not supported for shm buffers in OpenGL context")]
|
||||||
UnsupportedShmFormat(&'static str),
|
UnsupportedShmFormat(&'static str),
|
||||||
|
#[error("Could not access the client memory")]
|
||||||
|
AccessFailed(#[source] ClientMemError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -318,6 +321,10 @@ fn fill_boxes3(ctx: &GlRenderContext, boxes: &[[f32; 2]], color: &Color) {
|
||||||
|
|
||||||
fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
|
fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
|
||||||
let texture = tex.tex.as_gl();
|
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));
|
assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx));
|
||||||
let gles = ctx.ctx.dpy.gles;
|
let gles = ctx.ctx.dpy.gles;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,10 @@ pub struct GlTexture {
|
||||||
pub tex: GLuint,
|
pub tex: GLuint,
|
||||||
pub width: i32,
|
pub width: i32,
|
||||||
pub height: i32,
|
pub height: i32,
|
||||||
|
pub stride: i32,
|
||||||
pub external_only: bool,
|
pub external_only: bool,
|
||||||
pub format: &'static Format,
|
pub format: &'static Format,
|
||||||
|
pub contents_valid: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn image_target(external_only: bool) -> GLenum {
|
pub fn image_target(external_only: bool) -> GLenum {
|
||||||
|
|
@ -60,8 +62,10 @@ impl GlTexture {
|
||||||
tex,
|
tex,
|
||||||
width: img.dmabuf.width,
|
width: img.dmabuf.width,
|
||||||
height: img.dmabuf.height,
|
height: img.dmabuf.height,
|
||||||
|
stride: 0,
|
||||||
external_only: img.external_only,
|
external_only: img.external_only,
|
||||||
format: img.dmabuf.format,
|
format: img.dmabuf.format,
|
||||||
|
contents_valid: Cell::new(true),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,8 +112,10 @@ impl GlTexture {
|
||||||
tex,
|
tex,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
stride,
|
||||||
external_only: false,
|
external_only: false,
|
||||||
format,
|
format,
|
||||||
|
contents_valid: Cell::new(true),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -282,13 +282,32 @@ impl GfxContext for GlRenderContext {
|
||||||
|
|
||||||
fn async_shmem_texture(
|
fn async_shmem_texture(
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
_format: &'static Format,
|
format: &'static Format,
|
||||||
_width: i32,
|
width: i32,
|
||||||
_height: i32,
|
height: i32,
|
||||||
_stride: i32,
|
stride: i32,
|
||||||
_cpu_worker: &Rc<CpuWorker>,
|
_cpu_worker: &Rc<CpuWorker>,
|
||||||
) -> Result<Rc<dyn AsyncShmGfxTexture>, GfxError> {
|
) -> 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> {
|
fn allocator(&self) -> Rc<dyn Allocator> {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,21 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
clientmem::ClientMemOffset,
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{GfxError, GfxTexture, ShmGfxTexture},
|
gfx_api::{
|
||||||
|
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxError, GfxTexture, PendingShmUpload,
|
||||||
|
ShmGfxTexture,
|
||||||
|
},
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
gl::texture::GlTexture,
|
gl::texture::GlTexture,
|
||||||
renderer::{context::GlRenderContext, framebuffer::Framebuffer},
|
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,
|
RenderError,
|
||||||
},
|
},
|
||||||
|
rect::Region,
|
||||||
video::dmabuf::DmaBuf,
|
video::dmabuf::DmaBuf,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
|
|
@ -88,3 +97,66 @@ impl ShmGfxTexture for Texture {
|
||||||
self
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue