Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advanced rendering effects - filters, masks, box-shadows, gradients, and shaders #594

Merged
merged 80 commits into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
78db66c
Add effect sample
mikke89 Apr 29, 2023
05ec09b
Refactor: Move DecoratorInstancer into the Decorator files
mikke89 Apr 29, 2023
b6f70ff
Refactor: Style sheet type names
mikke89 Apr 29, 2023
607a8ce
Rectangle: Add getters for all corners and math rounding procedure
mikke89 Apr 30, 2023
679c615
Add number_percent parser and combined unit
mikke89 Apr 30, 2023
76b8556
ElementUtilities: Add procedure for determining element bounding box …
mikke89 Apr 30, 2023
1be3e86
Add render interface commands for layers and filters
mikke89 Apr 30, 2023
a5e3c7f
Add Filter class, to be used with the new 'filter' and 'backdrop-filt…
mikke89 Apr 29, 2023
bafca42
Add basic filters
mikke89 Apr 30, 2023
faae241
Take texture out of the compiled geometry
mikke89 Apr 30, 2023
f6230b2
Make elements with 'filter' and 'backdrop-filter' properties create a…
mikke89 Apr 30, 2023
a5ddc1a
Elements with 'filter' and 'backdrop-filter' properties now act as co…
mikke89 May 1, 2023
cb64ba4
Add a new visual test for stacking context paint order
mikke89 May 1, 2023
ebc8b65
Add filters to effect sample
mikke89 May 1, 2023
1d7b183
Add render layer and filter support to GL3 renderer
mikke89 May 1, 2023
edcb854
Improve visual tests automated test result output
mikke89 May 1, 2023
156d2bd
Fix backdrop-filter
mikke89 May 11, 2023
17246f5
Add blur filter, implement in GL3 renderer
mikke89 May 11, 2023
19281fd
Implement drop-shadow filter, integrate filter in GL3 renderer, and a…
mikke89 May 28, 2023
a30d3d5
Clarify Context::GetElementAtPoint
mikke89 Jun 1, 2023
3429285
Add geometry utility for creating background geometry on any target a…
mikke89 Jun 1, 2023
69ea397
Add clip mask to render interface, introduce render manager to keep t…
mikke89 Jun 2, 2023
4bfc80f
Debugger: Display the bounding box of the selected element
mikke89 Jun 3, 2023
655cd9a
Add support for the 'box-shadow' property
mikke89 Jun 3, 2023
72c816f
GL3 renderer: Fix assertion errors when minimizing the window
mikke89 Jun 4, 2023
2dba53e
GL3 renderer: Avoid sampling outside target region
mikke89 Jun 4, 2023
2338f2d
Add visual tests for drop shadow filter, and bounding box with ink ov…
mikke89 Jun 4, 2023
556607d
Replace gradient decorator syntax 'gradient(horizontal|vertical ...)'…
mikke89 Jun 6, 2023
17f1d95
Math: Normalize angle to positive values only
mikke89 Jun 6, 2023
0507e48
Improve PropertySpecification::ParsePropertyValues
mikke89 Jun 6, 2023
1525fd7
Add support for rendering geometry with shaders through the render in…
mikke89 Jun 7, 2023
b6efab1
Add 'linear-gradient' and 'repeating-linear-gradient' decorators
mikke89 Jun 7, 2023
c3622e6
Allow decorators to specify paint area [breaking change]
mikke89 Jun 7, 2023
81ae0c8
Visual tests: Highlight differences when comparing to previous captur…
mikke89 Jun 7, 2023
2f146f4
Add support for conic-gradient and radial-gradient, as well as their …
mikke89 Jun 8, 2023
5888497
Add interpolation support for angle values, support conic gradient an…
mikke89 Jun 8, 2023
5d52f71
Add shader decorator
mikke89 Jun 10, 2023
0471ce7
Add support for 'mask-image' property
mikke89 Jun 10, 2023
c6f550d
Add animation support for filters
mikke89 Jun 14, 2023
ecaaefa
Add 'mask-image' and 'backdrop-filter' animation tests
mikke89 Jun 15, 2023
aec3f2a
Fix backdrop-filter clipping to border background, add visual test
mikke89 Jun 30, 2023
ae8f2a4
Refactor: Move the box shadow generation into a separate file
mikke89 Jul 2, 2023
bdf5608
Use move semantics for texture callbacks
mikke89 Jul 2, 2023
9a00f2c
Unit tests: Make doctest string conversion functions inline
mikke89 Jul 15, 2023
59146e9
Update clang-format
mikke89 Jul 22, 2023
70bcdc7
Update SVG plugin for LunaSVG v2.3.2 and newer
mikke89 Jul 22, 2023
a064612
Avoid setting computed 'has_decorator' and similar when their pointer…
mikke89 Jul 22, 2023
641f8b5
Visual tests: Add alpha blending tests for renderer
mikke89 Jul 22, 2023
7ae3bb3
Use premultiplied alpha for textures submitted through the render int…
mikke89 Jul 22, 2023
c802aeb
Use premultiplied alpha for vertex colors
mikke89 Jul 22, 2023
2f80bdd
Backends: Handle premultiplied alpha for textures and vertices
mikke89 Jul 22, 2023
cfd963c
Fix minor GCC warning on Win32 backends
mikke89 Jul 23, 2023
f4414b8
Render interface: Mark optional functions for advanced effects
mikke89 Jul 23, 2023
a076be2
Postpone instancing named decorators until other decorators are insta…
mikke89 Aug 5, 2023
a452f26
Refactor Geometry and Texture, introduce unique render resources
mikke89 Sep 10, 2023
ba35525
Implement clip masks for the GL2 renderer
mikke89 Oct 8, 2023
90d2ef2
Introduce a basic implementation of a Span type
mikke89 Dec 25, 2023
3176c85
In demo sample, fix form submit animation not playing smoothly on pow…
mikke89 Dec 25, 2023
5faedc4
Refactor render interface: Require compiled geometry, use modern and …
mikke89 Dec 25, 2023
8b292e1
Add a render interface adapter from the old interface to the newly re…
mikke89 Dec 25, 2023
94fda35
GL3 renderer: Fix shader compilation on GLES, add GLSL line numbers
mikke89 Dec 26, 2023
cbeea43
Remove unused Log procedures for initialise and shutdown
mikke89 Dec 30, 2023
ac8e1f2
Use default log output also when there is no system interface installed
mikke89 Dec 30, 2023
5a27590
Redirect all print-like calls to our built-in logger
mikke89 Dec 30, 2023
6e1d487
Fix some situations where units were not shown in properties
mikke89 Feb 3, 2024
ff65107
Fix string conversion of ColorStopList and BoxShadowList, fixes #590
mikke89 Feb 3, 2024
7335eed
Ensure all invoked types define a string converter
mikke89 Feb 3, 2024
7b359d5
Use RCSS syntax for color-string conversion, format colors using hexa…
mikke89 Feb 3, 2024
144212b
Fix defender decorator from being rendered in invader samples
mikke89 Feb 3, 2024
b301702
Update CMake minimum to 3.5
mikke89 Feb 4, 2024
13b60d1
UnitTests: Add filter support to tests interface, test filter generat…
mikke89 Feb 5, 2024
7b9d865
Log warning if filter could not be compiled
mikke89 Feb 4, 2024
8dfba05
GL3 renderer: Add color write mask to OpenGL state backup
mikke89 Feb 4, 2024
742bbba
Add mask-image to absolute positioning containing block
mikke89 Feb 5, 2024
c42d729
Render interface naming: Remove compiled from release functions
mikke89 Feb 5, 2024
011b3c1
Fix file textures not being reloaded after release
mikke89 Mar 4, 2024
b470b2b
Make backdrop-filter be affected by any filter and mask-image applied…
mikke89 Mar 24, 2024
e96b950
Render interface: Make layer compositing a separate function instead …
mikke89 Mar 25, 2024
c93dbc0
Fix bad rendering in Emscripten, add sample assets as link dependencies
mikke89 Mar 26, 2024
37cf4d3
Refactor ElementDecoration to ElementEffects
mikke89 Mar 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Render interface: Make layer compositing a separate function instead …
…of being a part of layer pop

The purpose of each function should now be more clear. With this change, we can now composite two arbitrary layers which simplifies some use cases of compositing.

This commit also uses the changed interface to fix some artifacts when rendering back-drop filter blur combined with plain filter blur.
  • Loading branch information
mikke89 committed Mar 25, 2024
commit e96b950373f5cfd47f478ad48be7b82e7d3eb3a1
101 changes: 39 additions & 62 deletions Backends/RmlUi_Renderer_GL3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1736,9 +1736,9 @@ void RenderInterface_GL3::ReleaseShader(Rml::CompiledShaderHandle shader_handle)
delete reinterpret_cast<CompiledShader*>(shader_handle);
}

void RenderInterface_GL3::BlitTopLayerToPostprocessPrimary()
void RenderInterface_GL3::BlitLayerToPostprocessPrimary(Rml::LayerHandle layer_handle)
{
const Gfx::FramebufferData& source = render_layers.GetTopLayer();
const Gfx::FramebufferData& source = render_layers.GetLayer(layer_handle);
const Gfx::FramebufferData& destination = render_layers.GetPostprocessPrimary();
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destination.framebuffer);
Expand Down Expand Up @@ -1873,57 +1873,31 @@ void RenderInterface_GL3::RenderFilters(Rml::Span<const Rml::CompiledFilterHandl
Gfx::CheckGLError("RenderFilter");
}

void RenderInterface_GL3::PushLayer(Rml::LayerFill layer_fill)
Rml::LayerHandle RenderInterface_GL3::PushLayer()
{
const Gfx::FramebufferData source = render_layers.GetTopLayer();
const Rml::LayerHandle layer_handle = render_layers.PushLayer();

if (layer_fill == Rml::LayerFill::Link)
render_layers.PushLayerClone();
else
render_layers.PushLayer();
glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetLayer(layer_handle).framebuffer);
glClear(GL_COLOR_BUFFER_BIT);

if (layer_fill == Rml::LayerFill::Copy)
{
const Gfx::FramebufferData& destination = render_layers.GetTopLayer();
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destination.framebuffer);
// Note that the blit region will be clipped by any active scissor region.
glBlitFramebuffer(0, 0, source.width, source.height, 0, 0, destination.width, destination.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, destination.framebuffer);
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetTopLayer().framebuffer);
if (layer_fill == Rml::LayerFill::Clear)
glClear(GL_COLOR_BUFFER_BIT);
}
return layer_handle;
}

void RenderInterface_GL3::PopLayer(Rml::BlendMode blend_mode, Rml::Span<const Rml::CompiledFilterHandle> filters)
void RenderInterface_GL3::CompositeLayers(Rml::LayerHandle source_handle, Rml::LayerHandle destination_handle, Rml::BlendMode blend_mode,
Rml::Span<const Rml::CompiledFilterHandle> filters)
{
using Rml::BlendMode;

if (blend_mode == BlendMode::Discard)
{
RMLUI_ASSERT(filters.empty());
render_layers.PopLayer();
glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetTopLayer().framebuffer);
return;
}

// Blit stack to filter rendering buffer. Do this regardless of whether we actually have any filters to be applied,
// because we need to resolve the multi-sampled framebuffer in any case.
// Blit source layer to postprocessing buffer. Do this regardless of whether we actually have any filters to be
// applied, because we need to resolve the multi-sampled framebuffer in any case.
// @performance If we have BlendMode::Replace and no filters or mask then we can just blit directly to the destination.
BlitTopLayerToPostprocessPrimary();
BlitLayerToPostprocessPrimary(source_handle);

// Render the filters, the PostprocessPrimary framebuffer is used for both input and output.
RenderFilters(filters);

// Pop the active layer, thereby activating the beneath layer.
render_layers.PopLayer();

// Render to the activated layer. Apply any mask if active.
glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetTopLayer().framebuffer);
// Render to the destination layer.
glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetLayer(destination_handle).framebuffer);
Gfx::BindTexture(render_layers.GetPostprocessPrimary());

UseProgram(ProgramId::Passthrough);
Expand All @@ -1936,7 +1910,16 @@ void RenderInterface_GL3::PopLayer(Rml::BlendMode blend_mode, Rml::Span<const Rm
if (blend_mode == BlendMode::Replace)
glEnable(GL_BLEND);

Gfx::CheckGLError("PopLayer");
if (destination_handle != render_layers.GetTopLayerHandle())
glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetTopLayer().framebuffer);

Gfx::CheckGLError("CompositeLayers");
}

void RenderInterface_GL3::PopLayer()
{
render_layers.PopLayer();
glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetTopLayer().framebuffer);
}

Rml::TextureHandle RenderInterface_GL3::SaveLayerAsTexture(Rml::Vector2i dimensions)
Expand All @@ -1945,7 +1928,7 @@ Rml::TextureHandle RenderInterface_GL3::SaveLayerAsTexture(Rml::Vector2i dimensi
if (!render_texture)
return {};

BlitTopLayerToPostprocessPrimary();
BlitLayerToPostprocessPrimary(render_layers.GetTopLayerHandle());

RMLUI_ASSERT(scissor_state.Valid() && render_texture);
const Rml::Rectanglei initial_scissor_state = scissor_state;
Expand Down Expand Up @@ -1982,7 +1965,7 @@ Rml::TextureHandle RenderInterface_GL3::SaveLayerAsTexture(Rml::Vector2i dimensi

Rml::CompiledFilterHandle RenderInterface_GL3::SaveLayerAsMaskImage()
{
BlitTopLayerToPostprocessPrimary();
BlitLayerToPostprocessPrimary(render_layers.GetTopLayerHandle());

const Gfx::FramebufferData& source = render_layers.GetPostprocessPrimary();
const Gfx::FramebufferData& destination = render_layers.GetBlendMask();
Expand Down Expand Up @@ -2045,7 +2028,7 @@ RenderInterface_GL3::RenderLayerStack::~RenderLayerStack()
DestroyFramebuffers();
}

void RenderInterface_GL3::RenderLayerStack::PushLayer()
Rml::LayerHandle RenderInterface_GL3::RenderLayerStack::PushLayer()
{
RMLUI_ASSERT(layers_size <= (int)fb_layers.size());

Expand All @@ -2059,29 +2042,30 @@ void RenderInterface_GL3::RenderLayerStack::PushLayer()
}

layers_size += 1;
}

void RenderInterface_GL3::RenderLayerStack::PushLayerClone()
{
RMLUI_ASSERT(layers_size > 0);
fb_layers.insert(fb_layers.begin() + layers_size, Gfx::FramebufferData{fb_layers[layers_size - 1]});
layers_size += 1;
return GetTopLayerHandle();
}

void RenderInterface_GL3::RenderLayerStack::PopLayer()
{
RMLUI_ASSERT(layers_size > 0);
layers_size -= 1;
}

// Only cloned framebuffers are removed. Other framebuffers remain for later re-use.
if (IsCloneOfBelow(layers_size))
fb_layers.erase(fb_layers.begin() + layers_size);
const Gfx::FramebufferData& RenderInterface_GL3::RenderLayerStack::GetLayer(Rml::LayerHandle layer) const
{
RMLUI_ASSERT((size_t)layer < (size_t)layers_size);
return fb_layers[layer];
}

const Gfx::FramebufferData& RenderInterface_GL3::RenderLayerStack::GetTopLayer() const
{
return GetLayer(GetTopLayerHandle());
}

Rml::LayerHandle RenderInterface_GL3::RenderLayerStack::GetTopLayerHandle() const
{
RMLUI_ASSERT(layers_size > 0);
return fb_layers[layers_size - 1];
return static_cast<Rml::LayerHandle>(layers_size - 1);
}

void RenderInterface_GL3::RenderLayerStack::SwapPostprocessPrimarySecondary()
Expand Down Expand Up @@ -2123,13 +2107,6 @@ void RenderInterface_GL3::RenderLayerStack::DestroyFramebuffers()
Gfx::DestroyFramebuffer(fb);
}

bool RenderInterface_GL3::RenderLayerStack::IsCloneOfBelow(int layer_index) const
{
const bool result =
(layer_index >= 1 && layer_index < (int)fb_layers.size() && fb_layers[layer_index].framebuffer == fb_layers[layer_index - 1].framebuffer);
return result;
}

const Gfx::FramebufferData& RenderInterface_GL3::RenderLayerStack::EnsureFramebufferPostprocess(int index)
{
RMLUI_ASSERT(index < (int)fb_postprocess.size())
Expand Down
16 changes: 8 additions & 8 deletions Backends/RmlUi_Renderer_GL3.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ class RenderInterface_GL3 : public Rml::RenderInterface {

void SetTransform(const Rml::Matrix4f* transform) override;

void PushLayer(Rml::LayerFill layer_fill) override;
void PopLayer(Rml::BlendMode blend_mode, Rml::Span<const Rml::CompiledFilterHandle> filters) override;
Rml::LayerHandle PushLayer() override;
void CompositeLayers(Rml::LayerHandle source, Rml::LayerHandle destination, Rml::BlendMode blend_mode,
Rml::Span<const Rml::CompiledFilterHandle> filters) override;
void PopLayer() override;

Rml::TextureHandle SaveLayerAsTexture(Rml::Vector2i dimensions) override;

Expand All @@ -103,7 +105,7 @@ class RenderInterface_GL3 : public Rml::RenderInterface {
int GetUniformLocation(UniformId uniform_id) const;
void SubmitTransformUniform(Rml::Vector2f translation);

void BlitTopLayerToPostprocessPrimary();
void BlitLayerToPostprocessPrimary(Rml::LayerHandle layer_handle);
void RenderFilters(Rml::Span<const Rml::CompiledFilterHandle> filter_handles);

void SetScissor(Rml::Rectanglei region, bool vertically_flip = false);
Expand Down Expand Up @@ -144,15 +146,14 @@ class RenderInterface_GL3 : public Rml::RenderInterface {
~RenderLayerStack();

// Push a new layer. All references to previously retrieved layers are invalidated.
void PushLayer();

// Push a clone of the active layer. All references to previously retrieved layers are invalidated.
void PushLayerClone();
Rml::LayerHandle PushLayer();

// Pop the top layer. All references to previously retrieved layers are invalidated.
void PopLayer();

const Gfx::FramebufferData& GetLayer(Rml::LayerHandle layer) const;
const Gfx::FramebufferData& GetTopLayer() const;
Rml::LayerHandle GetTopLayerHandle() const;

const Gfx::FramebufferData& GetPostprocessPrimary() { return EnsureFramebufferPostprocess(0); }
const Gfx::FramebufferData& GetPostprocessSecondary() { return EnsureFramebufferPostprocess(1); }
Expand All @@ -166,7 +167,6 @@ class RenderInterface_GL3 : public Rml::RenderInterface {

private:
void DestroyFramebuffers();
bool IsCloneOfBelow(int layer_index) const;
const Gfx::FramebufferData& EnsureFramebufferPostprocess(int index);

int width = 0, height = 0;
Expand Down
32 changes: 16 additions & 16 deletions Include/RmlUi/Core/RenderInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,9 @@ enum class ClipMaskOperation {
SetInverse, // Set the clip mask to the area *outside* the rendered geometry, clearing any existing clip mask.
Intersect, // Intersect the clip mask with the area of the rendered geometry.
};
enum class LayerFill {
None, // No operation necessary, does not care about the layer color.
Clear, // Clear the layer to transparent black.
Copy, // Copy the color data from the previous layer.
Link, // Link the color data with the previous layer.
};
enum class BlendMode {
Blend, // Normal alpha blending.
Replace, // Replace the destination colors from the source.
Discard, // Leave the destination colors unaltered.
};

/**
Expand Down Expand Up @@ -119,7 +112,8 @@ class RMLUICORE_API RenderInterface : public NonCopyMoveable {
/// @param[in] geometry The compiled geometry to render.
/// @param[in] translation The translation to apply to the geometry.
/// @note When enabled, the clip mask should hide any rendered contents outside the area of the mask.
/// @note The clip mask applies to all other functions that render with a geometry handle, and only those.
/// @note The clip mask applies exclusively to all other functions that render with a geometry handle, in addition
/// to the layer compositing function while rendering to its destination.
virtual void RenderToClipMask(ClipMaskOperation operation, CompiledGeometryHandle geometry, Vector2f translation);

/// Called by RmlUi when it wants the renderer to use a new transform matrix.
Expand All @@ -129,21 +123,27 @@ class RMLUICORE_API RenderInterface : public NonCopyMoveable {
/// @note The transform applies to all functions that render with a geometry handle, and only those.
virtual void SetTransform(const Matrix4f* transform);

/// Called by RmlUi when it wants to push a new layer onto the render stack.
/// @param[in] layer_fill Specifies how the color data of the new layer should be filled.
virtual void PushLayer(LayerFill layer_fill);
/// Called by RmlUi when it wants to pop the render layer stack, after applying filters to the top layer and blending it into the layer below.
/// @param[in] blend_mode The mode used to blend the top layer into the one below.
/// @param[in] filters A list of compiled filters which should be applied to the top layer before blending.
virtual void PopLayer(BlendMode blend_mode, Span<const CompiledFilterHandle> filters);
/// Called by RmlUi when it wants to push a new layer onto the render stack, setting it as the new render target.
/// @return An application-specified handle representing the new layer. The value 'zero' is reserved for the initial base layer.
/// @note The new layer should be initialized to transparent black within the current scissor region.
virtual LayerHandle PushLayer();
/// Composite two layers with the given blend mode and apply filters.
/// @param[in] source The source layer.
/// @param[in] destination The destination layer.
/// @param[in] blend_mode The mode used to blend the source layer onto the destination layer.
/// @param[in] filters A list of compiled filters which should be applied before blending.
/// @note Source and destination can reference the same layer.
virtual void CompositeLayers(LayerHandle source, LayerHandle destination, BlendMode blend_mode, Span<const CompiledFilterHandle> filters);
/// Called by RmlUi when it wants to pop the render layer stack, setting the new top layer as the render target.
virtual void PopLayer();

/// Called by RmlUi when it wants to store the current layer as a new texture to be rendered later with geometry.
/// @param[in] dimensions The dimensions of the texture, to be copied from the top-left part of the viewport.
/// @return An application-specified handle to the new texture.
virtual TextureHandle SaveLayerAsTexture(Vector2i dimensions);

/// Called by RmlUi when it wants to store the current layer as a mask image, to be applied later as a filter.
/// @return An application-specified handle to a new filter representng the stored mask image.
/// @return An application-specified handle to a new filter representing the stored mask image.
virtual CompiledFilterHandle SaveLayerAsMaskImage();

/// Called by RmlUi when it wants to compile a new filter.
Expand Down
10 changes: 8 additions & 2 deletions Include/RmlUi/Core/RenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,12 @@ class RMLUICORE_API RenderManager : NonCopyMoveable {
CompiledFilter CompileFilter(const String& name, const Dictionary& parameters);
CompiledShader CompileShader(const String& name, const Dictionary& parameters);

void PushLayer(LayerFill layer_fill);
void PopLayer(BlendMode blend_mode, Span<const CompiledFilterHandle> filters);
LayerHandle PushLayer();
void CompositeLayers(LayerHandle source, LayerHandle destination, BlendMode blend_mode, Span<const CompiledFilterHandle> filters);
void PopLayer();

LayerHandle GetTopLayer() const;
LayerHandle GetNextLayer() const;

CompiledFilter SaveLayerAsMaskImage();

Expand Down Expand Up @@ -142,6 +146,8 @@ class RMLUICORE_API RenderManager : NonCopyMoveable {
RenderState state;
Vector2i viewport_dimensions;

Vector<LayerHandle> render_stack;

friend class RenderManagerAccess;
};

Expand Down
5 changes: 3 additions & 2 deletions Include/RmlUi/Core/StableVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ namespace Rml {
A vector-like container that returns stable indices to refer to entries.

The indices are only invalidated when the element is erased. Pointers on the other hand are invalidated just like for a
vector. The container is implemented as a vector with a separate bit mask to track free slots. For simplicity, freed
slots are simply replaced with value-initialized elements.
vector. The container is implemented as a vector with a separate bit mask to track free slots.

@note For simplicity, freed slots are simply replaced with value-initialized elements instead of being destroyed.
*/
template <typename T>
class StableVector {
Expand Down
1 change: 1 addition & 0 deletions Include/RmlUi/Core/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ using CompiledShaderHandle = uintptr_t;
using DecoratorDataHandle = uintptr_t;
using FontFaceHandle = uintptr_t;
using FontEffectsHandle = uintptr_t;
using LayerHandle = uintptr_t;

using ElementPtr = UniqueReleaserPtr<Element>;
using ContextPtr = UniqueReleaserPtr<Context>;
Expand Down
Loading
Loading