odin-blend2d

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

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