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