From 2baba0ec931011919f35b5ac07c7d272b8950618 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 7 Oct 2024 15:46:49 -0700 Subject: [PATCH] gles: Define a `TextureShaderElement` `GlesFrame` has support for using a custom shader, but there doesn't seem to be a particularly convenient way to use this. I'm not sure exactly how `override_default_tex_program` would best be used, and it's probably not a good way to use a shader for one specific element. `TextureShaderElement` wraps a `TextureRenderElement` with a shader and uniforms. So doesn't have to duplicate the implementation of different constructors `TextureRenderElement` provides. --- src/backend/renderer/element/texture.rs | 2 +- src/backend/renderer/gles/element.rs | 98 ++++++++++++++++++++++++- src/backend/renderer/glow.rs | 18 +++++ 3 files changed, 113 insertions(+), 5 deletions(-) diff --git a/src/backend/renderer/element/texture.rs b/src/backend/renderer/element/texture.rs index 94abae1f3506..621c45048b61 100644 --- a/src/backend/renderer/element/texture.rs +++ b/src/backend/renderer/element/texture.rs @@ -627,7 +627,7 @@ pub struct TextureRenderElement { location: Point, id: Id, renderer_id: usize, - texture: T, + pub(crate) texture: T, scale: i32, transform: Transform, alpha: f32, diff --git a/src/backend/renderer/gles/element.rs b/src/backend/renderer/gles/element.rs index 3d0c1537694c..4885a0118678 100644 --- a/src/backend/renderer/gles/element.rs +++ b/src/backend/renderer/gles/element.rs @@ -2,13 +2,13 @@ use crate::{ backend::renderer::{ - element::{Element, Id, Kind, RenderElement, UnderlyingStorage}, - utils::{CommitCounter, OpaqueRegions}, + element::{texture::TextureRenderElement, Element, Id, Kind, RenderElement, UnderlyingStorage}, + utils::{CommitCounter, DamageSet, OpaqueRegions}, }, - utils::{Buffer, Logical, Physical, Rectangle, Scale, Transform}, + utils::{Buffer, Logical, Physical, Point, Rectangle, Scale, Transform}, }; -use super::{GlesError, GlesFrame, GlesPixelProgram, GlesRenderer, Uniform}; +use super::{GlesError, GlesFrame, GlesPixelProgram, GlesRenderer, GlesTexProgram, GlesTexture, Uniform}; /// Render element for drawing with a gles2 pixel shader #[derive(Debug, Clone)] @@ -129,3 +129,93 @@ impl RenderElement for PixelShaderElement { None } } + +#[derive(Debug)] +pub struct TextureShaderElement { + inner: TextureRenderElement, + program: GlesTexProgram, + id: Id, + additional_uniforms: Vec>, +} + +impl TextureShaderElement { + pub fn new( + inner: TextureRenderElement, + program: GlesTexProgram, + additional_uniforms: Vec>, + ) -> Self { + Self { + inner, + program, + id: Id::new(), + + additional_uniforms: additional_uniforms.into_iter().map(|u| u.into_owned()).collect(), + } + } +} + +impl Element for TextureShaderElement { + fn id(&self) -> &Id { + &self.id + } + + fn current_commit(&self) -> CommitCounter { + self.inner.current_commit() + } + + fn geometry(&self, scale: Scale) -> Rectangle { + self.inner.geometry(scale) + } + + fn transform(&self) -> Transform { + self.inner.transform() + } + + fn src(&self) -> Rectangle { + self.inner.src() + } + + fn damage_since(&self, scale: Scale, commit: Option) -> DamageSet { + self.inner.damage_since(scale, commit) + } + + fn opaque_regions(&self, scale: Scale) -> OpaqueRegions { + self.inner.opaque_regions(scale) + } + + fn alpha(&self) -> f32 { + self.inner.alpha() + } + + fn kind(&self) -> Kind { + self.inner.kind() + } + + fn location(&self, scale: Scale) -> Point { + self.inner.location(scale) + } +} + +impl RenderElement for TextureShaderElement { + #[profiling::function] + fn draw( + &self, + frame: &mut GlesFrame<'_>, + src: Rectangle, + dst: Rectangle, + damage: &[Rectangle], + opaque_regions: &[Rectangle], + ) -> Result<(), GlesError> { + frame.render_texture_from_to( + &self.inner.texture, + src, + dst, + damage, + opaque_regions, + self.transform(), + self.alpha(), + Some(&self.program), + &self.additional_uniforms, + ) + } +} diff --git a/src/backend/renderer/glow.rs b/src/backend/renderer/glow.rs index cf30e6130226..3b1cd6bd0d5c 100644 --- a/src/backend/renderer/glow.rs +++ b/src/backend/renderer/glow.rs @@ -553,3 +553,21 @@ impl RenderElement for PixelShaderElement { RenderElement::::underlying_storage(self, renderer.borrow_mut()) } } + +impl RenderElement for TextureShaderElement { + #[profiling::function] + fn draw( + &self, + frame: &mut GlowFrame<'_>, + src: Rectangle, + dst: Rectangle, + damage: &[Rectangle], + opaque_regions: &[Rectangle], + ) -> Result<(), GlesError> { + RenderElement::::draw(self, frame.borrow_mut(), src, dst, damage, opaque_regions) + } + + fn underlying_storage(&self, renderer: &mut GlowRenderer) -> Option> { + RenderElement::::underlying_storage(self, renderer.borrow_mut()) + } +}