Partial Rendering refers to a rendering technique where
only a portion of the scene or screen is updated, rather
than redrawing the entire output. It is commonly used as
a performance optimization strategy, focusing on redrawing
only the regions that have changed, often called dirty regions.
This introduces RenderDirtyRegion, which assists
in collecting a compact dirty region from render tasks.
To efficient data-processing, this divide the screen region
with a designated size of partition and handles the partitl rendering
computation with a divide-conquer metholodgy.
Each backend can utilize this class to support efficient partial rendering.
This is implemented using a Line Sweep and Subdivision Merging O(NlogN).
The basic per-frame workflow is as follows:
0. RenderDirtyRegion::init() //set the screen size to properly partition the regions
1. RenderDirtyRegion::prepare() //Call this in Renderer::preRender().
2. RenderDirtyRegion::add() //Add all dirty paints for the frame before rendering.
3. RenderDirtyRegion::commit() //Generate the partial rendering region list before rendering.
4. RenderDirtyRegion::partition() //Get a certian partition
5. RenderDirtyRegion::get() //Retrieve the current dirty region list of a partition and use it when drawing paints.
6. RenderDirtyRegion::clear() //Reset the state.
RenderMethod introduced for 2 utilities for paritial renderings
1. RenderMethod::damage() //add a force dirty region, especially useful for scene effects
2. RenderMethod::partial() //toggle the partial rendering feature
issue: https://github.com/thorvg/thorvg/issues/1747
Implemented support for clipping shapes and images using a render region
bounding box at render time. This allows partial drawing of content,
laying the groundwork for upcoming partial rendering functionality.
for fast access of the drawing region from the linear rle data,
we introduced the binary search for begin/end of rle instead of
additional y index buffer.
There is a reason for not using a y-index buffer:
the shapes in the RLE are not single, continuous shapes
but multiple shapes scattered across the space.
which means that we need a double-associated data structure
per shapes for y indexing, and this data preparation wouldn't be
cheaper enough than realtime binary search especially animated data.
issue: https://github.com/thorvg/thorvg/issues/1747
previous logic doesn't work if the clipping shape
has any inner corners. replace the logic
with a intermediate composition approach for
stability.
- performance can be drop at texture clipping by ~11%
- size is reduced by -0.5kb
issue: https://github.com/thorvg/thorvg/issues/3520
redefiend properties so that min/max are prioritized,
as they are accessed more frequently than pos/size
during rendering calculations.
also introduced miscellaneous functions to improve usability.
Added drawing exceptions when target is not properly ready.
Now, Canvas::update() Canvas::draw() will return InsufficientCondition
if the target has not been set beforehand.
Simplified parameters and ensured proper backend engine
initialization by using reference checking through canvas
instances.
C++ API Modification:
- Result Initializer::init(uint32_t threads, CanvasEngine engine)
-> Result Initializer::init(uint32_t threads)
- Result Initializer::term(CanvasEngine engine)
-> Result Initializer::term()
C API Modification:
- Tvg_Result tvg_engine_init(Tvg_Engine engine_method, unsigned threads)
-> Tvg_Result tvg_engine_init(unsigned threads);
- Tvg_Result tvg_engine_term(Tvg_Engine engine_method)
-> Tvg_Result tvg_engine_term()
issue: https://github.com/thorvg/thorvg/issues/3116
ThorVG did not consider updates to the clipping path
when a paint object was modified after being added to the scene.
This fix ensures that any updates to clipping are correctly
reflected during rendering.
issue: https://github.com/thorvg/thorvg/issues/3403
- modify the concept of AABB to apply only to transformed shapes.
- transform points before computing the bounding box min/max
to obtain a more compact shape region.
- trimmming memory by removing the cached matrix, about 36kb
of memory has been reduced per paint instance.
Support the bindings to be more integrable with a system's coherent memory management.
Pleaes note that thorvg now only allow the desinated memory allocators here:
malloc -> tvg::malloc
calloc -> tvg::calloc
realloc -> tvg::realloc
free -> tvg::free
issue: https://github.com/thorvg/thorvg/issues/2652
In cases where the fill was changed while the stroke existed
but remained unchanged, the stroke would disappear because it
was being reset during the shape preparing (shapeReset).
Fixed by disabling the reset of stroke rle from shape reseting.
Also the shape should be prepared not only when the RenderUpdateFlag
is set to Color, but also when it is set to Gradient.
@Issue: https://github.com/thorvg/thorvg/issues/3237
We have improved the functionality to manage the memory pool safely,
by figuring out the current working threads. Users no longer need to
manually configure memory pool management, and the related APIs
have been removed.
API Removals:
- Result SwCanvas::mempool(MempoolPolicy policy)
- enum SwCanvas::MempoolPolicy
- Tvg_Result tvg_swcanvas_set_mempool(Tvg_Canvas* canvas, Tvg_Mempool_Policy policy)
- enum Tvg_Mempool_Policy
issue: https://github.com/thorvg/thorvg/issues/3116
RenderMethod effects methods would have changes:
+ update() //update the effects if any
- prepare() -> region() //update the effect drawing region
- effect() -> render() //draw the effect
clipping with a stroke is useful for various visual effects.
TVG can support this approach as it offers better efficiency
compared to alpha masking.
If a valid stroke is defined in the clipper shape,
the renderer prioritizes clipping with the stroke over
the shape's fill.
issue: https://github.com/thorvg/thorvg/issues/3063
The Tritone effect maps the scene's shadows, midtones, and highlights
to three specific colors, allowing for more complex and artistic color grading.
Applied Tritone Formula:
if (L < 0.5) Result = (1 - 2L) * Shadow + 2L * Midtone
else Result = (1 - 2(L - 0.5)) * Midtone + (2(L - 0.5)) * Highlight
Where the L is Luminance.
issue: https://github.com/thorvg/thorvg/issues/2718
The Tint effect in ThorVG is used to modify the overall color tone of a scene.
It works by blending a specified tint color with the existing colors of the scene.
This effect is useful for color grading, mood changes, or applying thematic filters
to vector graphics and animations.
Applied the equation is:
Result = (1 - L) * Black + L * White, where the L is Luminance.
issue: https://github.com/thorvg/thorvg/issues/2718
Shapes with boundaries outside the rendering area are ignored as non-visible.
The issue arises when such a shape serves as a clipper.
The expected behavior is for the entire clipee to be cut out,
but previously, the clipee remained fully visible as if no clip was applied.
The fix identifies these clippers and skips rendering clipees.
Please note that we can skip rendering at the Paint update stage
if the clipper's viewport is outside the canvas.
This optimization can improve performance, but only for this specific case.
The downside of the approach is that it disrupts multi-processing for clipper updates.
As a result, that approach was discarded.
issue: https://github.com/thorvg/thorvg/issues/3003
issue: https://github.com/thorvg/thorvg/issues/2684
Co-Authored-By: Mira Grudzinska <mira@lottiefiles.com>
enhanced the rendering composition target to better support features such as
alpha blending, blending, masking, post effects, and more.
This allows rasterizers to prepare the composition context with more precise control.
Additionally, resolved a crash in the software engine's post-effect process
caused by a buffer size mismatch during XY buffer flipping.
issue: https://github.com/thorvg/thorvg/issues/3009
issue: https://github.com/thorvg/thorvg/issues/2984
Shape's bbox represents only fill's render region.
Render region of fill and stroke is stored in SwTask.
This was visible while rendering shapes with a stroke -
fill was to big.
@Issue: https://github.com/thorvg/thorvg/issues/2908
Co-Authored-By: Hermet Park <hermet@lottiefiles.com>
Since we've separated ClipPath and Masking,
Masking now has a distinct and independent purpose.
API Modification:
- enum class CompositeMethod -> enum class MaskMethod
- Result Paint::composite(std::unique_ptr<Paint> target, CompositeMethod method) -> Result Paint::mask(std::unique_ptr<Paint> target, MaskMethod method)
- CompositeMethod Paint::mask(const Paint** target) const -> MaskMethod Paint::mask(const Paint** target) const
issue: https://github.com/thorvg/thorvg/issues/1372
shape render region should be aligned with the
current shape bbox. this could bring the compact size
of the rendering region even shapes are not drawable.