Fixup import_buffer definition to account for subsurface damage
This commit is contained in:
parent
12e80ca2c6
commit
25c61c7a73
|
@ -1,6 +1,6 @@
|
||||||
#![allow(clippy::too_many_arguments)]
|
#![allow(clippy::too_many_arguments)]
|
||||||
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
|
@ -9,10 +9,7 @@ use smithay::{
|
||||||
renderer::{Frame, Renderer, Texture, Transform},
|
renderer::{Frame, Renderer, Texture, Transform},
|
||||||
SwapBuffersError,
|
SwapBuffersError,
|
||||||
},
|
},
|
||||||
reexports::{
|
reexports::wayland_server::protocol::{wl_buffer, wl_surface},
|
||||||
calloop::LoopHandle,
|
|
||||||
wayland_server::protocol::{wl_buffer, wl_surface},
|
|
||||||
},
|
|
||||||
utils::Rectangle,
|
utils::Rectangle,
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{roles::Role, Damage, SubsurfaceRole, TraversalAction},
|
compositor::{roles::Role, Damage, SubsurfaceRole, TraversalAction},
|
||||||
|
@ -98,7 +95,16 @@ where
|
||||||
let mut data = data.borrow_mut();
|
let mut data = data.borrow_mut();
|
||||||
if data.texture.is_none() {
|
if data.texture.is_none() {
|
||||||
if let Some(buffer) = data.current_state.buffer.take() {
|
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::<Vec<_>>();
|
||||||
|
match renderer.import_buffer(&buffer, Some(&attributes), &damage, egl_buffer_reader) {
|
||||||
Ok(m) => {
|
Ok(m) => {
|
||||||
let buffer = if smithay::wayland::shm::with_buffer_contents(
|
let buffer = if smithay::wayland::shm::with_buffer_contents(
|
||||||
&buffer,
|
&buffer,
|
||||||
|
|
|
@ -32,8 +32,7 @@ use crate::backend::SwapBuffersError;
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::egl::display::EGLBufferReader,
|
backend::egl::display::EGLBufferReader, utils::Rectangle, wayland::compositor::SurfaceAttributes,
|
||||||
wayland::compositor::{Damage, SurfaceAttributes},
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use wayland_commons::user_data::UserDataMap;
|
use wayland_commons::user_data::UserDataMap;
|
||||||
|
@ -506,7 +505,8 @@ impl Gles2Renderer {
|
||||||
fn import_shm(
|
fn import_shm(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &wl_buffer::WlBuffer,
|
buffer: &wl_buffer::WlBuffer,
|
||||||
surface: &SurfaceAttributes,
|
surface: Option<&SurfaceAttributes>,
|
||||||
|
damage: &[Rectangle],
|
||||||
) -> Result<Gles2Texture, Gles2Error> {
|
) -> Result<Gles2Texture, Gles2Error> {
|
||||||
use crate::wayland::shm::with_buffer_contents;
|
use crate::wayland::shm::with_buffer_contents;
|
||||||
|
|
||||||
|
@ -539,9 +539,7 @@ impl Gles2Renderer {
|
||||||
// why not store a `Gles2Texture`? because the user might do so.
|
// why not store a `Gles2Texture`? because the user might do so.
|
||||||
// this is guaranteed a non-public internal type, so we are good.
|
// this is guaranteed a non-public internal type, so we are good.
|
||||||
surface
|
surface
|
||||||
.user_data
|
.and_then(|surface| surface.user_data.get::<Rc<Gles2TextureInternal>>().cloned())
|
||||||
.get::<Rc<Gles2TextureInternal>>()
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
let mut tex = 0;
|
let mut tex = 0;
|
||||||
unsafe { self.gl.GenTextures(1, &mut tex) };
|
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);
|
.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_T, ffi::CLAMP_TO_EDGE as i32);
|
||||||
self.gl.PixelStorei(ffi::UNPACK_ROW_LENGTH, stride / pixelsize);
|
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);
|
trace!(self.logger, "Uploading shm texture for {:?}", buffer);
|
||||||
self.gl.TexImage2D(
|
self.gl.TexImage2D(
|
||||||
ffi::TEXTURE_2D,
|
ffi::TEXTURE_2D,
|
||||||
|
@ -585,11 +583,7 @@ impl Gles2Renderer {
|
||||||
slice.as_ptr().offset(offset as isize) as *const _,
|
slice.as_ptr().offset(offset as isize) as *const _,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
for region in surface.damage.iter().map(|dmg| match dmg {
|
for region in damage.iter() {
|
||||||
Damage::Buffer(rect) => *rect,
|
|
||||||
// TODO also apply transformations
|
|
||||||
Damage::Surface(rect) => rect.scale(surface.buffer_scale),
|
|
||||||
}) {
|
|
||||||
trace!(self.logger, "Uploading partial shm texture for {:?}", buffer);
|
trace!(self.logger, "Uploading partial shm texture for {:?}", buffer);
|
||||||
self.gl.PixelStorei(ffi::UNPACK_SKIP_PIXELS, region.x);
|
self.gl.PixelStorei(ffi::UNPACK_SKIP_PIXELS, region.x);
|
||||||
self.gl.PixelStorei(ffi::UNPACK_SKIP_ROWS, region.y);
|
self.gl.PixelStorei(ffi::UNPACK_SKIP_ROWS, region.y);
|
||||||
|
@ -945,13 +939,14 @@ impl Renderer for Gles2Renderer {
|
||||||
fn import_buffer(
|
fn import_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &wl_buffer::WlBuffer,
|
buffer: &wl_buffer::WlBuffer,
|
||||||
surface: &SurfaceAttributes,
|
surface: Option<&SurfaceAttributes>,
|
||||||
|
damage: &[Rectangle],
|
||||||
egl: Option<&EGLBufferReader>,
|
egl: Option<&EGLBufferReader>,
|
||||||
) -> Result<Self::TextureId, Self::Error> {
|
) -> Result<Self::TextureId, Self::Error> {
|
||||||
let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() {
|
let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() {
|
||||||
self.import_egl(&buffer, egl.unwrap())
|
self.import_egl(&buffer, egl.unwrap())
|
||||||
} else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
|
} else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
|
||||||
self.import_shm(&buffer, surface)
|
self.import_shm(&buffer, surface, damage)
|
||||||
} else {
|
} else {
|
||||||
Err(Gles2Error::UnknownBufferType)
|
Err(Gles2Error::UnknownBufferType)
|
||||||
}?;
|
}?;
|
||||||
|
|
|
@ -11,12 +11,11 @@ use std::collections::HashSet;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use crate::wayland::compositor::SurfaceAttributes;
|
use crate::{utils::Rectangle, wayland::compositor::SurfaceAttributes};
|
||||||
use cgmath::{prelude::*, Matrix3, Vector2};
|
use cgmath::{prelude::*, Matrix3, Vector2};
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use wayland_server::protocol::{wl_buffer, wl_shm};
|
use wayland_server::protocol::{wl_buffer, wl_shm};
|
||||||
|
|
||||||
use crate::{backend::SwapBuffersError, utils::Rectangle};
|
|
||||||
#[cfg(feature = "renderer_gl")]
|
#[cfg(feature = "renderer_gl")]
|
||||||
pub mod gles2;
|
pub mod gles2;
|
||||||
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))]
|
#[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,
|
/// 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.
|
/// 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
|
/// 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"))]
|
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))]
|
||||||
fn import_buffer(
|
fn import_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &wl_buffer::WlBuffer,
|
buffer: &wl_buffer::WlBuffer,
|
||||||
surface: &SurfaceAttributes,
|
surface: Option<&SurfaceAttributes>,
|
||||||
|
damage: &[Rectangle],
|
||||||
egl: Option<&EGLBufferReader>,
|
egl: Option<&EGLBufferReader>,
|
||||||
) -> Result<Self::TextureId, Self::Error>;
|
) -> Result<Self::TextureId, Self::Error>;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue