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); + } } }