Skip to content

Commit

Permalink
gles: Define a TextureShaderElement
Browse files Browse the repository at this point in the history
`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.
  • Loading branch information
ids1024 committed Oct 8, 2024
1 parent df79eeb commit d5a3772
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/backend/renderer/element/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ pub struct TextureRenderElement<T> {
location: Point<f64, Physical>,
id: Id,
renderer_id: usize,
texture: T,
pub(crate) texture: T,
scale: i32,
transform: Transform,
alpha: f32,
Expand Down
102 changes: 98 additions & 4 deletions src/backend/renderer/gles/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -129,3 +129,97 @@ impl RenderElement<GlesRenderer> for PixelShaderElement {
None
}
}

/// Render element for drawing with a gles2 texture shader
#[derive(Debug)]
pub struct TextureShaderElement {
inner: TextureRenderElement<GlesTexture>,
program: GlesTexProgram,
id: Id,
additional_uniforms: Vec<Uniform<'static>>,
}

impl TextureShaderElement {
/// Create a new [`TextureShaderElement`] from a [`TextureRenderElement`] and a
/// [`GlesTexProgram`], which can be constructed using
/// [`GlesRenderer::compile_custom_texture_shader`]
pub fn new(
inner: TextureRenderElement<GlesTexture>,
program: GlesTexProgram,
additional_uniforms: Vec<Uniform<'_>>,
) -> 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<f64>) -> Rectangle<i32, Physical> {
self.inner.geometry(scale)
}

fn transform(&self) -> Transform {
self.inner.transform()
}

fn src(&self) -> Rectangle<f64, Buffer> {
self.inner.src()
}

fn damage_since(&self, scale: Scale<f64>, commit: Option<CommitCounter>) -> DamageSet<i32, Physical> {
self.inner.damage_since(scale, commit)
}

fn opaque_regions(&self, scale: Scale<f64>) -> OpaqueRegions<i32, Physical> {
self.inner.opaque_regions(scale)
}

fn alpha(&self) -> f32 {
self.inner.alpha()
}

fn kind(&self) -> Kind {
self.inner.kind()
}

fn location(&self, scale: Scale<f64>) -> Point<i32, Physical> {
self.inner.location(scale)
}
}

impl RenderElement<GlesRenderer> for TextureShaderElement {
#[profiling::function]
fn draw(
&self,
frame: &mut GlesFrame<'_>,
src: Rectangle<f64, Buffer>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>],
opaque_regions: &[Rectangle<i32, Physical>],
) -> 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,
)
}
}
18 changes: 18 additions & 0 deletions src/backend/renderer/glow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,3 +553,21 @@ impl RenderElement<GlowRenderer> for PixelShaderElement {
RenderElement::<GlesRenderer>::underlying_storage(self, renderer.borrow_mut())
}
}

impl RenderElement<GlowRenderer> for TextureShaderElement {
#[profiling::function]
fn draw(
&self,
frame: &mut GlowFrame<'_>,
src: Rectangle<f64, BufferCoord>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>],
opaque_regions: &[Rectangle<i32, Physical>],
) -> Result<(), GlesError> {
RenderElement::<GlesRenderer>::draw(self, frame.borrow_mut(), src, dst, damage, opaque_regions)
}

fn underlying_storage(&self, renderer: &mut GlowRenderer) -> Option<UnderlyingStorage<'_>> {
RenderElement::<GlesRenderer>::underlying_storage(self, renderer.borrow_mut())
}
}

0 comments on commit d5a3772

Please sign in to comment.