rastercontext_p.h (13560B)
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_RASTERCONTEXT_P_H_INCLUDED 7 #define BLEND2D_RASTER_RASTERCONTEXT_P_H_INCLUDED 8 9 #include "../api-internal_p.h" 10 #include "../compopinfo_p.h" 11 #include "../context_p.h" 12 #include "../font_p.h" 13 #include "../gradient_p.h" 14 #include "../matrix_p.h" 15 #include "../path_p.h" 16 #include "../rgba.h" 17 #include "../pipeline/piperuntime_p.h" 18 #include "../raster/analyticrasterizer_p.h" 19 #include "../raster/edgebuilder_p.h" 20 #include "../raster/rasterdefs_p.h" 21 #include "../raster/rendercommand_p.h" 22 #include "../raster/renderfetchdata_p.h" 23 #include "../raster/renderjob_p.h" 24 #include "../raster/renderqueue_p.h" 25 #include "../raster/rendertargetinfo_p.h" 26 #include "../raster/statedata_p.h" 27 #include "../raster/styledata_p.h" 28 #include "../raster/workdata_p.h" 29 #include "../raster/workermanager_p.h" 30 #include "../support/arenaallocator_p.h" 31 #include "../threading/uniqueidgenerator_p.h" 32 33 #if !defined(BL_BUILD_NO_JIT) 34 #include "../pipeline/jit/pipegenruntime_p.h" 35 #endif 36 37 //! \cond INTERNAL 38 //! \addtogroup blend2d_raster_engine_impl 39 //! \{ 40 41 //! Preferred fill-rule (fastest) to use when the fill-rule doesn't matter. 42 //! 43 //! Since the filler doesn't care of fill-rule (it always uses the same code-path for non-zero and even-odd fills) it 44 //! doesn't really matter. However, if there is more rasterizers added in the future this can be adjusted to always 45 //! select the fastest one. 46 static constexpr const BLFillRule BL_RASTER_CONTEXT_PREFERRED_FILL_RULE = BL_FILL_RULE_EVEN_ODD; 47 48 //! Preferred extend mode (fastest) to use when blitting images. The extend mode can be either PAD or REFLECT as these 49 //! have the same effect on blits that are bound to the size of the image. We prefer REFLECT, because it's useful also 50 //! outside regular blits. 51 static constexpr const BLExtendMode BL_RASTER_CONTEXT_PREFERRED_BLIT_EXTEND = BL_EXTEND_MODE_REFLECT; 52 53 //! Minimum size of a path (in vertices) to make it an asynchronous job. The reason for this threshold is that very 54 //! small paths actually do not benefit from being dispatched into a worker thread (the cost of serializing the job 55 //! is higher than the cost of processing that path in a user thread). 56 static constexpr const uint32_t BL_RASTER_CONTEXT_MINIMUM_ASYNC_PATH_SIZE = 10; 57 58 //! Maximum size of a text to be copied as is when dispatching asynchronous jobs. When the limit is reached the job 59 //! serialized would create a BLGlyphBuffer instead of making raw copy of the text, as the glyph-buffer has to copy 60 //! it anyway. 61 static constexpr const uint32_t BL_RASTER_CONTEXT_MAXIMUM_EMBEDDED_TEXT_SIZE = 256; 62 63 static constexpr const uint32_t BL_RASTER_CONTEXT_DEFAULT_SAVED_STATE_LIMIT = 4096; 64 65 static constexpr const uint32_t BL_RASTER_CONTEXT_DEFAULT_COMMAND_QUEUE_LIMIT = 10240; 66 67 //! Raster rendering context implementation (software accelerated). 68 class BLRasterContextImpl : public BLContextImpl { 69 public: 70 BL_NONCOPYABLE(BLRasterContextImpl) 71 72 //! \name Members 73 //! \{ 74 75 //! Context flags. 76 bl::RasterEngine::ContextFlags context_flags; 77 //! Rendering mode. 78 uint8_t rendering_mode; 79 //! Whether worker_mgr has been initialized. 80 uint8_t worker_mgr_initialized; 81 //! Precision information. 82 bl::RasterEngine::RenderTargetInfo render_target_info; 83 84 //! Work data used by synchronous rendering that also holds part of the current state. In async mode the work data 85 //! can still be used by user thread in case it's allowed, otherwise it would only hold some states that are used 86 //! by the rendering context directly. 87 bl::RasterEngine::WorkData sync_work_data; 88 89 //! Pipeline lookup cache (always used before attempting to use `pipe_provider`). 90 bl::Pipeline::PipeLookupCache pipe_lookup_cache; 91 92 //! Composition operator simplification that matches the destination format and current `comp_op`. 93 const bl::CompOpSimplifyInfo* comp_op_simplify_info; 94 //! Solid format table used to select the best pixel format for solid fills. 95 uint8_t solid_format_table[BL_RASTER_CONTEXT_SOLID_FORMAT_COUNT]; 96 //! Table that can be used to override a fill/stroke color by one from SolidId (after a simplification). 97 bl::RasterEngine::RenderFetchDataSolid* solid_override_fill_table; 98 //! Solid fill override table indexed by \ref bl::CompOpSolidId. 99 bl::RasterEngine::RenderFetchDataHeader* solid_fetch_data_override_table[uint32_t(bl::CompOpSolidId::kAlwaysNop) + 1u]; 100 101 //! The current state of the rendering context, the `BLContextState` part is public. 102 bl::RasterEngine::RasterContextState internal_state; 103 //! Link to the previous saved state that will be restored by `BLContext::restore()`. 104 bl::RasterEngine::SavedState* saved_state; 105 //! An actual shared fill-state (asynchronous rendering). 106 bl::RasterEngine::SharedFillState* shared_fill_state; 107 //! An actual shared stroke-state (asynchronous rendering). 108 bl::RasterEngine::SharedBaseStrokeState* shared_stroke_state; 109 110 //! Arena allocator used to allocate base data structures required by `BLRasterContextImpl`. 111 bl::ArenaAllocator base_zone; 112 //! Object pool used to allocate `RenderFetchData`. 113 bl::ArenaPool<bl::RasterEngine::RenderFetchData> fetch_data_pool; 114 //! Object pool used to allocate `SavedState`. 115 bl::ArenaPool<bl::RasterEngine::SavedState> saved_state_pool; 116 117 //! Pipeline runtime (either global or isolated, depending on create-options). 118 bl::Pipeline::PipeProvider pipe_provider; 119 //! Worker manager (only used by asynchronous rendering context). 120 bl::Wrap<bl::RasterEngine::WorkerManager> worker_mgr; 121 122 //! Context origin ID used in `data0` member of `BLContextCookie`. 123 uint64_t context_origin_id; 124 //! Used to generate unique IDs of this context. 125 uint64_t state_id_counter; 126 127 //! The number of states that can be saved by `BLContext::save()` call. 128 uint32_t saved_state_limit; 129 130 //! Destination image. 131 BLImageCore dst_image; 132 //! Destination image data. 133 BLImageData dst_data; 134 135 //! Minimum safe coordinate for integral transformation (scaled by 256.0 or 65536.0). 136 double fp_min_safe_coord_d; 137 //! Maximum safe coordinate for integral transformation (scaled by 256.0 or 65536.0). 138 double fp_max_safe_coord_d; 139 140 //! Pointers to essential transformations that can be applied to styles. 141 const BLMatrix2D* transform_ptrs[BL_CONTEXT_STYLE_TRANSFORM_MODE_MAX_VALUE + 1u]; 142 143 //! \} 144 145 //! \name Construction & Destruction 146 //! \{ 147 148 BL_INLINE BLRasterContextImpl(BLContextVirt* virt_in, void* static_data, size_t static_size) noexcept 149 : context_flags(bl::RasterEngine::ContextFlags::kNoFlagsSet), 150 rendering_mode(uint8_t(bl::RasterEngine::RenderingMode::kSync)), 151 worker_mgr_initialized(false), 152 render_target_info {}, 153 sync_work_data(this, nullptr), 154 pipe_lookup_cache{}, 155 comp_op_simplify_info{}, 156 solid_format_table{}, 157 solid_override_fill_table{}, 158 solid_fetch_data_override_table{}, 159 saved_state{}, 160 shared_fill_state{}, 161 shared_stroke_state{}, 162 base_zone(8192, 16, static_data, static_size), 163 fetch_data_pool(), 164 saved_state_pool(), 165 pipe_provider(), 166 context_origin_id(BLUniqueIdGenerator::generate_id(BLUniqueIdGenerator::Domain::kContext)), 167 state_id_counter(0), 168 saved_state_limit(0), 169 dst_image{}, 170 dst_data{}, 171 fp_min_safe_coord_d(0.0), 172 fp_max_safe_coord_d(0.0) { 173 174 // Initializes BLRasterContext2DImpl. 175 virt = virt_in; 176 context_type = BL_CONTEXT_TYPE_RASTER; 177 state = &internal_state; 178 transform_ptrs[BL_CONTEXT_STYLE_TRANSFORM_MODE_USER] = &internal_state.final_transform; 179 transform_ptrs[BL_CONTEXT_STYLE_TRANSFORM_MODE_META] = &internal_state.meta_transform; 180 transform_ptrs[BL_CONTEXT_STYLE_TRANSFORM_MODE_NONE] = &bl::TransformInternal::identity_transform; 181 } 182 183 BL_INLINE ~BLRasterContextImpl() noexcept { 184 destroy_worker_mgr(); 185 } 186 187 //! \} 188 189 //! \name Memory Management 190 //! \{ 191 192 BL_INLINE_NODEBUG bl::ArenaAllocator& fetch_data_zone() noexcept { return base_zone; } 193 BL_INLINE_NODEBUG bl::ArenaAllocator& saved_state_zone() noexcept { return base_zone; } 194 195 BL_INLINE bl::RasterEngine::RenderFetchData* alloc_fetch_data() noexcept { return fetch_data_pool.alloc(fetch_data_zone()); } 196 BL_INLINE void free_fetch_data(bl::RasterEngine::RenderFetchData* fetch_data) noexcept { fetch_data_pool.free(fetch_data); } 197 198 BL_INLINE bl::RasterEngine::SavedState* alloc_saved_state() noexcept { return saved_state_pool.alloc(saved_state_zone()); } 199 BL_INLINE void free_saved_state(bl::RasterEngine::SavedState* state) noexcept { saved_state_pool.free(state); } 200 201 BL_INLINE void ensure_worker_mgr() noexcept { 202 if (!worker_mgr_initialized) { 203 worker_mgr.init(); 204 worker_mgr_initialized = true; 205 } 206 } 207 208 BL_INLINE void destroy_worker_mgr() noexcept { 209 if (worker_mgr_initialized) { 210 worker_mgr.destroy(); 211 worker_mgr_initialized = false; 212 } 213 } 214 215 //! \} 216 217 //! \name Context Accessors 218 //! \{ 219 220 BL_INLINE_NODEBUG bool is_sync() const noexcept { return rendering_mode == uint8_t(bl::RasterEngine::RenderingMode::kSync); } 221 222 BL_INLINE_NODEBUG bl::FormatExt format() const noexcept { return bl::FormatExt(dst_data.format); } 223 BL_INLINE_NODEBUG double fp_scale_d() const noexcept { return render_target_info.fp_scale_d; } 224 BL_INLINE_NODEBUG double full_alpha_d() const noexcept { return render_target_info.full_alpha_d; } 225 226 BL_INLINE_NODEBUG uint32_t band_count() const noexcept { return sync_work_data.band_count(); } 227 BL_INLINE_NODEBUG uint32_t band_height() const noexcept { return sync_work_data.band_height(); } 228 BL_INLINE_NODEBUG uint32_t command_quantization_shift_aa() const noexcept { return sync_work_data.command_quantization_shift_aa(); } 229 BL_INLINE_NODEBUG uint32_t command_quantization_shift_fp() const noexcept { return sync_work_data.command_quantization_shift_fp(); } 230 231 //! \} 232 233 //! \name State Accessors 234 //! \{ 235 236 BL_INLINE_NODEBUG uint8_t clip_mode() const noexcept { return sync_work_data.clip_mode; } 237 238 BL_INLINE_NODEBUG uint8_t comp_op() const noexcept { return internal_state.comp_op; } 239 BL_INLINE_NODEBUG BLFillRule fill_rule() const noexcept { return BLFillRule(internal_state.fill_rule); } 240 BL_INLINE_NODEBUG const BLContextHints& hints() const noexcept { return internal_state.hints; } 241 242 BL_INLINE_NODEBUG const BLStrokeOptions& stroke_options() const noexcept { return internal_state.stroke_options.dcast(); } 243 BL_INLINE_NODEBUG const BLApproximationOptions& approximation_options() const noexcept { return internal_state.approximation_options; } 244 245 BL_INLINE_NODEBUG uint32_t global_alpha_i() const noexcept { return internal_state.global_alpha_i; } 246 BL_INLINE_NODEBUG double global_alpha_d() const noexcept { return internal_state.global_alpha; } 247 248 BL_INLINE_NODEBUG const bl::RasterEngine::StyleData* get_style(size_t index) const noexcept { return &internal_state.style[index]; } 249 250 BL_INLINE_NODEBUG const BLMatrix2D& meta_transform() const noexcept { return internal_state.meta_transform; } 251 BL_INLINE_NODEBUG BLTransformType meta_transform_type() const noexcept { return BLTransformType(internal_state.meta_transform_type); } 252 253 BL_INLINE_NODEBUG const BLMatrix2D& meta_transform_fixed() const noexcept { return internal_state.meta_transform_fixed; } 254 BL_INLINE_NODEBUG BLTransformType meta_transform_fixed_type() const noexcept { return BLTransformType(internal_state.meta_transform_fixed_type); } 255 256 BL_INLINE_NODEBUG const BLMatrix2D& user_transform() const noexcept { return internal_state.user_transform; } 257 258 BL_INLINE_NODEBUG const BLMatrix2D& final_transform() const noexcept { return internal_state.final_transform; } 259 BL_INLINE_NODEBUG BLTransformType final_transform_type() const noexcept { return BLTransformType(internal_state.final_transform_type); } 260 261 BL_INLINE_NODEBUG const BLMatrix2D& final_transform_fixed() const noexcept { return internal_state.final_transform_fixed; } 262 BL_INLINE_NODEBUG BLTransformType final_transform_fixed_type() const noexcept { return BLTransformType(internal_state.final_transform_fixed_type); } 263 264 BL_INLINE_NODEBUG const BLPointI& translation_i() const noexcept { return internal_state.translation_i; } 265 BL_INLINE_NODEBUG void set_translation_i(const BLPointI& pt) noexcept { internal_state.translation_i = pt; } 266 267 BL_INLINE_NODEBUG const BLBoxI& meta_clip_box_i() const noexcept { return internal_state.meta_clip_box_i; } 268 BL_INLINE_NODEBUG const BLBoxI& final_clip_box_i() const noexcept { return internal_state.final_clip_box_i; } 269 BL_INLINE_NODEBUG const BLBox& final_clip_box_d() const noexcept { return internal_state.final_clip_box_d; } 270 271 BL_INLINE_NODEBUG const BLBoxI& final_clip_box_fixed_i() const noexcept { return sync_work_data.edge_builder._clip_box_i; } 272 BL_INLINE_NODEBUG const BLBox& final_clip_box_fixed_d() const noexcept { return sync_work_data.edge_builder._clip_box_d; } 273 BL_INLINE_NODEBUG void set_final_clip_box_fixed_d(const BLBox& clip_box) { sync_work_data.edge_builder.set_clip_box(clip_box); } 274 275 //! \} 276 277 //! \name Error Accumulation 278 //! \{ 279 280 BL_INLINE_NODEBUG BLResult accumulate_error(BLResult error) noexcept { return sync_work_data.accumulate_error(error); } 281 282 //! \} 283 }; 284 285 BL_HIDDEN BLResult bl_raster_context_init_impl(BLContextCore* self, BLImageCore* image, const BLContextCreateInfo* options) noexcept; 286 BL_HIDDEN void bl_raster_context_on_init(BLRuntimeContext* rt) noexcept; 287 288 //! \} 289 //! \endcond 290 291 #endif // BLEND2D_RASTER_RASTERCONTEXT_P_H_INCLUDED