Skip to content

Commit

Permalink
Only allow a single render interface, remove the ability to set per-c…
Browse files Browse the repository at this point in the history
…ontext render interfaces [breaking change]

Now, only a single render interface can be set, and it must be set globally before the call to Rml::Initialise. Furthermore, the render interface cannot be changed while the library is initialised, and must live until after the call to Rml::Shutdown. If these conditions are not met, the library will submit error messages to the user in most cases.

This change is motivated by several reasons:

- The feature added considerable complexity, since several types of render state needed to store their state per render interface.
- This complexity would have become more pronounced with upcoming changes for advanced render effects.
- It was easy to make bugs where render resources (e.g. textures) would be freed in the wrong render interface.
- It was difficult to test for the presence of the above bugs.
- No tests existed already, it is very likely that bugs were already present.
  • Loading branch information
mikke89 committed Apr 15, 2023
1 parent 12193df commit 0bbd019
Show file tree
Hide file tree
Showing 42 changed files with 204 additions and 397 deletions.
7 changes: 0 additions & 7 deletions Include/RmlUi/Core/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ class Stream;
class ContextInstancer;
class ElementDocument;
class EventListener;
class RenderInterface;
class DataModel;
class DataModelConstructor;
class DataTypeRegister;
Expand Down Expand Up @@ -247,9 +246,6 @@ class RMLUICORE_API Context : public ScriptInterface {
/// @param[in] speed_factor A factor for adjusting the final smooth scrolling speed, must be strictly positive, defaults to 1.0.
void SetDefaultScrollBehavior(ScrollBehavior scroll_behavior, float speed_factor);

/// Gets the context's render interface.
/// @return The render interface the context renders through.
RenderInterface* GetRenderInterface() const;
/// Gets the current clipping region for the render traversal
/// @param[out] origin The clipping origin
/// @param[out] dimensions The clipping dimensions
Expand Down Expand Up @@ -373,8 +369,6 @@ class RMLUICORE_API Context : public ScriptInterface {
// itself can't be part of it.
ElementSet drag_hover_chain;

// The render interface this context renders through.
RenderInterface* render_interface;
Vector2i clip_origin;
Vector2i clip_dimensions;

Expand Down Expand Up @@ -426,7 +420,6 @@ class RMLUICORE_API Context : public ScriptInterface {
static void SendEvents(const ElementSet& old_items, const ElementSet& new_items, EventId id, const Dictionary& parameters);

friend class Rml::Element;
friend RMLUICORE_API Context* CreateContext(const String&, Vector2i, RenderInterface*);
};

} // namespace Rml
Expand Down
12 changes: 3 additions & 9 deletions Include/RmlUi/Core/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ RMLUICORE_API void SetSystemInterface(SystemInterface* system_interface);
/// Returns RmlUi's system interface.
RMLUICORE_API SystemInterface* GetSystemInterface();

/// Sets the interface through which all rendering requests are made. This is not required to be called, but if it is
/// it must be called before Initialise(). If no render interface is specified, then all contexts must have a custom
/// render interface.
/// Sets the interface through which all rendering requests are made. This must be called before Initialise().
/// @param[in] render_interface A non-owning pointer to the render interface implementation.
/// @lifetime The interface must be kept alive until after the call to Rml::Shutdown.
RMLUICORE_API void SetRenderInterface(RenderInterface* render_interface);
Expand All @@ -94,11 +92,8 @@ RMLUICORE_API FontEngineInterface* GetFontEngineInterface();
/// Creates a new element context.
/// @param[in] name The new name of the context. This must be unique.
/// @param[in] dimensions The initial dimensions of the new context.
/// @param[in] render_interface The custom render interface to use, or nullptr to use the default.
/// @lifetime If specified, the render interface must be kept alive until after the call to Rml::Shutdown. Alternatively, the render interface can be
/// destroyed after all contexts it belongs to have been destroyed and a subsequent call has been made to Rml::ReleaseTextures.
/// @return A non-owning pointer to the new context, or nullptr if the context could not be created.
RMLUICORE_API Context* CreateContext(const String& name, Vector2i dimensions, RenderInterface* render_interface = nullptr);
RMLUICORE_API Context* CreateContext(const String& name, Vector2i dimensions);
/// Removes and destroys a context.
/// @param[in] name The name of the context to remove.
/// @return True if name is a valid context, false otherwise.
Expand Down Expand Up @@ -154,8 +149,7 @@ RMLUICORE_API EventId RegisterEventType(const String& type, bool interruptible,
/// Returns a list of source URLs to textures in all loaded documents.
RMLUICORE_API StringList GetTextureSourceList();
/// Forces all texture handles loaded and generated by RmlUi to be released.
/// @param[in] render_interface Release all textures belonging to the given interface, or nullptr to release all textures in all interfaces.
RMLUICORE_API void ReleaseTextures(RenderInterface* render_interface = nullptr);
RMLUICORE_API void ReleaseTextures();
/// Forces all compiled geometry handles generated by RmlUi to be released.
RMLUICORE_API void ReleaseCompiledGeometry();
/// Releases unused font textures and rendered glyphs to free up memory, and regenerates actively used fonts.
Expand Down
5 changes: 0 additions & 5 deletions Include/RmlUi/Core/Element.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ class InlineLevelBox;
class ReplacedBox;
class PropertiesIteratorView;
class PropertyDictionary;
class RenderInterface;
class StyleSheet;
class StyleSheetContainer;
class TransformState;
Expand Down Expand Up @@ -584,10 +583,6 @@ class RMLUICORE_API Element : public ScriptInterface, public EnableObserverPtr<E
DataModel* GetDataModel() const;
//@}

/// Gets the render interface owned by this element's context.
/// @return The element's context's render interface.
RenderInterface* GetRenderInterface();

/// Sets the instancer to use for releasing this element.
/// @param[in] instancer Instancer to set on this element.
void SetInstancer(ElementInstancer* instancer);
Expand Down
8 changes: 3 additions & 5 deletions Include/RmlUi/Core/ElementUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ namespace Rml {

class Box;
class Context;
class RenderInterface;
namespace Style {
class ComputedValues;
}
Expand Down Expand Up @@ -100,8 +99,7 @@ class RMLUICORE_API ElementUtilities {
static bool SetClippingRegion(Element* element, Context* context = nullptr);
/// Applies the clip region from the render interface to the renderer
/// @param[in] context The context to read the clip region from
/// @param[in] render_interface The render interface to update.
static void ApplyActiveClipRegion(Context* context, RenderInterface* render_interface);
static void ApplyActiveClipRegion(Context* context);

/// Formats the contents of an element. This does not need to be called for ordinary elements, but can be useful
/// for non-DOM elements of custom elements.
Expand All @@ -124,9 +122,9 @@ class RMLUICORE_API ElementUtilities {
static bool PositionElement(Element* element, Vector2f offset, PositionAnchor anchor);

/// Applies an element's accumulated transform matrix, determined from its and ancestor's `perspective' and `transform' properties.
/// Note: All calls to RenderInterface::SetTransform must go through here.
/// @param[in] element The element whose transform to apply.
/// @param[in] element The element whose transform to apply.
/// @return true if a render interface is available to set the transform.
/// @note All calls to RenderInterface::SetTransform must go through here.
static bool ApplyTransform(Element& element);

/// Creates data views and data controllers if a data model applies to the element.
Expand Down
14 changes: 1 addition & 13 deletions Include/RmlUi/Core/Geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ namespace Rml {

class Context;
class Element;
class RenderInterface;
struct Texture;
using GeometryDatabaseHandle = uint32_t;

Expand All @@ -49,8 +48,7 @@ using GeometryDatabaseHandle = uint32_t;

class RMLUICORE_API Geometry {
public:
Geometry(Element* host_element = nullptr);
Geometry(Context* host_context);
Geometry();

Geometry(const Geometry&) = delete;
Geometry& operator=(const Geometry&) = delete;
Expand All @@ -60,10 +58,6 @@ class RMLUICORE_API Geometry {

~Geometry();

/// Set the host element for this geometry; this should be passed in the constructor if possible.
/// @param[in] host_element The new host element for the geometry.
void SetHostElement(Element* host_element);

/// Attempts to compile the geometry if appropriate, then renders the geometry, compiled if it can.
/// @param[in] translation The translation of the geometry.
void Render(Vector2f translation);
Expand Down Expand Up @@ -92,12 +86,6 @@ class RMLUICORE_API Geometry {
// Move members from another geometry.
void MoveFrom(Geometry& other) noexcept;

// Returns the host context's render interface.
RenderInterface* GetRenderInterface();

Context* host_context = nullptr;
Element* host_element = nullptr;

Vector<Vertex> vertices;
Vector<int> indices;
const Texture* texture = nullptr;
Expand Down
11 changes: 0 additions & 11 deletions Include/RmlUi/Core/RenderInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@

namespace Rml {

class Context;

/**
The abstract base class for application-specific rendering implementation. Your application must provide a concrete
implementation of this class and install it through Rml::SetRenderInterface() in order for anything to be rendered.
Expand Down Expand Up @@ -112,15 +110,6 @@ class RMLUICORE_API RenderInterface : public NonCopyMoveable {
/// 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.
virtual void SetTransform(const Matrix4f* transform);

/// Get the context currently being rendered. This is only valid during RenderGeometry,
/// CompileGeometry, RenderCompiledGeometry, EnableScissorRegion and SetScissorRegion.
Context* GetContext() const;

private:
Context* context;

friend class Rml::Context;
};

} // namespace Rml
Expand Down
14 changes: 6 additions & 8 deletions Include/RmlUi/Core/Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,12 @@ struct RMLUICORE_API Texture {
/// Returns the texture's source name. This is usually the name of the file the texture was loaded from.
/// @return The name of the this texture's source. This will be the empty string if this texture is not loaded.
const String& GetSource() const;
/// Returns the texture's handle.
/// @param[in] The render interface that is requesting the handle.
/// @return The texture's handle. This will be nullptr if the texture isn't loaded.
TextureHandle GetHandle(RenderInterface* render_interface) const;
/// Returns the texture's dimensions.
/// @param[in] The render interface that is requesting the dimensions.
/// @return The texture's dimensions. This will be (0, 0) if the texture isn't loaded.
Vector2i GetDimensions(RenderInterface* render_interface) const;
/// Returns the texture's handle, will attempt to load the texture as necessary.
/// @return The texture's handle. This will be 0 if the texture cannot be loaded.
TextureHandle GetHandle() const;
/// Returns the texture's dimensions, will attempt to load the texture as necessary.
/// @return The texture's dimensions. This will be (0, 0) if the texture cannot be loaded.
Vector2i GetDimensions() const;

/// Returns true if the texture points to the same underlying resource.
bool operator==(const Texture&) const;
Expand Down
5 changes: 3 additions & 2 deletions Samples/invaders/src/DecoratorDefender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/

#include "DecoratorDefender.h"
#include <RmlUi/Core/Core.h>
#include <RmlUi/Core/Element.h>
#include <RmlUi/Core/GeometryUtilities.h>
#include <RmlUi/Core/Math.h>
Expand Down Expand Up @@ -59,9 +60,9 @@ void DecoratorDefender::RenderElement(Rml::Element* element, Rml::DecoratorDataH
Rml::Vector2f size = element->GetBox().GetSize(Rml::Box::PADDING);
Rml::Math::SnapToPixelGrid(position, size);

if (Rml::RenderInterface* render_interface = element->GetRenderInterface())
if (Rml::RenderInterface* render_interface = ::Rml::GetRenderInterface())
{
Rml::TextureHandle texture = GetTexture(image_index)->GetHandle(render_interface);
Rml::TextureHandle texture = GetTexture(image_index)->GetHandle();
Rml::Colourb color = element->GetProperty<Rml::Colourb>("color");

Rml::Vertex vertices[4];
Expand Down
4 changes: 0 additions & 4 deletions Samples/invaders/src/DecoratorStarfield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,6 @@ void DecoratorStarfield::RenderElement(Rml::Element* element, Rml::DecoratorData
const float dp_ratio = Rml::ElementUtilities::GetDensityIndependentPixelRatio(element);
const float point_size = Rml::Math::RoundUp(2.f * dp_ratio);

Rml::RenderInterface* render_interface = element->GetRenderInterface();
if (!render_interface)
return;

int num_stars = 0;

for (size_t i = 0; i < star_field->star_layers.size(); i++)
Expand Down
2 changes: 1 addition & 1 deletion Samples/invaders/src/Game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ void Game::Render(float dp_ratio)
if (defender_lives <= 0)
return;

Rml::TextureHandle texture_handle = texture.GetHandle(Rml::GetRenderInterface());
Rml::TextureHandle texture_handle = texture.GetHandle();

// Render all available shields
for (int i = 0; i < NUM_SHIELDS; i++)
Expand Down
5 changes: 3 additions & 2 deletions Samples/luainvaders/src/DecoratorDefender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/

#include "DecoratorDefender.h"
#include <RmlUi/Core/Core.h>
#include <RmlUi/Core/Element.h>
#include <RmlUi/Core/GeometryUtilities.h>
#include <RmlUi/Core/Math.h>
Expand Down Expand Up @@ -59,9 +60,9 @@ void DecoratorDefender::RenderElement(Rml::Element* element, Rml::DecoratorDataH
Rml::Vector2f size = element->GetBox().GetSize(Rml::Box::PADDING);
Rml::Math::SnapToPixelGrid(position, size);

if (Rml::RenderInterface* render_interface = element->GetRenderInterface())
if (Rml::RenderInterface* render_interface = ::Rml::GetRenderInterface())
{
Rml::TextureHandle texture = GetTexture(image_index)->GetHandle(render_interface);
Rml::TextureHandle texture = GetTexture(image_index)->GetHandle();
Rml::Colourb color = element->GetProperty<Rml::Colourb>("color");

Rml::Vertex vertices[4];
Expand Down
4 changes: 0 additions & 4 deletions Samples/luainvaders/src/DecoratorStarfield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,6 @@ void DecoratorStarfield::RenderElement(Rml::Element* element, Rml::DecoratorData
const float dp_ratio = Rml::ElementUtilities::GetDensityIndependentPixelRatio(element);
const float point_size = Rml::Math::RoundUp(2.f * dp_ratio);

Rml::RenderInterface* render_interface = element->GetRenderInterface();
if (!render_interface)
return;

int num_stars = 0;

for (size_t i = 0; i < star_field->star_layers.size(); i++)
Expand Down
2 changes: 1 addition & 1 deletion Samples/luainvaders/src/Game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ void Game::Render(float dp_ratio)
if (defender_lives <= 0)
return;

Rml::TextureHandle texture_handle = texture.GetHandle(Rml::GetRenderInterface());
Rml::TextureHandle texture_handle = texture.GetHandle();

// Render all available shields
for (int i = 0; i < NUM_SHIELDS; i++)
Expand Down
19 changes: 1 addition & 18 deletions Source/Core/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ Context::Context(const String& name) :
{
instancer = nullptr;

// Initialise this to nullptr; this will be set in Rml::CreateContext().
render_interface = nullptr;

root = Factory::InstanceElement(nullptr, "*", "#root", XMLAttributes());
root->SetId(name);
root->SetOffset(Vector2f(0, 0), nullptr);
Expand Down Expand Up @@ -117,8 +114,6 @@ Context::~Context()
cursor_proxy.reset();

instancer = nullptr;

render_interface = nullptr;
}

const String& Context::GetName() const
Expand Down Expand Up @@ -223,12 +218,7 @@ bool Context::Render()
{
RMLUI_ZoneScoped;

RenderInterface* render_interface = GetRenderInterface();
if (render_interface == nullptr)
return false;

render_interface->context = this;
ElementUtilities::ApplyActiveClipRegion(this, render_interface);
ElementUtilities::ApplyActiveClipRegion(this);

root->Render();

Expand All @@ -243,8 +233,6 @@ bool Context::Render()
cursor_proxy->Render();
}

render_interface->context = nullptr;

return true;
}

Expand Down Expand Up @@ -867,11 +855,6 @@ void Context::SetDefaultScrollBehavior(ScrollBehavior scroll_behavior, float spe
scroll_controller->SetDefaultScrollBehavior(scroll_behavior, speed_factor);
}

RenderInterface* Context::GetRenderInterface() const
{
return render_interface;
}

bool Context::GetActiveClipRegion(Vector2i& origin, Vector2i& dimensions) const
{
if (clip_dimensions.x < 0 || clip_dimensions.y < 0)
Expand Down
Loading

0 comments on commit 0bbd019

Please sign in to comment.