diff --git a/anvil/src/drawing.rs b/anvil/src/drawing.rs index 15a244d..fbaafe8 100644 --- a/anvil/src/drawing.rs +++ b/anvil/src/drawing.rs @@ -1,6 +1,6 @@ #![allow(clippy::too_many_arguments)] -use std::{cell::RefCell, rc::Rc}; +use std::cell::RefCell; use slog::Logger; use smithay::{ @@ -9,10 +9,7 @@ use smithay::{ renderer::{Frame, Renderer, Texture, Transform}, SwapBuffersError, }, - reexports::{ - calloop::LoopHandle, - wayland_server::protocol::{wl_buffer, wl_surface}, - }, + reexports::wayland_server::protocol::{wl_buffer, wl_surface}, utils::Rectangle, wayland::{ compositor::{roles::Role, Damage, SubsurfaceRole, TraversalAction}, @@ -98,7 +95,16 @@ where let mut data = data.borrow_mut(); if data.texture.is_none() { if let Some(buffer) = data.current_state.buffer.take() { - match renderer.import_buffer(&buffer, &attributes, egl_buffer_reader) { + let damage = attributes + .damage + .iter() + .map(|dmg| match dmg { + Damage::Buffer(rect) => *rect, + // TODO also apply transformations + Damage::Surface(rect) => rect.scale(attributes.buffer_scale), + }) + .collect::>(); + match renderer.import_buffer(&buffer, Some(&attributes), &damage, egl_buffer_reader) { Ok(m) => { let buffer = if smithay::wayland::shm::with_buffer_contents( &buffer, diff --git a/src/backend/renderer/gles2/mod.rs b/src/backend/renderer/gles2/mod.rs index 0c06c58..fffeca0 100644 --- a/src/backend/renderer/gles2/mod.rs +++ b/src/backend/renderer/gles2/mod.rs @@ -32,8 +32,7 @@ use crate::backend::SwapBuffersError; #[cfg(feature = "wayland_frontend")] use crate::{ - backend::egl::display::EGLBufferReader, - wayland::compositor::{Damage, SurfaceAttributes}, + backend::egl::display::EGLBufferReader, utils::Rectangle, wayland::compositor::SurfaceAttributes, }; #[cfg(feature = "wayland_frontend")] use wayland_commons::user_data::UserDataMap; @@ -506,7 +505,8 @@ impl Gles2Renderer { fn import_shm( &mut self, buffer: &wl_buffer::WlBuffer, - surface: &SurfaceAttributes, + surface: Option<&SurfaceAttributes>, + damage: &[Rectangle], ) -> Result { use crate::wayland::shm::with_buffer_contents; @@ -539,9 +539,7 @@ impl Gles2Renderer { // why not store a `Gles2Texture`? because the user might do so. // this is guaranteed a non-public internal type, so we are good. surface - .user_data - .get::>() - .cloned() + .and_then(|surface| surface.user_data.get::>().cloned()) .unwrap_or_else(|| { let mut tex = 0; unsafe { self.gl.GenTextures(1, &mut tex) }; @@ -571,7 +569,7 @@ impl Gles2Renderer { .TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_T, ffi::CLAMP_TO_EDGE as i32); self.gl.PixelStorei(ffi::UNPACK_ROW_LENGTH, stride / pixelsize); - if upload_full { + if upload_full || damage.is_empty() { trace!(self.logger, "Uploading shm texture for {:?}", buffer); self.gl.TexImage2D( ffi::TEXTURE_2D, @@ -585,11 +583,7 @@ impl Gles2Renderer { slice.as_ptr().offset(offset as isize) as *const _, ); } else { - for region in surface.damage.iter().map(|dmg| match dmg { - Damage::Buffer(rect) => *rect, - // TODO also apply transformations - Damage::Surface(rect) => rect.scale(surface.buffer_scale), - }) { + for region in damage.iter() { trace!(self.logger, "Uploading partial shm texture for {:?}", buffer); self.gl.PixelStorei(ffi::UNPACK_SKIP_PIXELS, region.x); self.gl.PixelStorei(ffi::UNPACK_SKIP_ROWS, region.y); @@ -945,13 +939,14 @@ impl Renderer for Gles2Renderer { fn import_buffer( &mut self, buffer: &wl_buffer::WlBuffer, - surface: &SurfaceAttributes, + surface: Option<&SurfaceAttributes>, + damage: &[Rectangle], egl: Option<&EGLBufferReader>, ) -> Result { let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() { self.import_egl(&buffer, egl.unwrap()) } else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() { - self.import_shm(&buffer, surface) + self.import_shm(&buffer, surface, damage) } else { Err(Gles2Error::UnknownBufferType) }?; diff --git a/src/backend/renderer/mod.rs b/src/backend/renderer/mod.rs index dabe85b..ed1086c 100644 --- a/src/backend/renderer/mod.rs +++ b/src/backend/renderer/mod.rs @@ -11,12 +11,11 @@ use std::collections::HashSet; use std::error::Error; #[cfg(feature = "wayland_frontend")] -use crate::wayland::compositor::SurfaceAttributes; +use crate::{utils::Rectangle, wayland::compositor::SurfaceAttributes}; use cgmath::{prelude::*, Matrix3, Vector2}; #[cfg(feature = "wayland_frontend")] use wayland_server::protocol::{wl_buffer, wl_shm}; -use crate::{backend::SwapBuffersError, utils::Rectangle}; #[cfg(feature = "renderer_gl")] pub mod gles2; #[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))] @@ -236,13 +235,16 @@ pub trait Renderer { /// The implementation defines, if the id keeps being valid, if the buffer is released, /// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again. /// + /// If provided the `SurfaceAttributes` can be used to do caching of rendering resources and is generally recommended. + /// /// The `damage` argument provides a list of rectangle locating parts of the buffer that need to be updated. When provided - /// with an empty list `&[]`, the renderer is allows to not update the texture at all. + /// with an empty list `&[]`, the renderer is allowed to not update the texture at all. #[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))] fn import_buffer( &mut self, buffer: &wl_buffer::WlBuffer, - surface: &SurfaceAttributes, + surface: Option<&SurfaceAttributes>, + damage: &[Rectangle], egl: Option<&EGLBufferReader>, ) -> Result;