odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

renderfetchdata_p.h (7375B)


      1 // This file is part of Blend2D project <https://blend2d.com>
      2 //
      3 // See blend2d.h or LICENSE.md for license and copyright information
      4 // SPDX-License-Identifier: Zlib
      5 
      6 #ifndef BLEND2D_RASTER_RENDERFETCHDATA_P_H_INCLUDED
      7 #define BLEND2D_RASTER_RENDERFETCHDATA_P_H_INCLUDED
      8 
      9 #include "../raster/rasterdefs_p.h"
     10 
     11 //! \cond INTERNAL
     12 //! \addtogroup blend2d_raster_engine_impl
     13 //! \{
     14 
     15 namespace bl::RasterEngine {
     16 
     17 //! A small struct that precedes `Pipeline::FetchData` in `RenderFetchData` struct.
     18 //!
     19 //! When a pipeline signature is built, there is a lot of unknowns and in general two code paths to build SOLID
     20 //! and NON-SOLID pipelines. However, it's just a detail and the only thing that NON-SOLID render call needs is
     21 //! to make sure that FetchData has been properly setup. This is only problem when rendering with a default fill
     22 //! or stroke style, because in order to make style assignment fast, some calculations are postponed up to the place
     23 //! we would hit once we know that the style is really going to be used - in general, some properties are materialized
     24 //! lazily.
     25 //!
     26 //! To make this materialization simpler, we have a little prefix before a real `Pipeline::FetchData` that contains
     27 //! a signature (other members are here just to use the space as FetchData should be aligned to 16 bytes, so we need
     28 //! a 16 byte prefix as well). When the signature has only a PendingFlag set, it means that the FetchData hasn't been
     29 //! setup yet and it has to be setup before the pipeline signature can be obtained.
     30 //!
     31 //! \note In some cases, this header can be left uninitialized in a single-threaded rendering in case that the
     32 //! FetchData is constructed in place and allocated statically. In general, if it doesn't survive the render call
     33 //! (which happens in single-threaded rendering a lot) then these fields are not really needed.
     34 struct RenderFetchDataHeader {
     35   //! \name Members
     36   //! \{
     37 
     38   //! Signature if the fetch data is initialized, otherwise a Signature with PendingFlag bit set (last MSB).
     39   Pipeline::Signature signature;
     40   //! Batch id.
     41   uint32_t batch_id;
     42   //! Non-atomic reference count (never manipulated concurrently by multiple threads, usually the user thread only).
     43   uint32_t ref_count;
     44 
     45   union {
     46     uint32_t packed;
     47 
     48     struct {
     49       //! Pixel format of the source (possibly resolved to FRGB/ZERO, etc).
     50       uint8_t format;
     51       //! Extra bits, which can be used by the rendering engine to store some essential information required to materialize
     52       //! the FetchData.
     53       uint8_t custom[3];
     54     };
     55   } extra;
     56 
     57   //! \}
     58 
     59   //! \name Initialization
     60   //! \{
     61 
     62   //! Initializes the fetch data header by resetting all header members and initializing the reference count to `rc`.
     63   BL_INLINE void init_header(uint32_t rc, FormatExt format = FormatExt::kNone) noexcept {
     64     signature.reset();
     65     batch_id = 0;
     66     ref_count = rc;
     67     extra.packed = 0;
     68     extra.format = uint8_t(format);
     69   }
     70 
     71   //! \}
     72 
     73   //! \name Accessors
     74   //! \{
     75 
     76   BL_INLINE_NODEBUG bool is_solid() const noexcept { return signature.is_solid(); }
     77 
     78   BL_INLINE void retain(uint32_t n = 1) noexcept { ref_count += n; }
     79 
     80   BL_INLINE_NODEBUG const void* get_pipeline_data() const noexcept {
     81     return reinterpret_cast<const uint8_t*>(this) + sizeof(RenderFetchDataHeader);
     82   }
     83 
     84   //! \}
     85 };
     86 
     87 BL_STATIC_ASSERT(sizeof(RenderFetchDataHeader) == 16);
     88 
     89 //! FetchData that can only hold a solid color.
     90 struct RenderFetchDataSolid : public RenderFetchDataHeader {
     91   Pipeline::FetchData::Solid pipeline_data;
     92 };
     93 
     94 //! Raster context fetch data.
     95 //!
     96 //! Contains pipeline fetch data and additional members that are required by
     97 //! the rendering engine for proper pipeline construction and memory management.
     98 struct alignas(16) RenderFetchData : public RenderFetchDataHeader {
     99   //! \name Types
    100   //! \{
    101 
    102   typedef void (BL_CDECL* DestroyFunc)(BLRasterContextImpl* ctx_impl, RenderFetchData* fetch_data) noexcept;
    103 
    104   //! \}
    105 
    106   //! \name Members
    107   //! \{
    108 
    109   //! Fetch data part, which is used by pipelines.
    110   Pipeline::FetchData pipeline_data;
    111 
    112   //! Link to the external object holding the style data (BLImage or BLGradient).
    113   BLObjectCore style;
    114 
    115   //! Releases this fetch_data to the rendering context, can only be called if the reference count is decreased
    116   //! to zero. Don't use manually.
    117   DestroyFunc destroy_func;
    118 
    119   //! \}
    120 
    121   //! \name Accessors
    122   //! \{
    123 
    124   BL_INLINE_NODEBUG bool is_pending() const noexcept { return signature.has_pending_flag(); }
    125   BL_INLINE_NODEBUG Pipeline::FetchType fetch_type() const noexcept { return signature.fetch_type(); }
    126 
    127   template<typename T>
    128   BL_INLINE_NODEBUG const T& style_as() const noexcept { return static_cast<const T&>(style); }
    129 
    130   BL_INLINE_NODEBUG const BLImage& image() const noexcept { return static_cast<const BLImage&>(style); }
    131   BL_INLINE_NODEBUG const BLPattern& pattern() const noexcept { return static_cast<const BLPattern&>(style); }
    132   BL_INLINE_NODEBUG const BLGradient& gradient() const noexcept { return static_cast<const BLGradient&>(style); }
    133 
    134   //! \}
    135 
    136   //! \name Initialization
    137   //! \{
    138 
    139   BL_INLINE void init_style_object(const BLObjectCore* src) noexcept { style._d = src->_d; }
    140   BL_INLINE void init_destroy_func(DestroyFunc fn) noexcept { destroy_func = fn; }
    141 
    142   BL_INLINE void init_style_object_and_destroy_func(const BLObjectCore* src, DestroyFunc fn) noexcept {
    143     init_style_object(src);
    144     init_destroy_func(fn);
    145   }
    146 
    147   BL_INLINE void init_image_source(const BLImageImpl* image_impl, const BLRectI& area) noexcept {
    148     BL_ASSERT(area.x >= 0);
    149     BL_ASSERT(area.y >= 0);
    150     BL_ASSERT(area.w >= 0);
    151     BL_ASSERT(area.h >= 0);
    152 
    153     const uint8_t* src_pixel_data = static_cast<const uint8_t*>(image_impl->pixel_data);
    154     intptr_t src_stride = image_impl->stride;
    155     uint32_t src_bytes_per_pixel = image_impl->depth / 8u;
    156     Pipeline::FetchUtils::init_image_source(pipeline_data.pattern,
    157       (src_pixel_data + intptr_t(uint32_t(area.y)) * src_stride) + uint32_t(area.x) * src_bytes_per_pixel, image_impl->stride, area.w, area.h);
    158   }
    159 
    160   // Initializes `fetch_data` for a blit. Blits are never repeating and are always 1:1 (no scaling, no fractional translation).
    161   BL_INLINE bool setup_pattern_blit(int tx, int ty) noexcept {
    162     signature = Pipeline::FetchUtils::init_pattern_blit(pipeline_data.pattern, tx, ty);
    163     return true;
    164   }
    165 
    166   BL_INLINE bool setup_pattern_fx_fy(BLExtendMode extend_mode, BLPatternQuality quality, uint32_t bytes_per_pixel, int64_t tx_fixed, int64_t ty_fixed) noexcept {
    167     signature = Pipeline::FetchUtils::init_pattern_fx_fy(pipeline_data.pattern, extend_mode, quality, bytes_per_pixel, tx_fixed, ty_fixed);
    168     return true;
    169   }
    170 
    171   BL_INLINE bool setup_pattern_affine(BLExtendMode extend_mode, BLPatternQuality quality, uint32_t bytes_per_pixel, const BLMatrix2D& transform) noexcept {
    172     signature = Pipeline::FetchUtils::init_pattern_affine(pipeline_data.pattern, extend_mode, quality, bytes_per_pixel, transform);
    173     return !signature.has_pending_flag();
    174   }
    175 
    176   //! \}
    177 
    178   //! \name Reference Counting
    179   //! \{
    180 
    181   BL_INLINE void release(BLRasterContextImpl* ctx_impl) noexcept {
    182     if (--ref_count == 0)
    183       destroy_func(ctx_impl, this);
    184   }
    185 
    186   //! \}
    187 };
    188 
    189 BL_HIDDEN BLResult compute_pending_fetch_data(RenderFetchData* fetch_data) noexcept;
    190 
    191 } // {bl::RasterEngine}
    192 
    193 //! \}
    194 //! \endcond
    195 
    196 #endif // BLEND2D_RASTER_RENDERFETCHDATA_P_H_INCLUDED