Bläddra i källkod

Remove dimensions argument from render interface `SaveLayerAsTexture`

Instead, let the active scissor bounds define the region the texture should be extracted from, and thereby also its size.
Michael Ragazzon 1 år sedan
förälder
incheckning
9bfb8d7c60

+ 6 - 7
Backends/RmlUi_Renderer_GL3.cpp

@@ -1936,16 +1936,17 @@ void RenderInterface_GL3::PopLayer()
 	glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetTopLayer().framebuffer);
 }
 
-Rml::TextureHandle RenderInterface_GL3::SaveLayerAsTexture(Rml::Vector2i dimensions)
+Rml::TextureHandle RenderInterface_GL3::SaveLayerAsTexture()
 {
-	Rml::TextureHandle render_texture = GenerateTexture({}, dimensions);
+	RMLUI_ASSERT(scissor_state.Valid());
+	const Rml::Rectanglei bounds = scissor_state;
+
+	Rml::TextureHandle render_texture = GenerateTexture({}, bounds.Size());
 	if (!render_texture)
 		return {};
 
 	BlitLayerToPostprocessPrimary(render_layers.GetTopLayerHandle());
 
-	RMLUI_ASSERT(scissor_state.Valid() && render_texture);
-	const Rml::Rectanglei initial_scissor_state = scissor_state;
 	EnableScissorRegion(false);
 
 	const Gfx::FramebufferData& source = render_layers.GetPostprocessPrimary();
@@ -1953,8 +1954,6 @@ Rml::TextureHandle RenderInterface_GL3::SaveLayerAsTexture(Rml::Vector2i dimensi
 	glBindFramebuffer(GL_READ_FRAMEBUFFER, source.framebuffer);
 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destination.framebuffer);
 
-	Rml::Rectanglei bounds = initial_scissor_state;
-
 	// Flip the image vertically, as that convention is used for textures, and move to origin.
 	glBlitFramebuffer(                                  //
 		bounds.Left(), source.height - bounds.Bottom(), // src0
@@ -1970,7 +1969,7 @@ Rml::TextureHandle RenderInterface_GL3::SaveLayerAsTexture(Rml::Vector2i dimensi
 	glBindFramebuffer(GL_READ_FRAMEBUFFER, texture_source.framebuffer);
 	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bounds.Width(), bounds.Height());
 
-	SetScissor(initial_scissor_state);
+	SetScissor(bounds);
 	glBindFramebuffer(GL_FRAMEBUFFER, render_layers.GetTopLayer().framebuffer);
 	Gfx::CheckGLError("SaveLayerAsTexture");
 

+ 1 - 1
Backends/RmlUi_Renderer_GL3.h

@@ -83,7 +83,7 @@ public:
 		Rml::Span<const Rml::CompiledFilterHandle> filters) override;
 	void PopLayer() override;
 
-	Rml::TextureHandle SaveLayerAsTexture(Rml::Vector2i dimensions) override;
+	Rml::TextureHandle SaveLayerAsTexture() override;
 
 	Rml::CompiledFilterHandle SaveLayerAsMaskImage() override;
 

+ 2 - 2
Include/RmlUi/Core/CallbackTexture.h

@@ -79,8 +79,8 @@ public:
 	bool GenerateTexture(Span<const byte> source, Vector2i dimensions) const;
 
 	/// Store the current layer as a texture, so that it can be rendered with geometry later.
-	/// @param[in] dimensions The dimensions of the resulting texture, which will be copied from the top-left part of the active layer.
-	void SaveLayerAsTexture(Vector2i dimensions) const;
+	/// @note The texture will be extracted using the bounds defined by the active scissor region, thereby matching its size.
+	void SaveLayerAsTexture() const;
 
 	RenderManager& GetRenderManager() const;
 

+ 2 - 2
Include/RmlUi/Core/RenderInterface.h

@@ -138,9 +138,9 @@ public:
 	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);
+	/// @note The texture should be extracted using the bounds defined by the active scissor region, thereby matching its size.
+	virtual TextureHandle SaveLayerAsTexture();
 
 	/// 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 representing the stored mask image.

+ 1 - 0
Include/RmlUi/Core/RenderManager.h

@@ -82,6 +82,7 @@ public:
 
 	void DisableScissorRegion();
 	void SetScissorRegion(Rectanglei region);
+	Rectanglei GetScissorRegion() const;
 
 	void DisableClipMask();
 	void SetClipMask(ClipMaskGeometryList clip_elements);

+ 12 - 6
Source/Core/CallbackTexture.cpp

@@ -47,9 +47,7 @@ Rml::CallbackTexture::operator Texture() const
 }
 
 CallbackTextureInterface::CallbackTextureInterface(RenderManager& render_manager, RenderInterface& render_interface, TextureHandle& texture_handle,
-	Vector2i& dimensions) :
-	render_manager(render_manager),
-	render_interface(render_interface), texture_handle(texture_handle), dimensions(dimensions)
+	Vector2i& dimensions) : render_manager(render_manager), render_interface(render_interface), texture_handle(texture_handle), dimensions(dimensions)
 {}
 
 bool CallbackTextureInterface::GenerateTexture(Span<const byte> source, Vector2i new_dimensions) const
@@ -65,16 +63,24 @@ bool CallbackTextureInterface::GenerateTexture(Span<const byte> source, Vector2i
 	return texture_handle != TextureHandle{};
 }
 
-void CallbackTextureInterface::SaveLayerAsTexture(Vector2i new_dimensions) const
+void CallbackTextureInterface::SaveLayerAsTexture() const
 {
 	if (texture_handle)
 	{
 		RMLUI_ERRORMSG("Texture already set");
 		return;
 	}
-	texture_handle = render_interface.SaveLayerAsTexture(new_dimensions);
+
+	const Rectanglei region = render_manager.GetScissorRegion();
+	if (!region.Valid())
+	{
+		RMLUI_ERRORMSG("Save layer as texture requires a scissor region to be set first");
+		return;
+	}
+
+	texture_handle = render_interface.SaveLayerAsTexture();
 	if (texture_handle)
-		dimensions = new_dimensions;
+		dimensions = region.Size();
 }
 
 RenderManager& CallbackTextureInterface::GetRenderManager() const

+ 2 - 2
Source/Core/ElementEffects.cpp

@@ -233,7 +233,7 @@ void ElementEffects::RenderEffects(RenderStage render_stage)
 	if (!render_manager)
 		return;
 
-	Rectanglei initial_scissor_region = render_manager->GetState().scissor_region;
+	Rectanglei initial_scissor_region = render_manager->GetScissorRegion();
 
 	auto ApplyClippingRegion = [this, &render_manager](PropertyId filter_id) {
 		RMLUI_ASSERT(filter_id == PropertyId::Filter || filter_id == PropertyId::BackdropFilter);
@@ -255,7 +255,7 @@ void ElementEffects::RenderEffects(RenderStage render_stage)
 		Math::ExpandToPixelGrid(filter_region);
 
 		Rectanglei scissor_region = Rectanglei(filter_region);
-		scissor_region.IntersectIfValid(render_manager->GetState().scissor_region);
+		scissor_region.IntersectIfValid(render_manager->GetScissorRegion());
 		render_manager->SetScissorRegion(scissor_region);
 	};
 	auto ApplyScissorRegionForBackdrop = [this, &render_manager]() {

+ 1 - 1
Source/Core/ElementText.cpp

@@ -146,7 +146,7 @@ void ElementText::OnRender()
 
 	// Do a visibility test against the scissor region to avoid unnecessary render calls. Instead of handling
 	// culling in complicated transform cases, for simplicity we always proceed to render if one is detected.
-	Rectanglei scissor_region = render_manager.GetState().scissor_region;
+	Rectanglei scissor_region = render_manager.GetScissorRegion();
 	if (!scissor_region.Valid())
 		scissor_region = Rectanglei::FromSize(render_manager.GetViewport());
 

+ 2 - 1
Source/Core/GeometryBoxShadow.cpp

@@ -210,7 +210,8 @@ void GeometryBoxShadow::Generate(Geometry& out_shadow_geometry, CallbackTexture&
 			}
 		}
 
-		texture_interface.SaveLayerAsTexture(texture_dimensions);
+		RMLUI_ASSERT(render_manager.GetScissorRegion() == Rectanglei::FromSize(texture_dimensions))
+		texture_interface.SaveLayerAsTexture();
 
 		render_manager.PopLayer();
 		render_manager.SetState(initial_render_state);

+ 1 - 1
Source/Core/RenderInterface.cpp

@@ -62,7 +62,7 @@ void RenderInterface::CompositeLayers(LayerHandle /*source*/, LayerHandle /*dest
 
 void RenderInterface::PopLayer() {}
 
-TextureHandle RenderInterface::SaveLayerAsTexture(Vector2i /*dimensions*/)
+TextureHandle RenderInterface::SaveLayerAsTexture()
 {
 	return TextureHandle{};
 }

+ 5 - 0
Source/Core/RenderManager.cpp

@@ -134,6 +134,11 @@ void RenderManager::SetScissorRegion(Rectanglei new_region)
 	state.scissor_region = new_region;
 }
 
+Rectanglei RenderManager::GetScissorRegion() const
+{
+	return state.scissor_region;
+}
+
 void RenderManager::DisableClipMask()
 {
 	if (!state.clip_mask_list.empty())