From 5faedc427b42c1b2162dd41d60f483bef4af310e Mon Sep 17 00:00:00 2001 From: Michael Ragazzon Date: Mon, 25 Dec 2023 21:25:13 +0100 Subject: [PATCH] Refactor render interface: Require compiled geometry, use modern and safer types [breaking change] All geometry now requires compiling, the immediate geometry rendering call is removed for the following reasons: 1. Compiled geometry is required to use any of the new rendering features, including clip mask and shaders. 2. It simplifies the render interface, by removing a function that essentially provided a duplicate feature set. 3. This change enables us to make a clear distinction between required and optional functions. All required functions are now abstract, while optional functions are not. With recent changes, migrating from the immediate render function to using the compiled geometry functions, should be much less effort. Now the pointers to the geometry data (vertices and indices) are guaranteed to be available and immutable until the same geometry is released. Thus, users can simply store the views to this data, and reuse that during rendering. The signatures of several functions are changed: - The Span type is now used to represent contiguous data for improved usability and safety. - Texture load and generate now return the texture handle directly, to be consistent with the way geometry is compiled. The value zero is used to represent an empty texture, like before. - The scissor region now takes a Rectangle type for improved ergonomics. This is a breaking change for all users, and requires some minor adaptation in existing render interfaces. The changes to the backend renderers in this commit can be used as a reference for the change. --- Backends/RmlUi_Backend_SDL_GL2.cpp | 31 +++---- Backends/RmlUi_Backend_SDL_GL3.cpp | 21 ++--- Backends/RmlUi_Backend_SFML_GL2.cpp | 18 ++-- Backends/RmlUi_Renderer_GL2.cpp | 50 ++++------- Backends/RmlUi_Renderer_GL2.h | 24 +++-- Backends/RmlUi_Renderer_GL3.cpp | 68 ++++++-------- Backends/RmlUi_Renderer_GL3.h | 21 ++--- Backends/RmlUi_Renderer_SDL.cpp | 60 ++++++++----- Backends/RmlUi_Renderer_SDL.h | 20 +++-- Backends/RmlUi_Renderer_VK.cpp | 87 ++++++++---------- Backends/RmlUi_Renderer_VK.h | 29 +++--- Include/RmlUi/Core/CallbackTexture.h | 2 +- Include/RmlUi/Core/Rectangle.h | 6 ++ Include/RmlUi/Core/RenderInterface.h | 88 ++++++++----------- Include/RmlUi/Core/RenderManager.h | 2 +- Source/Core/CallbackTexture.cpp | 10 +-- .../FontFaceHandleDefault.cpp | 2 +- .../FontEngineDefault/FontFaceHandleDefault.h | 2 +- .../Core/FontEngineDefault/FontFaceLayer.cpp | 10 +-- Source/Core/FontEngineDefault/FontFaceLayer.h | 4 +- Source/Core/RenderInterface.cpp | 23 +---- Source/Core/RenderManager.cpp | 16 ++-- Source/Core/TextureDatabase.cpp | 3 +- Source/Core/TextureLayoutTexture.cpp | 9 +- Source/Core/TextureLayoutTexture.h | 2 +- Source/Lottie/ElementLottie.cpp | 2 +- Source/SVG/ElementSVG.cpp | 8 +- Tests/Source/Common/TestsInterface.cpp | 47 +++++----- Tests/Source/Common/TestsInterface.h | 40 ++++----- Tests/Source/Common/TestsShell.cpp | 15 ++-- Tests/Source/UnitTests/Core.cpp | 13 ++- Tests/Source/VisualTests/CaptureScreen.cpp | 29 +++--- Tests/Source/VisualTests/CaptureScreen.h | 1 + Tests/Source/VisualTests/TestNavigator.cpp | 11 ++- 34 files changed, 351 insertions(+), 423 deletions(-) diff --git a/Backends/RmlUi_Backend_SDL_GL2.cpp b/Backends/RmlUi_Backend_SDL_GL2.cpp index 8d84125f3..15277089d 100644 --- a/Backends/RmlUi_Backend_SDL_GL2.cpp +++ b/Backends/RmlUi_Backend_SDL_GL2.cpp @@ -52,7 +52,7 @@ class RenderInterface_GL2_SDL : public RenderInterface_GL2 { public: RenderInterface_GL2_SDL(SDL_Renderer* renderer) : renderer(renderer) {} - void RenderCompiledGeometry(Rml::CompiledGeometryHandle handle, const Rml::Vector2f& translation, Rml::TextureHandle texture) override + void RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) override { SDL_Texture* sdl_texture = (SDL_Texture*)texture; if (sdl_texture) @@ -61,18 +61,18 @@ class RenderInterface_GL2_SDL : public RenderInterface_GL2 { texture = RenderInterface_GL2::TextureEnableWithoutBinding; } - RenderInterface_GL2::RenderCompiledGeometry(handle, translation, texture); + RenderInterface_GL2::RenderGeometry(handle, translation, texture); if (sdl_texture) SDL_GL_UnbindTexture(sdl_texture); } - bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override + Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) override { Rml::FileInterface* file_interface = Rml::GetFileInterface(); Rml::FileHandle file_handle = file_interface->Open(source); if (!file_handle) - return false; + return {}; file_interface->Seek(file_handle, 0, SEEK_END); const size_t buffer_size = file_interface->Tell(file_handle); @@ -88,7 +88,9 @@ class RenderInterface_GL2_SDL : public RenderInterface_GL2 { SDL_Surface* surface = IMG_LoadTyped_RW(SDL_RWFromMem(buffer.get(), int(buffer_size)), 1, extension.c_str()); if (!surface) - return false; + return {}; + + texture_dimensions = {surface->w, surface->h}; if (surface->format->format != SDL_PIXELFORMAT_RGBA32 && surface->format->format != SDL_PIXELFORMAT_BGRA32) { @@ -98,7 +100,7 @@ class RenderInterface_GL2_SDL : public RenderInterface_GL2 { SDL_FreeSurface(surface); if (!converted_surface) - return false; + return {}; surface = converted_surface; } @@ -113,18 +115,12 @@ class RenderInterface_GL2_SDL : public RenderInterface_GL2 { } SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); - - texture_dimensions = Rml::Vector2i(surface->w, surface->h); - texture_handle = (Rml::TextureHandle)texture; SDL_FreeSurface(surface); - if (!texture) - return false; - - return true; + return (Rml::TextureHandle)texture; } - bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override + Rml::TextureHandle GenerateTexture(Rml::Span source, Rml::Vector2i source_dimensions) override { #if SDL_BYTEORDER == SDL_BIG_ENDIAN Uint32 rmask = 0xff000000; @@ -138,13 +134,12 @@ class RenderInterface_GL2_SDL : public RenderInterface_GL2 { Uint32 amask = 0xff000000; #endif - SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)source, source_dimensions.x, source_dimensions.y, 32, source_dimensions.x * 4, rmask, - gmask, bmask, amask); + SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)source.data(), source_dimensions.x, source_dimensions.y, 32, source_dimensions.x * 4, + rmask, gmask, bmask, amask); SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); SDL_FreeSurface(surface); - texture_handle = (Rml::TextureHandle)texture; - return true; + return (Rml::TextureHandle)texture; } void ReleaseTexture(Rml::TextureHandle texture_handle) override { SDL_DestroyTexture((SDL_Texture*)texture_handle); } diff --git a/Backends/RmlUi_Backend_SDL_GL3.cpp b/Backends/RmlUi_Backend_SDL_GL3.cpp index aaf2bf6ce..dfc6d9f90 100644 --- a/Backends/RmlUi_Backend_SDL_GL3.cpp +++ b/Backends/RmlUi_Backend_SDL_GL3.cpp @@ -52,12 +52,12 @@ class RenderInterface_GL3_SDL : public RenderInterface_GL3 { public: RenderInterface_GL3_SDL() {} - bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override + Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) override { Rml::FileInterface* file_interface = Rml::GetFileInterface(); Rml::FileHandle file_handle = file_interface->Open(source); if (!file_handle) - return false; + return {}; file_interface->Seek(file_handle, 0, SEEK_END); const size_t buffer_size = file_interface->Tell(file_handle); @@ -73,10 +73,9 @@ class RenderInterface_GL3_SDL : public RenderInterface_GL3 { SDL_Surface* surface = IMG_LoadTyped_RW(SDL_RWFromMem(buffer.get(), int(buffer_size)), 1, extension.c_str()); if (!surface) - return false; + return {}; - texture_dimensions.x = surface->w; - texture_dimensions.y = surface->h; + texture_dimensions = {surface->w, surface->h}; if (surface->format->format != SDL_PIXELFORMAT_RGBA32) { @@ -85,24 +84,26 @@ class RenderInterface_GL3_SDL : public RenderInterface_GL3 { SDL_FreeSurface(surface); if (!converted_surface) - return false; + return {}; surface = converted_surface; } // Convert colors to premultiplied alpha, which is necessary for correct alpha compositing. + const size_t pixels_byte_size = surface->w * surface->h * 4; byte* pixels = static_cast(surface->pixels); - for (int i = 0; i < surface->w * surface->h * 4; i += 4) + for (size_t i = 0; i < pixels_byte_size; i += 4) { const byte alpha = pixels[i + 3]; - for (int j = 0; j < 3; ++j) + for (size_t j = 0; j < 3; ++j) pixels[i + j] = byte(int(pixels[i + j]) * int(alpha) / 255); } - bool success = RenderInterface_GL3::GenerateTexture(texture_handle, (const Rml::byte*)surface->pixels, texture_dimensions); + Rml::TextureHandle texture_handle = RenderInterface_GL3::GenerateTexture({pixels, pixels_byte_size}, texture_dimensions); + SDL_FreeSurface(surface); - return success; + return texture_handle; } }; diff --git a/Backends/RmlUi_Backend_SFML_GL2.cpp b/Backends/RmlUi_Backend_SFML_GL2.cpp index 3d35fb81c..5d9dbb0ae 100644 --- a/Backends/RmlUi_Backend_SFML_GL2.cpp +++ b/Backends/RmlUi_Backend_SFML_GL2.cpp @@ -46,7 +46,7 @@ class RenderInterface_GL2_SFML : public RenderInterface_GL2 { public: // -- Inherited from Rml::RenderInterface -- - void RenderCompiledGeometry(Rml::CompiledGeometryHandle handle, const Rml::Vector2f& translation, Rml::TextureHandle texture) override + void RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) override { if (texture) { @@ -54,10 +54,10 @@ class RenderInterface_GL2_SFML : public RenderInterface_GL2 { texture = RenderInterface_GL2::TextureEnableWithoutBinding; } - RenderInterface_GL2::RenderCompiledGeometry(handle, translation, texture); + RenderInterface_GL2::RenderGeometry(handle, translation, texture); } - bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override + Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) override { Rml::FileInterface* file_interface = Rml::GetFileInterface(); Rml::FileHandle file_handle = file_interface->Open(source); @@ -99,13 +99,11 @@ class RenderInterface_GL2_SFML : public RenderInterface_GL2 { return false; } - texture_handle = (Rml::TextureHandle)texture; texture_dimensions = Rml::Vector2i(texture->getSize().x, texture->getSize().y); - - return true; + return (Rml::TextureHandle)texture; } - bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override + Rml::TextureHandle GenerateTexture(Rml::Span source, Rml::Vector2i source_dimensions) override { sf::Texture* texture = new sf::Texture(); texture->setSmooth(true); @@ -116,11 +114,9 @@ class RenderInterface_GL2_SFML : public RenderInterface_GL2 { return false; } - texture->update(source, source_dimensions.x, source_dimensions.y, 0, 0); - - texture_handle = (Rml::TextureHandle)texture; + texture->update(source.data(), source_dimensions.x, source_dimensions.y, 0, 0); - return true; + return (Rml::TextureHandle)texture; } void ReleaseTexture(Rml::TextureHandle texture_handle) override { delete (sf::Texture*)texture_handle; } diff --git a/Backends/RmlUi_Renderer_GL2.cpp b/Backends/RmlUi_Renderer_GL2.cpp index 0eee9b23b..85308d44b 100644 --- a/Backends/RmlUi_Renderer_GL2.cpp +++ b/Backends/RmlUi_Renderer_GL2.cpp @@ -97,35 +97,23 @@ void RenderInterface_GL2::Clear() glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } -void RenderInterface_GL2::RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, const Rml::TextureHandle texture, - const Rml::Vector2f& translation) +Rml::CompiledGeometryHandle RenderInterface_GL2::CompileGeometry(Rml::Span vertices, Rml::Span indices) { - Rml::CompiledGeometryHandle geometry = CompileGeometry(vertices, num_vertices, indices, num_indices); - - if (geometry) - { - RenderCompiledGeometry(geometry, translation, texture); - ReleaseCompiledGeometry(geometry); - } -} - -Rml::CompiledGeometryHandle RenderInterface_GL2::CompileGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices) -{ - GeometryView* data = new GeometryView{vertices, indices, num_vertices, num_indices}; + GeometryView* data = new GeometryView{vertices, indices}; return reinterpret_cast(data); } -void RenderInterface_GL2::ReleaseCompiledGeometry(Rml::CompiledGeometryHandle geometry) +void RenderInterface_GL2::ReleaseGeometry(Rml::CompiledGeometryHandle geometry) { delete reinterpret_cast(geometry); } -void RenderInterface_GL2::RenderCompiledGeometry(Rml::CompiledGeometryHandle handle, const Rml::Vector2f& translation, Rml::TextureHandle texture) +void RenderInterface_GL2::RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) { const GeometryView* geometry = reinterpret_cast(handle); - const Rml::Vertex* vertices = geometry->vertices; - const int* indices = geometry->indices; - const int num_indices = geometry->num_indices; + const Rml::Vertex* vertices = geometry->vertices.data(); + const int* indices = geometry->indices.data(); + const int num_indices = (int)geometry->indices.size(); glPushMatrix(); glTranslatef(translation.x, translation.y, 0); @@ -162,9 +150,9 @@ void RenderInterface_GL2::EnableScissorRegion(bool enable) glDisable(GL_SCISSOR_TEST); } -void RenderInterface_GL2::SetScissorRegion(int x, int y, int width, int height) +void RenderInterface_GL2::SetScissorRegion(Rml::Rectanglei region) { - glScissor(x, viewport_height - (y + height), width, height); + glScissor(region.Left(), viewport_height - region.Bottom(), region.Width(), region.Height()); } void RenderInterface_GL2::EnableClipMask(bool enable) @@ -215,7 +203,7 @@ void RenderInterface_GL2::RenderToClipMask(Rml::ClipMaskOperation operation, Rml break; } - RenderCompiledGeometry(geometry, translation, {}); + RenderGeometry(geometry, translation, {}); // Restore state // @performance Cache state so we don't toggle it unnecessarily. @@ -243,7 +231,7 @@ struct TGAHeader { // Restore packing #pragma pack() -bool RenderInterface_GL2::LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) +Rml::TextureHandle RenderInterface_GL2::LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) { Rml::FileInterface* file_interface = Rml::GetFileInterface(); Rml::FileHandle file_handle = file_interface->Open(source); @@ -272,7 +260,7 @@ bool RenderInterface_GL2::LoadTexture(Rml::TextureHandle& texture_handle, Rml::V memcpy(&header, buffer.get(), sizeof(TGAHeader)); int color_mode = header.bitsPerPixel / 8; - int image_size = header.width * header.height * 4; // We always make 32bit textures + const size_t image_size = header.width * header.height * 4; // We always make 32bit textures if (header.dataType != 2) { @@ -319,33 +307,29 @@ bool RenderInterface_GL2::LoadTexture(Rml::TextureHandle& texture_handle, Rml::V texture_dimensions.x = header.width; texture_dimensions.y = header.height; - bool success = GenerateTexture(texture_handle, image_dest, texture_dimensions); - - return success; + return GenerateTexture({image_dest, image_size}, texture_dimensions); } -bool RenderInterface_GL2::GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) +Rml::TextureHandle RenderInterface_GL2::GenerateTexture(Rml::Span source, Rml::Vector2i source_dimensions) { GLuint texture_id = 0; glGenTextures(1, &texture_id); if (texture_id == 0) { Rml::Log::Message(Rml::Log::LT_ERROR, "Failed to generate texture."); - return false; + return {}; } glBindTexture(GL_TEXTURE_2D, texture_id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, source_dimensions.x, source_dimensions.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, source); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, source_dimensions.x, source_dimensions.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, source.data()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - texture_handle = (Rml::TextureHandle)texture_id; - - return true; + return (Rml::TextureHandle)texture_id; } void RenderInterface_GL2::ReleaseTexture(Rml::TextureHandle texture_handle) diff --git a/Backends/RmlUi_Renderer_GL2.h b/Backends/RmlUi_Renderer_GL2.h index b7d49f401..c26e4c4c0 100644 --- a/Backends/RmlUi_Renderer_GL2.h +++ b/Backends/RmlUi_Renderer_GL2.h @@ -47,22 +47,20 @@ class RenderInterface_GL2 : public Rml::RenderInterface { // -- Inherited from Rml::RenderInterface -- - void RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rml::TextureHandle texture, - const Rml::Vector2f& translation) override; - Rml::CompiledGeometryHandle CompileGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices) override; - void ReleaseCompiledGeometry(Rml::CompiledGeometryHandle geometry) override; - void RenderCompiledGeometry(Rml::CompiledGeometryHandle handle, const Rml::Vector2f& translation, Rml::TextureHandle texture) override; + Rml::CompiledGeometryHandle CompileGeometry(Rml::Span vertices, Rml::Span indices) override; + void ReleaseGeometry(Rml::CompiledGeometryHandle geometry) override; + void RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) override; + + Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) override; + Rml::TextureHandle GenerateTexture(Rml::Span source, Rml::Vector2i source_dimensions) override; + void ReleaseTexture(Rml::TextureHandle texture_handle) override; void EnableScissorRegion(bool enable) override; - void SetScissorRegion(int x, int y, int width, int height) override; + void SetScissorRegion(Rml::Rectanglei region) override; void EnableClipMask(bool enable) override; void RenderToClipMask(Rml::ClipMaskOperation operation, Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation) override; - bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override; - bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override; - void ReleaseTexture(Rml::TextureHandle texture_handle) override; - void SetTransform(const Rml::Matrix4f* transform) override; // Can be passed to RenderGeometry() to enable texture rendering without changing the bound texture. @@ -70,10 +68,8 @@ class RenderInterface_GL2 : public Rml::RenderInterface { private: struct GeometryView { - Rml::Vertex* vertices = nullptr; - int* indices = nullptr; - int num_vertices = 0; - int num_indices = 0; + Rml::Span vertices; + Rml::Span indices; }; int viewport_width = 0; diff --git a/Backends/RmlUi_Renderer_GL3.cpp b/Backends/RmlUi_Renderer_GL3.cpp index 66113ffd0..f10455fd4 100644 --- a/Backends/RmlUi_Renderer_GL3.cpp +++ b/Backends/RmlUi_Renderer_GL3.cpp @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -783,8 +783,7 @@ RenderInterface_GL3::RenderInterface_GL3() program_data = std::move(mut_program_data); Rml::Mesh mesh; Rml::MeshUtilities::GenerateQuad(mesh, Rml::Vector2f(-1), Rml::Vector2f(2), {}); - fullscreen_quad_geometry = - RenderInterface_GL3::CompileGeometry(mesh.vertices.data(), (int)mesh.vertices.size(), mesh.indices.data(), (int)mesh.indices.size()); + fullscreen_quad_geometry = RenderInterface_GL3::CompileGeometry(mesh.vertices, mesh.indices); } } @@ -792,7 +791,7 @@ RenderInterface_GL3::~RenderInterface_GL3() { if (fullscreen_quad_geometry) { - RenderInterface_GL3::ReleaseCompiledGeometry(fullscreen_quad_geometry); + RenderInterface_GL3::ReleaseGeometry(fullscreen_quad_geometry); fullscreen_quad_geometry = {}; } @@ -965,19 +964,7 @@ void RenderInterface_GL3::Clear() glClear(GL_COLOR_BUFFER_BIT); } -void RenderInterface_GL3::RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, const Rml::TextureHandle texture, - const Rml::Vector2f& translation) -{ - Rml::CompiledGeometryHandle geometry = CompileGeometry(vertices, num_vertices, indices, num_indices); - - if (geometry) - { - RenderCompiledGeometry(geometry, translation, texture); - ReleaseCompiledGeometry(geometry); - } -} - -Rml::CompiledGeometryHandle RenderInterface_GL3::CompileGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices) +Rml::CompiledGeometryHandle RenderInterface_GL3::CompileGeometry(Rml::Span vertices, Rml::Span indices) { constexpr GLenum draw_usage = GL_STATIC_DRAW; @@ -991,7 +978,7 @@ Rml::CompiledGeometryHandle RenderInterface_GL3::CompileGeometry(Rml::Vertex* ve glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(Rml::Vertex) * num_vertices, (const void*)vertices, draw_usage); + glBufferData(GL_ARRAY_BUFFER, sizeof(Rml::Vertex) * vertices.size(), (const void*)vertices.data(), draw_usage); glEnableVertexAttribArray((GLuint)Gfx::VertexAttribute::Position); glVertexAttribPointer((GLuint)Gfx::VertexAttribute::Position, 2, GL_FLOAT, GL_FALSE, sizeof(Rml::Vertex), @@ -1006,7 +993,7 @@ Rml::CompiledGeometryHandle RenderInterface_GL3::CompileGeometry(Rml::Vertex* ve (const GLvoid*)(offsetof(Rml::Vertex, tex_coord))); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * num_indices, (const void*)indices, draw_usage); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * indices.size(), (const void*)indices.data(), draw_usage); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -1017,12 +1004,12 @@ Rml::CompiledGeometryHandle RenderInterface_GL3::CompileGeometry(Rml::Vertex* ve geometry->vao = vao; geometry->vbo = vbo; geometry->ibo = ibo; - geometry->draw_count = num_indices; + geometry->draw_count = (GLsizei)indices.size(); return (Rml::CompiledGeometryHandle)geometry; } -void RenderInterface_GL3::RenderCompiledGeometry(Rml::CompiledGeometryHandle handle, const Rml::Vector2f& translation, Rml::TextureHandle texture) +void RenderInterface_GL3::RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) { Gfx::CompiledGeometryData* geometry = (Gfx::CompiledGeometryData*)handle; @@ -1053,7 +1040,7 @@ void RenderInterface_GL3::RenderCompiledGeometry(Rml::CompiledGeometryHandle han Gfx::CheckGLError("RenderCompiledGeometry"); } -void RenderInterface_GL3::ReleaseCompiledGeometry(Rml::CompiledGeometryHandle handle) +void RenderInterface_GL3::ReleaseGeometry(Rml::CompiledGeometryHandle handle) { Gfx::CompiledGeometryData* geometry = (Gfx::CompiledGeometryData*)handle; @@ -1103,9 +1090,9 @@ void RenderInterface_GL3::EnableScissorRegion(bool enable) SetScissor(Rml::Rectanglei::MakeInvalid(), false); } -void RenderInterface_GL3::SetScissorRegion(int x, int y, int width, int height) +void RenderInterface_GL3::SetScissorRegion(Rml::Rectanglei region) { - SetScissor(Rml::Rectanglei::FromPositionSize({x, y}, {width, height})); + SetScissor(region); } void RenderInterface_GL3::EnableClipMask(bool enable) @@ -1156,7 +1143,7 @@ void RenderInterface_GL3::RenderToClipMask(Rml::ClipMaskOperation operation, Rml break; } - RenderCompiledGeometry(geometry, translation, {}); + RenderGeometry(geometry, translation, {}); // Restore state // @performance Cache state so we don't toggle it unnecessarily. @@ -1184,7 +1171,7 @@ struct TGAHeader { // Restore packing #pragma pack() -bool RenderInterface_GL3::LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) +Rml::TextureHandle RenderInterface_GL3::LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) { Rml::FileInterface* file_interface = Rml::GetFileInterface(); Rml::FileHandle file_handle = file_interface->Open(source); @@ -1213,7 +1200,7 @@ bool RenderInterface_GL3::LoadTexture(Rml::TextureHandle& texture_handle, Rml::V memcpy(&header, buffer.get(), sizeof(TGAHeader)); int color_mode = header.bitsPerPixel / 8; - int image_size = header.width * header.height * 4; // We always make 32bit textures + const size_t image_size = header.width * header.height * 4; // We always make 32bit textures if (header.dataType != 2) { @@ -1260,12 +1247,10 @@ bool RenderInterface_GL3::LoadTexture(Rml::TextureHandle& texture_handle, Rml::V texture_dimensions.x = header.width; texture_dimensions.y = header.height; - bool success = GenerateTexture(texture_handle, image_dest, texture_dimensions); - - return success; + return GenerateTexture({image_dest, image_size}, texture_dimensions); } -bool RenderInterface_GL3::GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) +Rml::TextureHandle RenderInterface_GL3::GenerateTexture(Rml::Span source_data, Rml::Vector2i source_dimensions) { GLuint texture_id = 0; glGenTextures(1, &texture_id); @@ -1277,23 +1262,21 @@ bool RenderInterface_GL3::GenerateTexture(Rml::TextureHandle& texture_handle, co glBindTexture(GL_TEXTURE_2D, texture_id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, source_dimensions.x, source_dimensions.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, source); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, source_dimensions.x, source_dimensions.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, source_data.data()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - texture_handle = (Rml::TextureHandle)texture_id; - glBindTexture(GL_TEXTURE_2D, 0); - return true; + return (Rml::TextureHandle)texture_id; } void RenderInterface_GL3::DrawFullscreenQuad() { - RenderCompiledGeometry(fullscreen_quad_geometry, {}, RenderInterface_GL3::TexturePostprocess); + RenderGeometry(fullscreen_quad_geometry, {}, RenderInterface_GL3::TexturePostprocess); } void RenderInterface_GL3::DrawFullscreenQuad(Rml::Vector2f uv_offset, Rml::Vector2f uv_scaling) @@ -1305,8 +1288,9 @@ void RenderInterface_GL3::DrawFullscreenQuad(Rml::Vector2f uv_offset, Rml::Vecto for (Rml::Vertex& vertex : mesh.vertices) vertex.tex_coord = (vertex.tex_coord * uv_scaling) + uv_offset; } - RenderGeometry(mesh.vertices.data(), (int)mesh.vertices.size(), mesh.indices.data(), (int)mesh.indices.size(), - RenderInterface_GL3::TexturePostprocess, {}); + const Rml::CompiledGeometryHandle geometry = CompileGeometry(mesh.vertices, mesh.indices); + RenderGeometry(geometry, {}, RenderInterface_GL3::TexturePostprocess); + ReleaseGeometry(geometry); } static Rml::Colourf ConvertToColorf(Rml::ColourbPremultiplied c0) @@ -1758,7 +1742,7 @@ void RenderInterface_GL3::BlitTopLayerToPostprocessPrimary() glBlitFramebuffer(0, 0, source.width, source.height, 0, 0, destination.width, destination.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); } -void RenderInterface_GL3::RenderFilters(const Rml::FilterHandleList& filter_handles) +void RenderInterface_GL3::RenderFilters(Rml::Span filter_handles) { for (const Rml::CompiledFilterHandle filter_handle : filter_handles) { @@ -1896,7 +1880,7 @@ void RenderInterface_GL3::PushLayer(Rml::LayerFill layer_fill) glClear(GL_COLOR_BUFFER_BIT); } -void RenderInterface_GL3::PopLayer(Rml::BlendMode blend_mode, const Rml::FilterHandleList& filters) +void RenderInterface_GL3::PopLayer(Rml::BlendMode blend_mode, Rml::Span filters) { using Rml::BlendMode; @@ -1938,8 +1922,8 @@ void RenderInterface_GL3::PopLayer(Rml::BlendMode blend_mode, const Rml::FilterH Rml::TextureHandle RenderInterface_GL3::SaveLayerAsTexture(Rml::Vector2i dimensions) { - Rml::TextureHandle render_texture = {}; - if (!GenerateTexture(render_texture, nullptr, dimensions)) + Rml::TextureHandle render_texture = GenerateTexture({}, dimensions); + if (!render_texture) return {}; BlitTopLayerToPostprocessPrimary(); diff --git a/Backends/RmlUi_Renderer_GL3.h b/Backends/RmlUi_Renderer_GL3.h index f145685e3..40297e059 100644 --- a/Backends/RmlUi_Renderer_GL3.h +++ b/Backends/RmlUi_Renderer_GL3.h @@ -62,27 +62,24 @@ class RenderInterface_GL3 : public Rml::RenderInterface { // -- Inherited from Rml::RenderInterface -- - void RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rml::TextureHandle texture, - const Rml::Vector2f& translation) override; + Rml::CompiledGeometryHandle CompileGeometry(Rml::Span vertices, Rml::Span indices) override; + void RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) override; + void ReleaseGeometry(Rml::CompiledGeometryHandle handle) override; - Rml::CompiledGeometryHandle CompileGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices) override; - void RenderCompiledGeometry(Rml::CompiledGeometryHandle geometry, const Rml::Vector2f& translation, Rml::TextureHandle texture) override; - void ReleaseCompiledGeometry(Rml::CompiledGeometryHandle geometry) override; + Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) override; + Rml::TextureHandle GenerateTexture(Rml::Span source_data, Rml::Vector2i source_dimensions) override; + void ReleaseTexture(Rml::TextureHandle texture_handle) override; void EnableScissorRegion(bool enable) override; - void SetScissorRegion(int x, int y, int width, int height) override; + void SetScissorRegion(Rml::Rectanglei region) override; void EnableClipMask(bool enable) override; void RenderToClipMask(Rml::ClipMaskOperation mask_operation, Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation) override; - bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override; - bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override; - void ReleaseTexture(Rml::TextureHandle texture_handle) override; - void SetTransform(const Rml::Matrix4f* transform) override; void PushLayer(Rml::LayerFill layer_fill) override; - void PopLayer(Rml::BlendMode blend_mode, const Rml::FilterHandleList& filters) override; + void PopLayer(Rml::BlendMode blend_mode, Rml::Span filters) override; Rml::TextureHandle SaveLayerAsTexture(Rml::Vector2i dimensions) override; @@ -107,7 +104,7 @@ class RenderInterface_GL3 : public Rml::RenderInterface { void SubmitTransformUniform(Rml::Vector2f translation); void BlitTopLayerToPostprocessPrimary(); - void RenderFilters(const Rml::FilterHandleList& filter_handles); + void RenderFilters(Rml::Span filter_handles); void SetScissor(Rml::Rectanglei region, bool vertically_flip = false); diff --git a/Backends/RmlUi_Renderer_SDL.cpp b/Backends/RmlUi_Renderer_SDL.cpp index 1a0bdcb04..636ae2ba4 100644 --- a/Backends/RmlUi_Renderer_SDL.cpp +++ b/Backends/RmlUi_Renderer_SDL.cpp @@ -51,12 +51,28 @@ void RenderInterface_SDL::BeginFrame() void RenderInterface_SDL::EndFrame() {} -void RenderInterface_SDL::RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, const Rml::TextureHandle texture, - const Rml::Vector2f& translation) +Rml::CompiledGeometryHandle RenderInterface_SDL::CompileGeometry(Rml::Span vertices, Rml::Span indices) { + GeometryView* data = new GeometryView{vertices, indices}; + return reinterpret_cast(data); +} + +void RenderInterface_SDL::ReleaseGeometry(Rml::CompiledGeometryHandle geometry) +{ + delete reinterpret_cast(geometry); +} + +void RenderInterface_SDL::RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) +{ + const GeometryView* geometry = reinterpret_cast(handle); + const Rml::Vertex* vertices = geometry->vertices.data(); + const size_t num_vertices = geometry->vertices.size(); + const int* indices = geometry->indices.data(); + const size_t num_indices = geometry->indices.size(); + SDL_FPoint* positions = new SDL_FPoint[num_vertices]; - for (int i = 0; i < num_vertices; i++) + for (size_t i = 0; i < num_vertices; i++) { positions[i].x = vertices[i].position.x + translation.x; positions[i].y = vertices[i].position.y + translation.y; @@ -65,7 +81,7 @@ void RenderInterface_SDL::RenderGeometry(Rml::Vertex* vertices, int num_vertices SDL_Texture* sdl_texture = (SDL_Texture*)texture; SDL_RenderGeometryRaw(renderer, sdl_texture, &positions[0].x, sizeof(SDL_FPoint), (const SDL_Color*)&vertices->colour, sizeof(Rml::Vertex), - &vertices->tex_coord.x, sizeof(Rml::Vertex), num_vertices, indices, num_indices, 4); + &vertices->tex_coord.x, sizeof(Rml::Vertex), (int)num_vertices, indices, (int)num_indices, 4); delete[] positions; } @@ -80,23 +96,23 @@ void RenderInterface_SDL::EnableScissorRegion(bool enable) scissor_region_enabled = enable; } -void RenderInterface_SDL::SetScissorRegion(int x, int y, int width, int height) +void RenderInterface_SDL::SetScissorRegion(Rml::Rectanglei region) { - rect_scissor.x = x; - rect_scissor.y = y; - rect_scissor.w = width; - rect_scissor.h = height; + rect_scissor.x = region.Left(); + rect_scissor.y = region.Top(); + rect_scissor.w = region.Width(); + rect_scissor.h = region.Height(); if (scissor_region_enabled) SDL_RenderSetClipRect(renderer, &rect_scissor); } -bool RenderInterface_SDL::LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) +Rml::TextureHandle RenderInterface_SDL::LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) { Rml::FileInterface* file_interface = Rml::GetFileInterface(); Rml::FileHandle file_handle = file_interface->Open(source); if (!file_handle) - return false; + return {}; file_interface->Seek(file_handle, 0, SEEK_END); size_t buffer_size = file_interface->Tell(file_handle); @@ -112,7 +128,7 @@ bool RenderInterface_SDL::LoadTexture(Rml::TextureHandle& texture_handle, Rml::V SDL_Surface* surface = IMG_LoadTyped_RW(SDL_RWFromMem(buffer.get(), int(buffer_size)), 1, extension.c_str()); if (!surface) - return false; + return {}; if (surface->format->format != SDL_PIXELFORMAT_RGBA32 && surface->format->format != SDL_PIXELFORMAT_BGRA32) { @@ -120,7 +136,7 @@ bool RenderInterface_SDL::LoadTexture(Rml::TextureHandle& texture_handle, Rml::V SDL_FreeSurface(surface); if (!converted_surface) - return false; + return {}; surface = converted_surface; } @@ -137,28 +153,24 @@ bool RenderInterface_SDL::LoadTexture(Rml::TextureHandle& texture_handle, Rml::V SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); texture_dimensions = Rml::Vector2i(surface->w, surface->h); - texture_handle = (Rml::TextureHandle)texture; SDL_FreeSurface(surface); - if (!texture) - return false; - - SDL_SetTextureBlendMode(texture, blend_mode); + if (texture) + SDL_SetTextureBlendMode(texture, blend_mode); - return true; + return (Rml::TextureHandle)texture; } -bool RenderInterface_SDL::GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) +Rml::TextureHandle RenderInterface_SDL::GenerateTexture(Rml::Span source, Rml::Vector2i source_dimensions) { - SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom((void*)source, source_dimensions.x, source_dimensions.y, 32, source_dimensions.x * 4, - SDL_PIXELFORMAT_RGBA32); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom((void*)source.data(), source_dimensions.x, source_dimensions.y, 32, + source_dimensions.x * 4, SDL_PIXELFORMAT_RGBA32); SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_SetTextureBlendMode(texture, blend_mode); SDL_FreeSurface(surface); - texture_handle = (Rml::TextureHandle)texture; - return true; + return (Rml::TextureHandle)texture; } void RenderInterface_SDL::ReleaseTexture(Rml::TextureHandle texture_handle) diff --git a/Backends/RmlUi_Renderer_SDL.h b/Backends/RmlUi_Renderer_SDL.h index 4ee1c93f2..7c0af76e9 100644 --- a/Backends/RmlUi_Renderer_SDL.h +++ b/Backends/RmlUi_Renderer_SDL.h @@ -42,17 +42,23 @@ class RenderInterface_SDL : public Rml::RenderInterface { // -- Inherited from Rml::RenderInterface -- - void RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rml::TextureHandle texture, - const Rml::Vector2f& translation) override; + Rml::CompiledGeometryHandle CompileGeometry(Rml::Span vertices, Rml::Span indices) override; + void ReleaseGeometry(Rml::CompiledGeometryHandle geometry) override; + void RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) override; - void EnableScissorRegion(bool enable) override; - void SetScissorRegion(int x, int y, int width, int height) override; - - bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override; - bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override; + Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) override; + Rml::TextureHandle GenerateTexture(Rml::Span source, Rml::Vector2i source_dimensions) override; void ReleaseTexture(Rml::TextureHandle texture_handle) override; + void EnableScissorRegion(bool enable) override; + void SetScissorRegion(Rml::Rectanglei region) override; + private: + struct GeometryView { + Rml::Span vertices; + Rml::Span indices; + }; + SDL_Renderer* renderer; SDL_BlendMode blend_mode = {}; SDL_Rect rect_scissor = {}; diff --git a/Backends/RmlUi_Renderer_VK.cpp b/Backends/RmlUi_Renderer_VK.cpp index 151b4b889..33fb04e8e 100644 --- a/Backends/RmlUi_Renderer_VK.cpp +++ b/Backends/RmlUi_Renderer_VK.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -101,19 +102,7 @@ RenderInterface_VK::RenderInterface_VK() : RenderInterface_VK::~RenderInterface_VK() {} -void RenderInterface_VK::RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rml::TextureHandle texture, - const Rml::Vector2f& translation) -{ - Rml::CompiledGeometryHandle handle = CompileGeometry(vertices, num_vertices, indices, num_indices); - - if (handle) - { - RenderCompiledGeometry(handle, translation, texture); - ReleaseCompiledGeometry(handle); - } -} - -Rml::CompiledGeometryHandle RenderInterface_VK::CompileGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices) +Rml::CompiledGeometryHandle RenderInterface_VK::CompileGeometry(Rml::Span vertices, Rml::Span indices) { RMLUI_ZoneScopedN("Vulkan - CompileGeometry"); @@ -127,26 +116,26 @@ Rml::CompiledGeometryHandle RenderInterface_VK::CompileGeometry(Rml::Vertex* ver auto* p_geometry_handle = new geometry_handle_t{}; uint32_t* pCopyDataToBuffer = nullptr; - const void* pData = reinterpret_cast(vertices); + const void* pData = reinterpret_cast(vertices.data()); - bool status = m_memory_pool.Alloc_VertexBuffer(num_vertices, sizeof(Rml::Vertex), reinterpret_cast(&pCopyDataToBuffer), + bool status = m_memory_pool.Alloc_VertexBuffer((uint32_t)vertices.size(), sizeof(Rml::Vertex), reinterpret_cast(&pCopyDataToBuffer), &p_geometry_handle->m_p_vertex, &p_geometry_handle->m_p_vertex_allocation); RMLUI_VK_ASSERTMSG(status, "failed to AllocVertexBuffer"); - memcpy(pCopyDataToBuffer, pData, sizeof(Rml::Vertex) * num_vertices); + memcpy(pCopyDataToBuffer, pData, sizeof(Rml::Vertex) * vertices.size()); - status = m_memory_pool.Alloc_IndexBuffer(num_indices, sizeof(int), reinterpret_cast(&pCopyDataToBuffer), &p_geometry_handle->m_p_index, - &p_geometry_handle->m_p_index_allocation); + status = m_memory_pool.Alloc_IndexBuffer((uint32_t)indices.size(), sizeof(int), reinterpret_cast(&pCopyDataToBuffer), + &p_geometry_handle->m_p_index, &p_geometry_handle->m_p_index_allocation); RMLUI_VK_ASSERTMSG(status, "failed to AllocIndexBuffer"); - memcpy(pCopyDataToBuffer, indices, sizeof(int) * num_indices); + memcpy(pCopyDataToBuffer, indices.data(), sizeof(int) * indices.size()); - p_geometry_handle->m_num_indices = num_indices; + p_geometry_handle->m_num_indices = (int)indices.size(); return Rml::CompiledGeometryHandle(p_geometry_handle); } -void RenderInterface_VK::RenderCompiledGeometry(Rml::CompiledGeometryHandle geometry, const Rml::Vector2f& translation, Rml::TextureHandle texture) +void RenderInterface_VK::RenderGeometry(Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation, Rml::TextureHandle texture) { RMLUI_ZoneScopedN("Vulkan - RenderCompiledGeometry"); @@ -288,7 +277,7 @@ void RenderInterface_VK::RenderCompiledGeometry(Rml::CompiledGeometryHandle geom vkCmdDrawIndexed(m_p_current_command_buffer, p_casted_compiled_geometry->m_num_indices, 1, 0, 0, 0); } -void RenderInterface_VK::ReleaseCompiledGeometry(Rml::CompiledGeometryHandle geometry) +void RenderInterface_VK::ReleaseGeometry(Rml::CompiledGeometryHandle geometry) { RMLUI_ZoneScopedN("Vulkan - ReleaseCompiledGeometry"); @@ -316,23 +305,18 @@ void RenderInterface_VK::EnableScissorRegion(bool enable) } } -void RenderInterface_VK::SetScissorRegion(int x, int y, int width, int height) +void RenderInterface_VK::SetScissorRegion(Rml::Rectanglei region) { if (m_is_use_scissor_specified) { if (m_is_transform_enabled) { - float left = static_cast(x); - float right = static_cast(x + width); - float top = static_cast(y); - float bottom = static_cast(y + height); - Rml::Vertex vertices[4]; - vertices[0].position = {left, top}; - vertices[1].position = {right, top}; - vertices[2].position = {right, bottom}; - vertices[3].position = {left, bottom}; + vertices[0].position = Rml::Vector2f(region.TopLeft()); + vertices[1].position = Rml::Vector2f(region.TopRight()); + vertices[2].position = Rml::Vector2f(region.BottomRight()); + vertices[3].position = Rml::Vector2f(region.BottomLeft()); int indices[6] = {0, 2, 1, 0, 3, 2}; @@ -365,7 +349,11 @@ void RenderInterface_VK::SetScissorRegion(int x, int y, int width, int height) vkCmdClearDepthStencilImage(m_p_current_command_buffer, m_texture_depthstencil.m_p_vk_image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &info_clear_color, 1, &info_range); - RenderGeometry(vertices, 4, indices, 6, 0, Rml::Vector2f(0.0f, 0.0f)); + if (Rml::CompiledGeometryHandle handle = CompileGeometry({vertices, 4}, {indices, 6})) + { + RenderGeometry(handle, {}, {}); + ReleaseGeometry(handle); + } m_is_use_stencil_pipeline = false; @@ -373,10 +361,10 @@ void RenderInterface_VK::SetScissorRegion(int x, int y, int width, int height) } else { - m_scissor.extent.width = width; - m_scissor.extent.height = height; - m_scissor.offset.x = static_cast(std::abs(x)); - m_scissor.offset.y = static_cast(std::abs(y)); + m_scissor.extent.width = region.Width(); + m_scissor.extent.height = region.Height(); + m_scissor.offset.x = Rml::Math::Max(region.Left(), 0); + m_scissor.offset.y = Rml::Math::Max(region.Top(), 0); #ifdef RMLUI_DEBUG VkDebugUtilsLabelEXT info{}; @@ -414,7 +402,7 @@ struct TGAHeader { // Restore packing #pragma pack() -bool RenderInterface_VK::LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) +Rml::TextureHandle RenderInterface_VK::LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) { Rml::FileInterface* file_interface = Rml::GetFileInterface(); Rml::FileHandle file_handle = file_interface->Open(source); @@ -443,7 +431,7 @@ bool RenderInterface_VK::LoadTexture(Rml::TextureHandle& texture_handle, Rml::Ve memcpy(&header, buffer.get(), sizeof(TGAHeader)); int color_mode = header.bitsPerPixel / 8; - int image_size = header.width * header.height * 4; // We always make 32bit textures + const size_t image_size = header.width * header.height * 4; // We always make 32bit textures if (header.dataType != 2) { @@ -490,15 +478,13 @@ bool RenderInterface_VK::LoadTexture(Rml::TextureHandle& texture_handle, Rml::Ve texture_dimensions.x = header.width; texture_dimensions.y = header.height; - bool success = GenerateTexture(texture_handle, image_dest, texture_dimensions); - - return success; + return GenerateTexture({image_dest, image_size}, texture_dimensions); } -bool RenderInterface_VK::GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) +Rml::TextureHandle RenderInterface_VK::GenerateTexture(Rml::Span source_data, Rml::Vector2i source_dimensions) { Rml::String source_name = "generated-texture"; - return CreateTexture(texture_handle, source, source_dimensions, source_name); + return CreateTexture(source_data, source_dimensions, source_name); } /* @@ -517,12 +503,11 @@ bool RenderInterface_VK::GenerateTexture(Rml::TextureHandle& texture_handle, con efficient handling otherwise it is cpu_to_gpu visibility and it means you create only ONE buffer that is accessible for CPU and for GPU, but it will cause the worst performance... */ -bool RenderInterface_VK::CreateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& dimensions, - const Rml::String& name) +Rml::TextureHandle RenderInterface_VK::CreateTexture(Rml::Span source, Rml::Vector2i dimensions, const Rml::String& name) { RMLUI_ZoneScopedN("Vulkan - GenerateTexture"); - RMLUI_VK_ASSERTMSG(source, "you pushed not valid data for copying to buffer"); + RMLUI_VK_ASSERTMSG(!source.empty(), "you pushed not valid data for copying to buffer"); RMLUI_VK_ASSERTMSG(m_p_allocator, "you have to initialize Vma Allocator for this method"); (void)name; @@ -532,14 +517,14 @@ bool RenderInterface_VK::CreateTexture(Rml::TextureHandle& texture_handle, const RMLUI_VK_ASSERTMSG(width, "invalid width"); RMLUI_VK_ASSERTMSG(height, "invalid height"); - VkDeviceSize image_size = width * height * 4; + VkDeviceSize image_size = source.size(); VkFormat format = VkFormat::VK_FORMAT_R8G8B8A8_UNORM; buffer_data_t cpu_buffer = CreateResource_StagingBuffer(image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); void* data; vmaMapMemory(m_p_allocator, cpu_buffer.m_p_vma_allocation, &data); - memcpy(data, source, static_cast(image_size)); + memcpy(data, source.data(), static_cast(image_size)); vmaUnmapMemory(m_p_allocator, cpu_buffer.m_p_vma_allocation); VkExtent3D extent_image = {}; @@ -678,9 +663,7 @@ bool RenderInterface_VK::CreateTexture(Rml::TextureHandle& texture_handle, const p_texture->m_p_vk_image_view = p_image_view; p_texture->m_p_vk_sampler = m_p_sampler_linear; - texture_handle = reinterpret_cast(p_texture); - - return true; + return reinterpret_cast(p_texture); } void RenderInterface_VK::ReleaseTexture(Rml::TextureHandle texture_handle) diff --git a/Backends/RmlUi_Renderer_VK.h b/Backends/RmlUi_Renderer_VK.h index c4d377ef4..f8afb5d4b 100644 --- a/Backends/RmlUi_Renderer_VK.h +++ b/Backends/RmlUi_Renderer_VK.h @@ -126,32 +126,25 @@ class RenderInterface_VK : public Rml::RenderInterface { // -- Inherited from Rml::RenderInterface -- - /// Called by RmlUi when it wants to render geometry that it does not wish to optimise. - void RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rml::TextureHandle texture, - const Rml::Vector2f& translation) override; - /// Called by RmlUi when it wants to compile geometry it believes will be static for the forseeable future. - Rml::CompiledGeometryHandle CompileGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices) override; - + Rml::CompiledGeometryHandle CompileGeometry(Rml::Span vertices, Rml::Span indices) override; /// Called by RmlUi when it wants to render application-compiled geometry. - void RenderCompiledGeometry(Rml::CompiledGeometryHandle geometry, const Rml::Vector2f& translation, Rml::TextureHandle texture) override; - + void RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) override; /// Called by RmlUi when it wants to release application-compiled geometry. - void ReleaseCompiledGeometry(Rml::CompiledGeometryHandle geometry) override; - - /// Called by RmlUi when it wants to enable or disable scissoring to clip content. - void EnableScissorRegion(bool enable) override; - /// Called by RmlUi when it wants to change the scissor region. - void SetScissorRegion(int x, int y, int width, int height) override; + void ReleaseGeometry(Rml::CompiledGeometryHandle geometry) override; /// Called by RmlUi when a texture is required by the library. - bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override; + Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) override; /// Called by RmlUi when a texture is required to be built from an internally-generated sequence of pixels. - bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override; - + Rml::TextureHandle GenerateTexture(Rml::Span source_data, Rml::Vector2i source_dimensions) override; /// Called by RmlUi when a loaded texture is no longer required. void ReleaseTexture(Rml::TextureHandle texture_handle) override; + /// Called by RmlUi when it wants to enable or disable scissoring to clip content. + void EnableScissorRegion(bool enable) override; + /// Called by RmlUi when it wants to change the scissor region. + void SetScissorRegion(Rml::Rectanglei region) override; + /// Called by RmlUi when it wants to set the current transform matrix to a new matrix. void SetTransform(const Rml::Matrix4f* transform) override; @@ -479,7 +472,7 @@ class RenderInterface_VK : public Rml::RenderInterface { using ExtensionPropertiesList = Rml::Vector; private: - bool CreateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& dimensions, const Rml::String& name); + Rml::TextureHandle CreateTexture(Rml::Span source, Rml::Vector2i dimensions, const Rml::String& name); void Initialize_Instance(Rml::Vector required_extensions) noexcept; void Initialize_Device() noexcept; diff --git a/Include/RmlUi/Core/CallbackTexture.h b/Include/RmlUi/Core/CallbackTexture.h index ef1aa41f6..5584bc1d8 100644 --- a/Include/RmlUi/Core/CallbackTexture.h +++ b/Include/RmlUi/Core/CallbackTexture.h @@ -76,7 +76,7 @@ class RMLUICORE_API CallbackTextureInterface { /// @param[in] source Texture data in 8-bit RGBA (premultiplied) format. /// @param[in] dimensions The width and height of the texture. /// @return True on success. - bool GenerateTexture(const byte* source, Vector2i dimensions) const; + bool GenerateTexture(Span 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. diff --git a/Include/RmlUi/Core/Rectangle.h b/Include/RmlUi/Core/Rectangle.h index e85370c97..58ba9356a 100644 --- a/Include/RmlUi/Core/Rectangle.h +++ b/Include/RmlUi/Core/Rectangle.h @@ -76,6 +76,12 @@ class Rectangle { void ExtendTopLeft(Vector2Type v) { p0 -= v; } void ExtendBottomRight(Vector2Type v) { p1 += v; } + void Translate(Vector2Type v) + { + p0 += v; + p1 += v; + } + void Join(Vector2Type p) { p0 = Math::Min(p0, p); diff --git a/Include/RmlUi/Core/RenderInterface.h b/Include/RmlUi/Core/RenderInterface.h index b931d6b77..81c4c8f68 100644 --- a/Include/RmlUi/Core/RenderInterface.h +++ b/Include/RmlUi/Core/RenderInterface.h @@ -64,80 +64,68 @@ class RMLUICORE_API RenderInterface : public NonCopyMoveable { RenderInterface(); virtual ~RenderInterface(); - /// Called by RmlUi when it wants to render geometry that the application does not wish to optimise. Note that - /// RmlUi renders everything as triangles. - /// @param[in] vertices The geometry's vertex data. - /// @param[in] num_vertices The number of vertices passed to the function. - /// @param[in] indices The geometry's index data. - /// @param[in] num_indices The number of indices passed to the function. This will always be a multiple of three. - /// @param[in] texture The texture to be applied to the geometry. This may be nullptr, in which case the geometry is untextured. - /// @param[in] translation The translation to apply to the geometry. - virtual void RenderGeometry(Vertex* vertices, int num_vertices, int* indices, int num_indices, TextureHandle texture, - const Vector2f& translation) = 0; + /** + @name Required functions for basic rendering. + */ - /// Called by RmlUi when it wants to compile geometry it believes will be static for the forseeable future. - /// If supported, this should return a handle to an optimised, application-specific version of the data. If - /// not, do not override the function or return zero; the simpler RenderGeometry() will be called instead. + /// Called by RmlUi when it wants to compile geometry to be rendered later. /// @param[in] vertices The geometry's vertex data. - /// @param[in] num_vertices The number of vertices passed to the function. /// @param[in] indices The geometry's index data. - /// @param[in] num_indices The number of indices passed to the function. This will always be a multiple of three. - /// @return The application-specific compiled geometry. Compiled geometry will be stored and rendered using RenderCompiledGeometry() in future - /// calls, and released with ReleaseCompiledGeometry() when it is no longer needed. - virtual CompiledGeometryHandle CompileGeometry(Vertex* vertices, int num_vertices, int* indices, int num_indices); - /// Called by RmlUi when it wants to render application-compiled geometry. - /// @param[in] geometry The application-specific compiled geometry to render. + /// @return An application-specified handle to the geometry, or zero if it could not be compiled. + /// @lifetime The pointed-to vertex and index data are guaranteed to be valid and immutable until ReleaseGeometry() + /// is called with the geometry handle returned here. + virtual CompiledGeometryHandle CompileGeometry(Span vertices, Span indices) = 0; + /// Called by RmlUi when it wants to render geometry. + /// @param[in] geometry The geometry to render. /// @param[in] translation The translation to apply to the geometry. - /// @param[in] texture The texture to be applied to the geometry. This may be nullptr, in which case the geometry is untextured. - virtual void RenderCompiledGeometry(CompiledGeometryHandle geometry, const Vector2f& translation, TextureHandle texture); - /// Called by RmlUi when it wants to release application-compiled geometry. - /// @param[in] geometry The application-specific compiled geometry to release. - virtual void ReleaseCompiledGeometry(CompiledGeometryHandle geometry); + /// @param[in] texture The texture to be applied to the geometry, or zero if the geometry is untextured. + virtual void RenderGeometry(CompiledGeometryHandle geometry, Vector2f translation, TextureHandle texture) = 0; + /// Called by RmlUi when it wants to release geometry. + /// @param[in] geometry The geometry to release. + virtual void ReleaseGeometry(CompiledGeometryHandle geometry) = 0; /// Called by RmlUi when a texture is required by the library. - /// @param[out] texture_handle The handle to write the texture handle for the loaded texture to. - /// @param[out] texture_dimensions The variable to write the dimensions of the loaded texture. + /// @param[out] texture_dimensions The dimensions of the loaded texture, which must be set by the application. /// @param[in] source The application-defined image source, joined with the path of the referencing document. - /// @return True if the load attempt succeeded and the handle and dimensions are valid, false if not. - virtual bool LoadTexture(TextureHandle& texture_handle, Vector2i& texture_dimensions, const String& source); - /// Called by RmlUi when a texture is required to be built from an internally-generated sequence of pixels. - /// @param[out] texture_handle The handle to write the texture handle for the generated texture to. + /// @return An application-specified handle identifying the texture, or zero if it could not be loaded. + virtual TextureHandle LoadTexture(Vector2i& texture_dimensions, const String& source) = 0; + /// Called by RmlUi when a texture is required to be generated from a sequence of pixels in memory. /// @param[in] source The raw texture data. Each pixel is made up of four 8-bit values, red, green, blue, and premultiplied alpha, in that order. /// @param[in] source_dimensions The dimensions, in pixels, of the source data. - /// @return True if the texture generation succeeded and the handle is valid, false if not. - virtual bool GenerateTexture(TextureHandle& texture_handle, const byte* source, const Vector2i& source_dimensions); - /// Called by RmlUi when a loaded texture is no longer required. + /// @return An application-specified handle identifying the texture, or zero if it could not be generated. + virtual TextureHandle GenerateTexture(Span source, Vector2i source_dimensions) = 0; + /// Called by RmlUi when a loaded or generated texture is no longer required. /// @param[in] texture The texture handle to release. - virtual void ReleaseTexture(TextureHandle texture); + virtual void ReleaseTexture(TextureHandle texture) = 0; /// Called by RmlUi when it wants to enable or disable scissoring to clip content. /// @param[in] enable True if scissoring is to enabled, false if it is to be disabled. virtual void EnableScissorRegion(bool enable) = 0; /// Called by RmlUi when it wants to change the scissor region. - /// @param[in] x The left-most pixel to be rendered. All pixels to the left of this should be clipped. - /// @param[in] y The top-most pixel to be rendered. All pixels to the top of this should be clipped. - /// @param[in] width The width of the scissored region. All pixels to the right of (x + width) should be clipped. - /// @param[in] height The height of the scissored region. All pixels to below (y + height) should be clipped. - virtual void SetScissorRegion(int x, int y, int width, int height) = 0; + /// @param[in] region The region to be rendered. All pixels outside this region should be clipped. + /// @note The region should be applied in window coordinates regardless of any active transform. + virtual void SetScissorRegion(Rectanglei region) = 0; /** - @name Remaining functions are optional to implement for advanced effects. + @name Optional functions for advanced rendering features. */ /// Called by RmlUi when it wants to enable or disable the clip mask. /// @param[in] enable True if the clip mask is to be enabled, false if it is to be disabled. - /// @note When enabled, the clip mask should hide any rendered contents outside the area of the mask. virtual void EnableClipMask(bool enable); /// Called by RmlUi when it wants to set or modify the contents of the clip mask. /// @param[in] operation Describes how the geometry should affect the clip mask. /// @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. virtual void RenderToClipMask(ClipMaskOperation operation, CompiledGeometryHandle geometry, Vector2f translation); /// Called by RmlUi when it wants the renderer to use a new transform matrix. - /// This will only be called if 'transform' properties are encountered. If no transform applies to the current element, nullptr - /// is submitted. Then it expects the renderer to use an identity matrix or otherwise omit the multiplication with the transform. /// @param[in] transform The new transform to apply, or nullptr if no transform applies to the current element. + /// @note When nullptr is submitted, the renderer should use an identity transform matrix or otherwise omit the + /// multiplication with the transform. + /// @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. @@ -146,21 +134,21 @@ class RMLUICORE_API RenderInterface : public NonCopyMoveable { /// 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, const FilterHandleList& filters); + virtual void PopLayer(BlendMode blend_mode, Span filters); /// 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 The handle to the new texture. + /// @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 The handle to a new filter representng the stored mask image. + /// @return An application-specified handle to a new filter representng the stored mask image. virtual CompiledFilterHandle SaveLayerAsMaskImage(); /// Called by RmlUi when it wants to compile a new filter. /// @param[in] name The name of the filter. /// @param[in] parameters The list of name-value parameters specified for the filter. - /// @return The handle representing the compiled filter. + /// @return An application-specified handle representing the compiled filter. virtual CompiledFilterHandle CompileFilter(const String& name, const Dictionary& parameters); /// Called by RmlUi when it no longer needs a previously compiled filter. /// @param[in] filter The handle to a previously compiled filter. @@ -169,13 +157,13 @@ class RMLUICORE_API RenderInterface : public NonCopyMoveable { /// Called by RmlUi when it wants to compile a new shader. /// @param[in] name The name of the shader. /// @param[in] parameters The list of name-value parameters specified for the filter. - /// @return The handle representing the compiled shader. + /// @return An application-specified handle representing the shader. virtual CompiledShaderHandle CompileShader(const String& name, const Dictionary& parameters); /// Called by RmlUi when it wants to render geometry using the given shader. /// @param[in] shader The handle to a previously compiled shader. /// @param[in] geometry The handle to a previously compiled geometry. /// @param[in] translation The translation to apply to the geometry. - /// @param[in] texture The texture to use when rendering the geometry, or nullptr if no texture is required. + /// @param[in] texture The texture to use when rendering the geometry, or zero for no texture. virtual void RenderShader(CompiledShaderHandle shader, CompiledGeometryHandle geometry, Vector2f translation, TextureHandle texture); /// Called by RmlUi when it no longer needs a previously compiled shader. /// @param[in] shader The handle to a previously compiled shader. diff --git a/Include/RmlUi/Core/RenderManager.h b/Include/RmlUi/Core/RenderManager.h index 808a63110..594b50007 100644 --- a/Include/RmlUi/Core/RenderManager.h +++ b/Include/RmlUi/Core/RenderManager.h @@ -104,7 +104,7 @@ class RMLUICORE_API RenderManager : NonCopyMoveable { CompiledShader CompileShader(const String& name, const Dictionary& parameters); void PushLayer(LayerFill layer_fill); - void PopLayer(BlendMode blend_mode, const FilterHandleList& filters); + void PopLayer(BlendMode blend_mode, Span filters); CompiledFilter SaveLayerAsMaskImage(); diff --git a/Source/Core/CallbackTexture.cpp b/Source/Core/CallbackTexture.cpp index 286211448..c86c5db20 100644 --- a/Source/Core/CallbackTexture.cpp +++ b/Source/Core/CallbackTexture.cpp @@ -52,19 +52,17 @@ CallbackTextureInterface::CallbackTextureInterface(RenderManager& render_manager render_interface(render_interface), texture_handle(texture_handle), dimensions(dimensions) {} -bool CallbackTextureInterface::GenerateTexture(const byte* source, Vector2i new_dimensions) const +bool CallbackTextureInterface::GenerateTexture(Span source, Vector2i new_dimensions) const { if (texture_handle) { RMLUI_ERRORMSG("Texture already set"); return false; } - const bool result = render_interface.GenerateTexture(texture_handle, source, new_dimensions); - if (result) + texture_handle = render_interface.GenerateTexture(source, new_dimensions); + if (texture_handle) dimensions = new_dimensions; - else - texture_handle = {}; - return result; + return texture_handle != TextureHandle{}; } void CallbackTextureInterface::SaveLayerAsTexture(Vector2i new_dimensions) const diff --git a/Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp b/Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp index 6225ed66f..044a81f11 100644 --- a/Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp +++ b/Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp @@ -169,7 +169,7 @@ int FontFaceHandleDefault::GenerateLayerConfiguration(const FontEffectList& font return (int)(layer_configurations.size() - 1); } -bool FontFaceHandleDefault::GenerateLayerTexture(UniquePtr& texture_data, Vector2i& texture_dimensions, const FontEffect* font_effect, +bool FontFaceHandleDefault::GenerateLayerTexture(Vector& texture_data, Vector2i& texture_dimensions, const FontEffect* font_effect, int texture_id, int handle_version) const { if (handle_version != version) diff --git a/Source/Core/FontEngineDefault/FontFaceHandleDefault.h b/Source/Core/FontEngineDefault/FontFaceHandleDefault.h index 0b30d43d9..d94ebcceb 100644 --- a/Source/Core/FontEngineDefault/FontFaceHandleDefault.h +++ b/Source/Core/FontEngineDefault/FontFaceHandleDefault.h @@ -73,7 +73,7 @@ class FontFaceHandleDefault final : public NonCopyMoveable { /// @param[in] font_effect The font effect used for the layer. /// @param[in] texture_id The index of the texture within the layer to generate. /// @param[in] handle_version The version of the handle data. Function returns false if out of date. - bool GenerateLayerTexture(UniquePtr& texture_data, Vector2i& texture_dimensions, const FontEffect* font_effect, int texture_id, + bool GenerateLayerTexture(Vector& texture_data, Vector2i& texture_dimensions, const FontEffect* font_effect, int texture_id, int handle_version) const; /// Generates the geometry required to render a single line of text. diff --git a/Source/Core/FontEngineDefault/FontFaceLayer.cpp b/Source/Core/FontEngineDefault/FontFaceLayer.cpp index c81947168..10364faf5 100644 --- a/Source/Core/FontEngineDefault/FontFaceLayer.cpp +++ b/Source/Core/FontEngineDefault/FontFaceLayer.cpp @@ -161,12 +161,12 @@ bool FontFaceLayer::Generate(const FontFaceHandleDefault* handle, const FontFace const int texture_id = i; CallbackTextureFunction texture_callback = [handle, effect_ptr, texture_id, handle_version]( - const CallbackTextureInterface& texture_interface) -> bool { + const CallbackTextureInterface& texture_interface) -> bool { Vector2i dimensions; - UniquePtr data; - if (!handle->GenerateLayerTexture(data, dimensions, effect_ptr, texture_id, handle_version) || !data) + Vector data; + if (!handle->GenerateLayerTexture(data, dimensions, effect_ptr, texture_id, handle_version) || data.empty()) return false; - if (!texture_interface.GenerateTexture(data.get(), dimensions)) + if (!texture_interface.GenerateTexture(data, dimensions)) return false; return true; }; @@ -181,7 +181,7 @@ bool FontFaceLayer::Generate(const FontFaceHandleDefault* handle, const FontFace return true; } -bool FontFaceLayer::GenerateTexture(UniquePtr& texture_data, Vector2i& texture_dimensions, int texture_id, const FontGlyphMap& glyphs) +bool FontFaceLayer::GenerateTexture(Vector& texture_data, Vector2i& texture_dimensions, int texture_id, const FontGlyphMap& glyphs) { if (texture_id < 0 || texture_id > texture_layout.GetNumTextures()) return false; diff --git a/Source/Core/FontEngineDefault/FontFaceLayer.h b/Source/Core/FontEngineDefault/FontFaceLayer.h index e19cc2938..909015487 100644 --- a/Source/Core/FontEngineDefault/FontFaceLayer.h +++ b/Source/Core/FontEngineDefault/FontFaceLayer.h @@ -60,11 +60,11 @@ class FontFaceLayer { bool Generate(const FontFaceHandleDefault* handle, const FontFaceLayer* clone = nullptr, bool clone_glyph_origins = false); /// Generates the texture data for a layer (for the texture database). - /// @param[out] texture_data The pointer to be set to the generated texture data. + /// @param[out] texture_data The generated texture data. /// @param[out] texture_dimensions The dimensions of the texture. /// @param[in] texture_id The index of the texture within the layer to generate. /// @param[in] glyphs The glyphs required by the font face handle. - bool GenerateTexture(UniquePtr& texture_data, Vector2i& texture_dimensions, int texture_id, const FontGlyphMap& glyphs); + bool GenerateTexture(Vector& texture_data, Vector2i& texture_dimensions, int texture_id, const FontGlyphMap& glyphs); /// Generates the geometry required to render a single character. /// @param[out] mesh_list An array of meshes this layer will write to. It must be at least as big as the number of textures in this layer. diff --git a/Source/Core/RenderInterface.cpp b/Source/Core/RenderInterface.cpp index 3fd9e69a2..414cd20fa 100644 --- a/Source/Core/RenderInterface.cpp +++ b/Source/Core/RenderInterface.cpp @@ -45,36 +45,15 @@ RenderInterface::~RenderInterface() "or nullptr dereference when releasing render resources. Ensure that the render interface is destroyed *after* the call to Rml::Shutdown."); } -CompiledGeometryHandle RenderInterface::CompileGeometry(Vertex* /*vertices*/, int /*num_vertices*/, int* /*indices*/, int /*num_indices*/) -{ - return 0; -} - -void RenderInterface::RenderCompiledGeometry(CompiledGeometryHandle /*geometry*/, const Vector2f& /*translation*/, TextureHandle /*texture*/) {} - -void RenderInterface::ReleaseCompiledGeometry(CompiledGeometryHandle /*geometry*/) {} - void RenderInterface::EnableClipMask(bool /*enable*/) {} void RenderInterface::RenderToClipMask(ClipMaskOperation /*operation*/, CompiledGeometryHandle /*geometry*/, Vector2f /*translation*/) {} -bool RenderInterface::LoadTexture(TextureHandle& /*texture_handle*/, Vector2i& /*texture_dimensions*/, const String& /*source*/) -{ - return false; -} - -bool RenderInterface::GenerateTexture(TextureHandle& /*texture_handle*/, const byte* /*source*/, const Vector2i& /*source_dimensions*/) -{ - return false; -} - -void RenderInterface::ReleaseTexture(TextureHandle /*texture*/) {} - void RenderInterface::SetTransform(const Matrix4f* /*transform*/) {} void RenderInterface::PushLayer(LayerFill /*layer_fill*/) {} -void RenderInterface::PopLayer(BlendMode /*blend_mode*/, const FilterHandleList& /*filters*/) {} +void RenderInterface::PopLayer(BlendMode /*blend_mode*/, Span /*filters*/) {} TextureHandle RenderInterface::SaveLayerAsTexture(Vector2i /*dimensions*/) { diff --git a/Source/Core/RenderManager.cpp b/Source/Core/RenderManager.cpp index 253d907a3..7c6685e46 100644 --- a/Source/Core/RenderManager.cpp +++ b/Source/Core/RenderManager.cpp @@ -127,7 +127,7 @@ void RenderManager::SetScissorRegion(Rectanglei new_region) new_region.Intersect(Rectanglei::FromSize(viewport_dimensions)); if (new_region != state.scissor_region) - render_interface->SetScissorRegion(new_region.Left(), new_region.Top(), new_region.Width(), new_region.Height()); + render_interface->SetScissorRegion(new_region); } state.scissor_region = new_region; @@ -219,8 +219,10 @@ CompiledGeometryHandle RenderManager::GetCompiledGeometryHandle(StableVectorInde GeometryData& geometry = geometry_list[index]; if (!geometry.handle && !geometry.mesh.indices.empty()) { - geometry.handle = render_interface->CompileGeometry(geometry.mesh.vertices.data(), (int)geometry.mesh.vertices.size(), - geometry.mesh.indices.data(), (int)geometry.mesh.indices.size()); + geometry.handle = render_interface->CompileGeometry(geometry.mesh.vertices, geometry.mesh.indices); + + if (!geometry.handle) + Log::Message(Log::LT_ERROR, "Got empty compiled geometry."); } return geometry.handle; } @@ -245,7 +247,7 @@ void RenderManager::Render(const Geometry& geometry, Vector2f translation, Textu if (shader) render_interface->RenderShader(shader.resource_handle, geometry_handle, translation, texture_handle); else - render_interface->RenderCompiledGeometry(geometry_handle, translation, texture_handle); + render_interface->RenderGeometry(geometry_handle, translation, texture_handle); } } @@ -265,7 +267,7 @@ void RenderManager::ReleaseAllCompiledGeometry() geometry_list.for_each([this](GeometryData& data) { if (data.handle) { - render_interface->ReleaseCompiledGeometry(data.handle); + render_interface->ReleaseGeometry(data.handle); data.handle = {}; } }); @@ -298,7 +300,7 @@ void RenderManager::PushLayer(LayerFill layer_fill) render_interface->PushLayer(layer_fill); } -void RenderManager::PopLayer(BlendMode blend_mode, const FilterHandleList& filters) +void RenderManager::PopLayer(BlendMode blend_mode, Span filters) { render_interface->PopLayer(blend_mode, filters); } @@ -327,7 +329,7 @@ Mesh RenderManager::ReleaseResource(const Geometry& geometry) GeometryData& data = geometry_list[geometry.resource_handle]; if (data.handle) { - render_interface->ReleaseCompiledGeometry(data.handle); + render_interface->ReleaseGeometry(data.handle); data.handle = {}; } Mesh result = std::exchange(data.mesh, Mesh()); diff --git a/Source/Core/TextureDatabase.cpp b/Source/Core/TextureDatabase.cpp index 13c762ab8..aca8ae6a4 100644 --- a/Source/Core/TextureDatabase.cpp +++ b/Source/Core/TextureDatabase.cpp @@ -122,9 +122,8 @@ TextureFileIndex FileTextureDatabase::LoadTexture(RenderInterface* render_interf if (it != texture_map.end()) return it->second; - TextureHandle handle = {}; Vector2i dimensions; - if (render_interface->LoadTexture(handle, dimensions, source) && handle) + if (TextureHandle handle = render_interface->LoadTexture(dimensions, source)) { TextureFileIndex result = TextureFileIndex(texture_list.size()); texture_map[source] = result; diff --git a/Source/Core/TextureLayoutTexture.cpp b/Source/Core/TextureLayoutTexture.cpp index 7fdf65f27..2194fafe6 100644 --- a/Source/Core/TextureLayoutTexture.cpp +++ b/Source/Core/TextureLayoutTexture.cpp @@ -132,18 +132,17 @@ int TextureLayoutTexture::Generate(TextureLayout& layout, int maximum_dimensions } } -UniquePtr TextureLayoutTexture::AllocateTexture() +Vector TextureLayoutTexture::AllocateTexture() { - // Note: this object does not free this texture data. It is freed in the font texture loader. - UniquePtr texture_data; + Vector texture_data; if (dimensions.x > 0 && dimensions.y > 0) { // Set the texture to transparent black. - texture_data.reset(new byte[dimensions.x * dimensions.y * 4]()); + texture_data.resize(dimensions.x * dimensions.y * 4, 0); for (size_t i = 0; i < rows.size(); ++i) - rows[i].Allocate(texture_data.get(), dimensions.x * 4); + rows[i].Allocate(texture_data.data(), dimensions.x * 4); } return texture_data; diff --git a/Source/Core/TextureLayoutTexture.h b/Source/Core/TextureLayoutTexture.h index 4d9c43bb2..c8ff5adf6 100644 --- a/Source/Core/TextureLayoutTexture.h +++ b/Source/Core/TextureLayoutTexture.h @@ -62,7 +62,7 @@ class TextureLayoutTexture { /// Allocates the texture. /// @return The allocated texture data. - UniquePtr AllocateTexture(); + Vector AllocateTexture(); private: using RowList = Vector; diff --git a/Source/Lottie/ElementLottie.cpp b/Source/Lottie/ElementLottie.cpp index e59ae910b..ab74f9c8f 100644 --- a/Source/Lottie/ElementLottie.cpp +++ b/Source/Lottie/ElementLottie.cpp @@ -238,7 +238,7 @@ void ElementLottie::UpdateTexture() #endif } - if (!texture_interface.GenerateTexture(p_data, render_dimensions)) + if (!texture_interface.GenerateTexture({p_data, total_bytes}, render_dimensions)) return false; return true; }; diff --git a/Source/SVG/ElementSVG.cpp b/Source/SVG/ElementSVG.cpp index 8e4dc55d3..0e8d834a3 100644 --- a/Source/SVG/ElementSVG.cpp +++ b/Source/SVG/ElementSVG.cpp @@ -188,14 +188,14 @@ void ElementSVG::UpdateTexture() lunasvg::Bitmap bitmap = svg_document->renderToBitmap(render_dimensions.x, render_dimensions.y); // Swap red and blue channels, assuming LunaSVG v2.3.2 or newer, to convert to RmlUi's expected RGBA-ordering. - const size_t bitmap_size = bitmap.width() * bitmap.height(); + const size_t bitmap_byte_size = bitmap.width() * bitmap.height() * 4; uint8_t* bitmap_data = bitmap.data(); - for (size_t i = 0; i < bitmap_size; i++) - std::swap(bitmap_data[i * 4], bitmap_data[i * 4 + 2]); + for (size_t i = 0; i < bitmap_byte_size; i += 4) + std::swap(bitmap_data[i], bitmap_data[i + 2]); if (!bitmap.valid() || !bitmap.data()) return false; - if (!texture_interface.GenerateTexture(reinterpret_cast(bitmap.data()), render_dimensions)) + if (!texture_interface.GenerateTexture({reinterpret_cast(bitmap.data()), bitmap_byte_size}, render_dimensions)) return false; return true; }; diff --git a/Tests/Source/Common/TestsInterface.cpp b/Tests/Source/Common/TestsInterface.cpp index d675ae7d1..0fec9f35d 100644 --- a/Tests/Source/Common/TestsInterface.cpp +++ b/Tests/Source/Common/TestsInterface.cpp @@ -83,30 +83,20 @@ void TestsSystemInterface::SetTime(double t) elapsed_time = t; } -void TestsRenderInterface::RenderGeometry(Rml::Vertex* /*vertices*/, int /*num_vertices*/, int* /*indices*/, int /*num_indices*/, - const Rml::TextureHandle /*texture*/, const Rml::Vector2f& /*translation*/) +Rml::CompiledGeometryHandle TestsRenderInterface::CompileGeometry(Rml::Span /*vertices*/, Rml::Span /*indices*/) { - counters.render_calls += 1; + counters.compile_geometry += 1; + return Rml::CompiledGeometryHandle(counters.compile_geometry); } -Rml::CompiledGeometryHandle TestsRenderInterface::CompileGeometry(Rml::Vertex* /*vertices*/, int /*num_vertices*/, int* /*indices*/, - int /*num_indices*/) +void TestsRenderInterface::RenderGeometry(Rml::CompiledGeometryHandle /*geometry*/, Rml::Vector2f /*translation*/, Rml::TextureHandle /*texture*/) { - if (!enable_compiled_geometry) - return {}; - counters.compile_geometry_calls += 1; - return Rml::CompiledGeometryHandle(counters.compile_geometry_calls); + counters.render_geometry += 1; } -void TestsRenderInterface::RenderCompiledGeometry(Rml::CompiledGeometryHandle /*geometry*/, const Rml::Vector2f& /*translation*/, - Rml::TextureHandle /*texture*/) +void TestsRenderInterface::ReleaseGeometry(Rml::CompiledGeometryHandle /*geometry*/) { - counters.render_compiled_geometry_calls += 1; -} - -void TestsRenderInterface::ReleaseCompiledGeometry(Rml::CompiledGeometryHandle /*geometry*/) -{ - counters.release_compiled_geometry_calls += 1; + counters.release_geometry += 1; } void TestsRenderInterface::EnableScissorRegion(bool /*enable*/) @@ -114,26 +104,33 @@ void TestsRenderInterface::EnableScissorRegion(bool /*enable*/) counters.enable_scissor += 1; } -void TestsRenderInterface::SetScissorRegion(int /*x*/, int /*y*/, int /*width*/, int /*height*/) +void TestsRenderInterface::SetScissorRegion(Rml::Rectanglei /*region*/) { counters.set_scissor += 1; } -bool TestsRenderInterface::LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& /*source*/) +void TestsRenderInterface::EnableClipMask(bool /*enable*/) +{ + counters.enable_clip_mask += 1; +} + +void TestsRenderInterface::RenderToClipMask(Rml::ClipMaskOperation /*mask_operation*/, Rml::CompiledGeometryHandle /*geometry*/, Rml::Vector2f /*translation*/) +{ + counters.render_to_clip_mask += 1; +} + +Rml::TextureHandle TestsRenderInterface::LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& /*source*/) { counters.load_texture += 1; - texture_handle = 1; texture_dimensions.x = 512; texture_dimensions.y = 256; - return true; + return 1; } -bool TestsRenderInterface::GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* /*source*/, - const Rml::Vector2i& /*source_dimensions*/) +Rml::TextureHandle TestsRenderInterface::GenerateTexture(Rml::Span /*source*/, Rml::Vector2i /*source_dimensions*/) { counters.generate_texture += 1; - texture_handle = 1; - return true; + return 1; } void TestsRenderInterface::ReleaseTexture(Rml::TextureHandle /*texture_handle*/) diff --git a/Tests/Source/Common/TestsInterface.h b/Tests/Source/Common/TestsInterface.h index 563670e3f..68fde0c64 100644 --- a/Tests/Source/Common/TestsInterface.h +++ b/Tests/Source/Common/TestsInterface.h @@ -57,47 +57,41 @@ class TestsSystemInterface : public Rml::SystemInterface { class TestsRenderInterface : public Rml::RenderInterface { public: struct Counters { - size_t render_calls; - size_t compile_geometry_calls; - size_t render_compiled_geometry_calls; - size_t release_compiled_geometry_calls; - size_t enable_scissor; - size_t set_scissor; + size_t compile_geometry; + size_t render_geometry; + size_t release_geometry; size_t load_texture; size_t generate_texture; size_t release_texture; + size_t enable_scissor; + size_t set_scissor; + size_t enable_clip_mask; + size_t render_to_clip_mask; size_t set_transform; }; - void RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rml::TextureHandle texture, - const Rml::Vector2f& translation) override; + Rml::CompiledGeometryHandle CompileGeometry(Rml::Span vertices, Rml::Span indices) override; + void RenderGeometry(Rml::CompiledGeometryHandle handle, Rml::Vector2f translation, Rml::TextureHandle texture) override; + void ReleaseGeometry(Rml::CompiledGeometryHandle handle) override; - Rml::CompiledGeometryHandle CompileGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices) override; - void RenderCompiledGeometry(Rml::CompiledGeometryHandle geometry, const Rml::Vector2f& translation, Rml::TextureHandle texture) override; - void ReleaseCompiledGeometry(Rml::CompiledGeometryHandle geometry) override; + Rml::TextureHandle LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source) override; + Rml::TextureHandle GenerateTexture(Rml::Span source_data, Rml::Vector2i source_dimensions) override; + void ReleaseTexture(Rml::TextureHandle texture_handle) override; void EnableScissorRegion(bool enable) override; - void SetScissorRegion(int x, int y, int width, int height) override; + void SetScissorRegion(Rml::Rectanglei region) override; - bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override; - bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override; - void ReleaseTexture(Rml::TextureHandle texture_handle) override; + void EnableClipMask(bool enable) override; + void RenderToClipMask(Rml::ClipMaskOperation mask_operation, Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation) override; void SetTransform(const Rml::Matrix4f* transform) override; - void EnableCompiledGeometry(bool enable) { enable_compiled_geometry = enable; } - const Counters& GetCounters() const { return counters; } void ResetCounters() { counters = {}; } - void Reset() - { - ResetCounters(); - EnableCompiledGeometry(false); - } + void Reset() { ResetCounters(); } private: - bool enable_compiled_geometry = false; Counters counters = {}; }; diff --git a/Tests/Source/Common/TestsShell.cpp b/Tests/Source/Common/TestsShell.cpp index 49b4b49a1..acf91fc97 100644 --- a/Tests/Source/Common/TestsShell.cpp +++ b/Tests/Source/Common/TestsShell.cpp @@ -196,15 +196,20 @@ Rml::String TestsShell::GetRenderStats() result = Rml::CreateString(256, "Context::Render() stats:\n" - " Render calls: %zu\n" - " Scissor enable: %zu\n" - " Scissor set: %zu\n" + " Compile geometry: %zu\n" + " Render geometry: %zu\n" + " Release geometry: %zu\n" " Texture load: %zu\n" " Texture generate: %zu\n" " Texture release: %zu\n" + " Scissor enable: %zu\n" + " Scissor set: %zu\n" + " Clip mask enable: %zu\n" + " Clip mask render: %zu\n" " Transform set: %zu", - counters.render_calls, counters.enable_scissor, counters.set_scissor, counters.load_texture, counters.generate_texture, - counters.release_texture, counters.set_transform); + counters.compile_geometry, counters.render_geometry, counters.release_geometry, counters.load_texture, counters.generate_texture, + counters.release_texture, counters.enable_scissor, counters.set_scissor, counters.enable_clip_mask, counters.render_to_clip_mask, + counters.set_transform); #endif diff --git a/Tests/Source/UnitTests/Core.cpp b/Tests/Source/UnitTests/Core.cpp index 20d4625b0..e786798df 100644 --- a/Tests/Source/UnitTests/Core.cpp +++ b/Tests/Source/UnitTests/Core.cpp @@ -132,7 +132,6 @@ TEST_CASE("core.release_resources") return; render_interface->Reset(); - render_interface->EnableCompiledGeometry(true); const auto& counters = render_interface->GetCounters(); Context* context = TestsShell::GetContext(); @@ -187,16 +186,16 @@ TEST_CASE("core.release_resources") CHECK(counters.release_texture == counter_release_before + 1); } - SUBCASE("ReleaseCompiledGeometry") + SUBCASE("ReleaseGeometry") { - CHECK(counters.compile_geometry_calls > 0); - CHECK(counters.release_compiled_geometry_calls == 0); + CHECK(counters.compile_geometry > 0); + CHECK(counters.release_geometry == 0); Rml::ReleaseCompiledGeometry(); - CHECK(counters.compile_geometry_calls == counters.release_compiled_geometry_calls); + CHECK(counters.compile_geometry == counters.release_geometry); TestsShell::RenderLoop(); - CHECK(counters.compile_geometry_calls > counters.release_compiled_geometry_calls); + CHECK(counters.compile_geometry > counters.release_geometry); } document->Close(); @@ -205,7 +204,7 @@ TEST_CASE("core.release_resources") // Finally, verify that all generated and loaded resources are released during shutdown. CHECK(counters.generate_texture + counters.load_texture == counters.release_texture); - CHECK(counters.compile_geometry_calls == counters.release_compiled_geometry_calls); + CHECK(counters.compile_geometry == counters.release_geometry); render_interface->Reset(); } diff --git a/Tests/Source/VisualTests/CaptureScreen.cpp b/Tests/Source/VisualTests/CaptureScreen.cpp index 230a5836a..868013b00 100644 --- a/Tests/Source/VisualTests/CaptureScreen.cpp +++ b/Tests/Source/VisualTests/CaptureScreen.cpp @@ -125,11 +125,13 @@ ComparisonResult CompareScreenToPreviousCapture(Rml::RenderInterface* render_int } RMLUI_ASSERT(screen.num_components == 3); + const size_t image_ref_diff_byte_size = w_ref * h_ref * 4; + Image diff; diff.width = w_ref; diff.height = h_ref; diff.num_components = 4; - diff.data = Rml::UniquePtr(new Rml::byte[diff.width * diff.height * diff.num_components]); + diff.data = Rml::UniquePtr(new Rml::byte[image_ref_diff_byte_size]); // So we have both images now, compare them! Also create a diff image. // In case they are not the same size, we require that the reference image size is smaller or equal to the screen @@ -181,22 +183,23 @@ ComparisonResult CompareScreenToPreviousCapture(Rml::RenderInterface* render_int result.similarity_score = (sum_diff == 0 ? 1.0 : 1.0 - std::log(double(sum_diff)) / std::log(double(max_diff))); // Optionally render the screen capture or diff to a texture. - auto GenerateGeometry = [&](TextureGeometry& geometry, Rml::byte* data, Rml::Vector2i dimensions) -> bool { - if (!render_interface->GenerateTexture(geometry.texture_handle, data, dimensions)) - return false; + auto GenerateGeometry = [&](TextureGeometry& geometry, Rml::Span data, Rml::Vector2i dimensions) -> bool { + ReleaseTextureGeometry(render_interface, geometry); const Rml::ColourbPremultiplied colour = {255, 255, 255, 255}; const Rml::Vector2f uv_top_left = {0, 0}; const Rml::Vector2f uv_bottom_right = {1, 1}; Rml::MeshUtilities::GenerateQuad(geometry.mesh, Rml::Vector2f(0, 0), Rml::Vector2f((float)w_ref, (float)h_ref), colour, uv_top_left, uv_bottom_right); - return true; + geometry.texture_handle = render_interface->GenerateTexture(data, dimensions); + geometry.geometry_handle = render_interface->CompileGeometry(geometry.mesh.vertices, geometry.mesh.indices); + return geometry.texture_handle && geometry.geometry_handle; }; if (out_reference && result.success) - result.success = GenerateGeometry(*out_reference, data_ref, {(int)w_ref, (int)h_ref}); + result.success = GenerateGeometry(*out_reference, {data_ref, image_ref_diff_byte_size}, {(int)w_ref, (int)h_ref}); if (out_highlight && result.success) - result.success = GenerateGeometry(*out_highlight, diff.data.get(), {diff.width, diff.height}); + result.success = GenerateGeometry(*out_highlight, {diff.data.get(), image_ref_diff_byte_size}, {diff.width, diff.height}); if (!result.success) result.error_msg = Rml::CreateString(1024, "Could not generate texture from file %s", input_path.c_str()); @@ -206,13 +209,19 @@ ComparisonResult CompareScreenToPreviousCapture(Rml::RenderInterface* render_int void RenderTextureGeometry(Rml::RenderInterface* render_interface, TextureGeometry& geometry) { - if (geometry.texture_handle) - render_interface->RenderGeometry(geometry.mesh.vertices.data(), (int)geometry.mesh.vertices.size(), geometry.mesh.indices.data(), - (int)geometry.mesh.indices.size(), geometry.texture_handle, Rml::Vector2f(0, 0)); + if (geometry.geometry_handle && geometry.texture_handle) + { + render_interface->RenderGeometry(geometry.geometry_handle, Rml::Vector2f(0, 0), geometry.texture_handle); + } } void ReleaseTextureGeometry(Rml::RenderInterface* render_interface, TextureGeometry& geometry) { + if (geometry.geometry_handle) + { + render_interface->ReleaseGeometry(geometry.geometry_handle); + geometry.geometry_handle = 0; + } if (geometry.texture_handle) { render_interface->ReleaseTexture(geometry.texture_handle); diff --git a/Tests/Source/VisualTests/CaptureScreen.h b/Tests/Source/VisualTests/CaptureScreen.h index 7c6d67a47..41150bfca 100644 --- a/Tests/Source/VisualTests/CaptureScreen.h +++ b/Tests/Source/VisualTests/CaptureScreen.h @@ -44,6 +44,7 @@ struct ComparisonResult { struct TextureGeometry { Rml::TextureHandle texture_handle = 0; + Rml::CompiledGeometryHandle geometry_handle = 0; Rml::Mesh mesh; }; diff --git a/Tests/Source/VisualTests/TestNavigator.cpp b/Tests/Source/VisualTests/TestNavigator.cpp index 7c25a2851..8ded7edea 100644 --- a/Tests/Source/VisualTests/TestNavigator.cpp +++ b/Tests/Source/VisualTests/TestNavigator.cpp @@ -117,9 +117,14 @@ void TestNavigator::Render() { if (reference_state != ReferenceState::None && source_state == SourceType::None && !viewer->IsHelpVisible()) { - TextureGeometry& geometry = (reference_state == ReferenceState::ShowReferenceHighlight ? reference_highlight_geometry : reference_geometry); - render_interface->RenderGeometry(geometry.mesh.vertices.data(), (int)geometry.mesh.vertices.size(), geometry.mesh.indices.data(), - (int)geometry.mesh.indices.size(), geometry.texture_handle, Rml::Vector2f(0, 0)); + const TextureGeometry& geometry = + (reference_state == ReferenceState::ShowReferenceHighlight ? reference_highlight_geometry : reference_geometry); + + if (const Rml::CompiledGeometryHandle handle = render_interface->CompileGeometry(geometry.mesh.vertices, geometry.mesh.indices)) + { + render_interface->RenderGeometry(handle, Rml::Vector2f(0, 0), geometry.texture_handle); + render_interface->ReleaseGeometry(handle); + } } }