33#include <unordered_map>
63 void BeginDrawing()
override;
64 void EndDrawing()
override;
66 void ResizeScreen(
int aWidth,
int aHeight )
override;
67 void Flush()
override;
68 void ClearScreen()
override;
74 void StartDiffLayer()
override;
75 void EndDiffLayer()
override;
76 void StartNegativesLayer()
override;
77 void EndNegativesLayer()
override;
78 void SetNegativeDrawMode(
bool aSetting )
override;
89 m_strokePixelPad =
static_cast<uint16_t
>( std::clamp( std::lround( aPixels * 16.0 ), 0
L, 65535L ) );
96 void BitmapText(
const wxString& aText,
const VECTOR2I& aPosition,
const EDA_ANGLE& aAngle )
override;
101 void DrawGrid()
override;
102 void DrawCursor(
const VECTOR2D& aCursorPosition )
override;
104 int BeginGroup()
override;
105 void EndGroup()
override;
106 std::array<uint64_t, 2> GroupContentFingerprint(
int aGroupNumber )
const override;
107 void DrawGroup(
int aGroupNumber )
override;
108 void ChangeGroupColor(
int aGroupNumber,
const COLOR4D& aNewColor )
override;
109 void ChangeGroupDepth(
int aGroupNumber,
int aDepth )
override;
110 void ChangeGroupUndimmed(
int aGroupNumber,
bool aUndimmed )
override;
111 void DeleteGroup(
int aGroupNumber )
override;
112 void ClearCache()
override;
114 void SetSceneLayerState(
int aLayer,
int aOrder,
bool aVisible,
bool aHasNegatives )
override;
115 void SetSceneLayerDim(
int aLayer,
const COLOR4D& aToward,
double aKeep )
override;
116 void SetSceneLayerOverlayAlpha(
int aLayer )
override;
117 void SetSceneDrawOrdered(
bool aOrdered )
override;
118 void BeginSceneLayer(
int aLayer )
override;
119 void SetGroupPlacement(
int aGroup,
int aLayer,
double aLodScale,
bool aShown,
121 void SetSceneScale(
double aScale )
override;
131 void Save()
override;
132 void Restore()
override;
133 void Transform(
const MATRIX3x3D& aTransformation )
override;
134 void Rotate(
double aAngle )
override;
135 void Translate(
const VECTOR2D& aTranslation )
override;
136 void Scale(
const VECTOR2D& aScale )
override;
138 void SetLayerDepth(
double aLayerDepth )
override;
140 int GetSwapInterval()
const override;
169 static std::shared_ptr<RENDER_THREAD> AcquireRenderThread(
bool aEnableValidation );
172 static uint32_t AllocateWindowId();
178 void DestroyBuffers();
185 bs.buffer.fill( {} );
186 bs.capacity.fill( 0 );
188 for(
auto& bq : bs.bitmapQuads )
191 bq.vertexBuffer = {};
212 layer.polygons.buffer = {};
213 layer.polygons.capacity = 0;
221 void DrawLine(
const VECTOR2D& aStartPoint,
const VECTOR2D& aEndPoint )
override;
223 double aWidth )
override;
225 double aWidth,
const COLOR4D& aColor )
override;
226 void DrawPad(
const VECTOR2D& aCenter,
double aHalfWidth,
double aHalfHeight,
227 double aCornerRadius,
float aShapeType,
double aRotation,
228 const COLOR4D& aColor )
override;
229 void DrawSegmentChain(
const std::vector<VECTOR2D>& aPointList,
double aWidth )
override;
230 void DrawSegmentChain(
const SHAPE_LINE_CHAIN& aLineChain,
double aWidth )
override;
232 void DrawArc(
const VECTOR2D& aCenterPoint,
double aRadius,
234 void DrawArcSegment(
const VECTOR2D& aCenterPoint,
double aRadius,
236 double aWidth,
double aMaxError )
override;
238 void DrawCircle(
const VECTOR2D& aCenterPoint,
double aRadius )
override;
239 void DrawEllipse(
const VECTOR2D& aCenterPoint,
double aMajorRadius,
double aMinorRadius,
241 void DrawEllipseArc(
const VECTOR2D& aCenterPoint,
double aMajorRadius,
double aMinorRadius,
244 void DrawHoleWall(
const VECTOR2D& aCenterPoint,
double aHoleRadius,
245 double aWallWidth )
override;
246 void DrawRectangle(
const VECTOR2D& aStartPoint,
const VECTOR2D& aEndPoint )
override;
247 void DrawPolygon(
const std::deque<VECTOR2D>& aPointList )
override;
248 void DrawPolygon(
const VECTOR2D aPointList[],
int aListSize )
override;
249 void DrawPolygon(
const SHAPE_POLY_SET& aPolySet,
bool aStrokeTriangulation =
false )
override;
252 void DrawCurve(
const VECTOR2D& aStartPoint,
const VECTOR2D& aControlPointA,
254 double aFilterValue = 0.0 )
override;
256 void DrawBitmap(
const BITMAP_BASE& aBitmap,
double alphaBlend = 1.0 )
override;
258 void DrawPolyline(
const std::deque<VECTOR2D>& aPointList )
override;
259 void DrawPolyline(
const std::vector<VECTOR2D>& aPointList )
override;
260 void DrawPolyline(
const VECTOR2D aPointList[],
int aListSize )
override;
262 void DrawPolylines(
const std::vector<std::vector<VECTOR2D>>& aPointLists )
override;
264 void DrawGlyph(
const KIFONT::GLYPH& aGlyph,
int aNth = 0,
int aTotal = 1 )
override;
288 static constexpr int arenaOf(
int aShape,
bool aNegative ) {
return 2 * aShape + ( aNegative ? 1 : 0 ); }
316 std::optional<std::multimap<double, int>::iterator>
lodEntry;
331 void ReleaseRetiredBuffers( uint64_t aConsumedGeneration );
369 void beginUpdate()
override;
370 void endUpdate()
override;
405 && m[1][0] == 0.0 && m[1][1] == 1.0 && m[1][2] == 0.0
406 && m[2][0] == 0.0 && m[2][1] == 0.0 && m[2][2] == 1.0;
436 void releaseBitmapQuads( std::vector<BITMAP_QUAD>& aQuads,
bool aOwnedOnly );
439 bool drawBitmapGlyphs(
const wxString& aText,
const VECTOR2I& aPosition,
const EDA_ANGLE& aAngle );
442 double aWidth,
const COLOR4D& aColor );
446 double aSweepAngle,
double aWidth,
const COLOR4D& aColor );
449 double aCornerRadius,
float aShapeType,
double aRotation,
474 size_t aNeeded,
size_t aStride );
501 sizes[shape] =
static_cast<uint32_t
>(
instances[shape].size() );
509 return std::ranges::all_of(
Sizes(), []( uint32_t aSize ) {
return aSize == 0; } )
515 for( std::vector<RHI_INSTANCE>& shape :
instances )
526 std::array<RHI_BufferHandle, RHI_SHAPES>
buffer;
581 void drawGridSources();
585 double screenPixelSize()
const;
621 void add( uint32_t aStart, uint32_t aCount )
627 end = std::max(
end, aStart + aCount );
635 template <
typename T>
636 void submitSpan(
const std::vector<T>& aElements,
RHI_BufferHandle aBuffer,
const PATCH_SPAN& aSpan );
655 template <
typename INSTANCE_FN,
typename VERTEX_FN>
656 bool patchStaticGroup(
int aGroup, INSTANCE_FN aInstance, VERTEX_FN aVertex );
659 void rewriteResidentGroup(
int aGroupNumber, GAL_GROUP& aGroup );
666 template <
typename T>
678 std::unordered_map<uint32_t, std::vector<uint32_t>>
freeSlots;
714 std::vector<POLARITY_RUN>
runs;
730 static std::shared_ptr<const RHI_RUN_TABLE> updateSceneCullRuns( SCENE_LAYER& aLayer );
733 void buildSceneRuns( SCENE_LAYER& aLayer );
759 template <
typename T>
762 template <
typename T>
765 template <
typename T>
769 template <
typename T>
849 void countBitmapRefs(
const GAL_GROUP& aGroup,
int aDelta );
855 bool assignSlicesByOrder( std::vector<LAYER_RANGE>& aRanges,
size_t aFirst )
const;
864 void notePolarity(
bool aNegative );
924 void beginLayerRange(
float aDepth );
This class handle bitmap images in KiCad.
A color representation with 4 components: red, green, blue, alpha.
GEOMETRY_BUFFER_SET m_gridPool
The grids of the grid items, which the static target draws over the grid and under all else.
static void countGroupArenas(const GAL_GROUP &aGroup, uint32_t *aCounts)
Fill aCounts with how many of a group's instances go in each instance arena.
bool keepsRelativeDepth(const GEOMETRY_BUFFER_SET &aPool) const
The pool is a kept target whose ranges are drawn in depth slices, see Flush()
double xformAngle() const
void countGroupAlpha(const GAL_GROUP &aGroup, SCENE_LAYER &aLayer, int aDelta)
void SetScreenSpaceMode(bool aEnabled) override
Store sizes of what is drawn next in pixels rather than world units, so it keeps its pixel size throu...
static std::array< uint64_t, 2 > computeGroupFingerprint(const GAL_GROUP &aGroup)
double m_bitmapTextHeight
glyph height while bitmap text is stroked, else 0
std::vector< std::pair< uint64_t, RHI_TextureHandle > > m_retiredTextures
void writeGroupToScene(const GAL_GROUP &aGroup, SCENE_LAYER &aLayer)
Copy a resident group's elements into its slots, applying the layer's hoisted alpha.
void SetCentringPad(int aPad)
The other canvases lay the view out this many pixels larger than the client area.
std::multimap< double, int > m_lodGroups
groups with a scale threshold, by it
float m_strokeLengthPad
see SetStrokeLengthPad(), 0 when off
void SetPersistentTargets(bool aPersistent)
Keep the non-cached and overlay pools across frames until ClearTarget() empties one,...
void emitInstance(RHI_SHAPE aShape, const RHI_INSTANCE &aInstance)
Append to the current target's pool.
const GEOMETRY_BUFFER_SET & poolForCurrentTarget() const
void refillDynamicTarget(RENDER_TARGET aTarget)
Rotate a dynamic target's ring, empty the new slot and open a range at the current depth.
bool m_nonCachedRefilled
non-cached pool was emptied for the frame being drawn
void evictBitmapCacheEntries()
Evict least recently used entries down to the entry and byte caps, sparing those used this frame sinc...
uint64_t m_bufferGeneration
Bumped whenever a resource is retired.
bool HasStaticRebuildPending() const override
Return true if the backend dropped its cached geometry and VIEW must draw the cached layers again,...
std::array< PATCH_SPAN, RHI_SHAPES > m_staticPatches
static bool sceneLayerComposited(const SCENE_LAYER &aLayer)
Whether a scene layer goes through the temp target and is composited with its alpha.
GEOMETRY_BUFFER_SET m_overlaySets[BUFFER_RING_SIZE]
bool retainedTieOrderChanged(int aGroupId, GAL_GROUP &aGroup, SCENE_LAYER &aLayer)
void retireBuffer(RHI_BufferHandle aBuffer)
void retireTexture(RHI_TextureHandle aTexture)
static constexpr int BUFFER_RING_SIZE
bool uploadSceneArena(SCENE_ARENA< T > &aArena)
Upload the arena's pending spans, growing its buffer first.
uint64_t m_bitmapFrameStartSeq
use counter at frame start, entries used since are pinned
MATRIX3x3D m_currentTransform
GAL_MODERN(GAL_DISPLAY_OPTIONS &aOptions, RHI_DEVICE_PROXY &aDeviceProxy)
std::vector< LAYER_RANGE > m_gridLayerRanges
bool m_transformIsIdentity
The GPU applies world to screen, so most geometry skips the matrix math on the hot path.
void SetStrokeLevelOfDetail(double aLod) override
Show every stroke drawn from now on only while the view scale is above aLod, as VIEW::IsShownAtScale(...
std::array< std::vector< RHI_INSTANCE >, RHI_INSTANCED_SHAPES > SHAPE_INSTANCES
Instances of each instanced shape, indexed by RHI_SHAPE.
GEOMETRY_BUFFER_SET m_bufferSets[BUFFER_RING_SIZE]
The non-cached pool.
uint64_t m_bitmapUseCounter
bumped on every cache touch
SCENE_LAYER * m_openSceneLayer
bool UsesPolygonTriangulationCache() const override
Return true if filled polygons are drawn from the SHAPE_POLY_SET triangulation cache,...
void SetBitmapGlyphs(bool aEnable)
Draw bitmap text as one font atlas glyph per quad, for editors whose track shader supports it.
void SetRenderThread(RENDER_THREAD *aThread)
Render thread used for fence-based synchronization.
std::vector< BITMAP_QUAD > m_groupScratchBitmapQuads
void sortSceneOrder()
Put the declared layers back in decreasing depth order after one was added or moved.
std::unordered_map< int, std::vector< STATIC_GROUP_SLOT > > m_staticGroupSlots
A group may be drawn into the static pool more than once per build, so a patch touches every slot.
const std::vector< LAYER_RANGE > & layerRangesForCurrentTarget() const
static constexpr int ARENA_INSTANCE_COUNT
Arenas of one retained scene layer.
RENDER_THREAD * m_renderThread
bool SupportsStrokePixelPad() const override
Tell whether strokes can carry part of their width in pixels, see SetStrokePixelPad().
static constexpr int arenaOf(int aShape, bool aNegative)
std::vector< std::pair< uint64_t, RHI_BufferHandle > > m_retiredBuffers
bool IsInitialized() const override
Return the initialization status for the canvas.
void appendSceneRanges(FRAME_DRAW_DESC &aDesc) const
uint16_t m_strokePixelPad
see SetStrokePixelPad(), in sixteenths of a pixel
std::vector< MATRIX3x3D > m_transformStack
static constexpr int ARENA_POLYGON
RENDER_TARGET m_currentTarget
bool m_groupNegative
the group being recorded has drawn a knockout
bool m_bitmapGlyphs
see SetBitmapGlyphs()
std::unordered_map< KIID, BITMAP_CACHE_ENTRY > m_bitmapTextureCache
void compactSceneArena(SCENE_LAYER &aLayer, SCENE_ARENA< T > &aArena, int aArenaId)
float m_dpiScale
see SetDpiScale()
const GEOMETRY_BUFFER_SET & obuf() const
RHI_DEVICE_PROXY & m_deviceProxy
std::vector< int > m_sceneOrder
layer ids in draw order
static constexpr int ARENA_COUNT
double m_strokeLod
see SetStrokeLevelOfDetail(), 0 when off
void freeSceneSlot(SCENE_ARENA< T > &aArena, uint32_t aStart, uint32_t aCount)
static constexpr size_t BITMAP_CACHE_MAX_ENTRIES
void SetStrokeLengthPad(double aPixels) override
Extend every stroke drawn from now on by aPixels at each end.
std::array< uint64_t, 2 > m_gridPoolHash
hash of what the GPU buffers hold
SHAPE_INSTANCES m_groupScratchInstances
BeginGroup() swaps these with the current pool's vectors and EndGroup() swaps them back.
bool TakeStaticChanged()
Whether the last Flush() rebuilt the static pool.
bool currentTargetOpen() const
Whether drawing to the current target lands in a pool that this frame has emptied.
std::vector< LAYER_RANGE > m_staticLayerRanges
Kept per pool so static ranges survive BeginDrawing when m_staticDirty is false.
GEOMETRY_BUFFER_SET m_staticPool
Pool for TARGET_CACHED.
const GEOMETRY_BUFFER_SET & buf() const
GEOMETRY_BUFFER_SET & poolForCurrentTarget()
TARGET_CACHED draws to the static pool and every other target to its dynamic ring slot.
void resetScene()
Empty every arena and forget residency ahead of a full rebuild.
void recomputeTransformIdentity()
Exact comparison is enough since a false negative only takes the slow path.
void placeGroupInScene(int aGroupId, GAL_GROUP &aGroup, SCENE_LAYER &aLayer)
VECTOR2D xform(const VECTOR2D &aPt) const
std::vector< LAYER_RANGE > m_overlayLayerRanges
uint32_t allocSceneSlot(SCENE_ARENA< T > &aArena, uint32_t aCount)
void MarkStaticDirty() override
Force the next Flush() to rebuild the static pool from scratch.
GEOMETRY_BUFFER_SET & obuf()
bool HasRetainedScene() const override
Return true if the backend keeps cached groups in a persistent scene that it patches in place,...
int m_centringPad
see SetCentringPad()
bool RefillsNonCachedTargets() const override
Return true if the backend empties every non-cached target each frame, so VIEW must emit them again e...
VECTOR2I GetLayoutPixelSize() const override
Return the size the view is centred in and panned by.
std::unordered_map< int, SCENE_LAYER > m_sceneLayers
by VIEW layer id
bool flushScene()
Settle hoisted alpha, compact and upload.
std::vector< RHI_VERTEX > m_groupScratchPolygonVertices
void SetStrokePixelPad(double aPixels) override
Widen every stroke, circle and pad drawn from now on by aPixels.
bool IsDrawingMode() const override
Return true if the GAL is inside a BeginDrawing/EndDrawing pair.
void clearStaticSlots()
Forget where groups sit in the static pool and the patches pending for it.
void trackGroupLod(int aGroupId, GAL_GROUP &aGroup, bool aTrack)
Keep m_lodGroups to the shown groups whose threshold a zoom can actually cross.
bool m_drawingGridSources
emissions go to m_gridPool
GEOMETRY_BUFFER_SET & buf()
bool SupportsStrokeLevelOfDetail() const override
Tell whether strokes can carry a level of detail, see SetStrokeLevelOfDetail().
double xformScale() const
std::vector< LAYER_RANGE > & layerRangesForCurrentTarget()
bool SupportsStrokeLengthPad() const override
Tell whether strokes can be longer by a number of pixels, see SetStrokeLengthPad().
void SetDpiScale(float aScale)
Backing-store scale factor, 2.0 on Retina.
void ReleaseBuffers()
Drop all GPU handles without destroying them.
std::unordered_map< int, GAL_GROUP > m_groups
std::vector< LAYER_RANGE > m_dynamicLayerRanges
void removeGroupFromScene(int aGroupId, GAL_GROUP &aGroup)
bool m_staticRebuiltThisFlush
see TakeStaticChanged()
bool SupportsTypedPads() const override
Return true if DrawPad() renders every standard pad shape.
VECTOR2I m_screenSize
Screen size in screen (wx logical) coordinates.
VECTOR2D m_gridSize
The grid size.
bool m_gridVisibility
Should the grid be shown.
GAL(GAL_DISPLAY_OPTIONS &aOptions)
Thread that owns the RHI device.
UI-thread access to GPU resources without touching the device, which only the render thread may mutat...
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
MATRIX3x3< double > MATRIX3x3D
The Cairo implementation of the graphics abstraction layer.
RHI_SHAPE
Shapes a frame draws, each with its own array and pipelines.
RENDER_TARGET
RENDER_TARGET: Possible rendering targets.
@ TARGET_CACHED
Main rendering target (cached)
@ TARGET_OVERLAY
Items that may change while the view stays the same (noncached)
std::array< uint32_t, RHI_SHAPES > RHI_SHAPE_COUNTS
Elements of each shape, indexed by RHI_SHAPE.
constexpr int RHI_INSTANCED_SHAPES
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
void DrawSegment(const ROUND_SEGMENT_2D &aSegment, unsigned int aNrSidesPerCircle)
Draw a thick line segment with rounded ends.
RHI_HANDLE< RHI_TAG_TEXTURE > RHI_TextureHandle
RHI_HANDLE< RHI_TAG_BUFFER > RHI_BufferHandle
GPU geometry of one frame, built by GAL_MODERN after EndDrawing() and passed through the FRAME_MAILBO...
GPU texture per bitmap, keyed on the image KIID so redrawing reuses the upload.
uint32_t groupRefs
quads of cached groups drawing this texture
std::array< uint64_t, 2 > contentHash
RHI_TextureHandle texture
size_t bytes
texture memory, which can be less than the image takes
uint64_t lastUse
use counter for LRU eviction
bool ownsTexture
false when the shared cache owns the texture
std::array< uint64_t, 2 > contentHash
RHI_BufferHandle vertexBuffer
RHI_TextureHandle texture
bool ownsResources
false for group copies, which own nothing
uint32_t slotCount[ARENA_COUNT]
std::vector< RHI_VERTEX > polygonVertices
RETAINED_GROUP_ORDER order
float baseDepth
Layer depth the group was cached at.
uint64_t placeSeq
When the group was placed in the scene, which orders a layer's polarity runs.
bool contentFingerprintValid
std::vector< BITMAP_QUAD > bitmapQuads
bool undimmed
Keeps its colour when its layer is dimmed, see ChangeGroupUndimmed.
SHAPE_INSTANCES instances
uint32_t slotStart[ARENA_COUNT]
bool negative
Recorded as a knockout, so it erases instead of drawing.
bool resident
Slot held in each arena of sceneLayer while resident.
int sceneLayer
Placement in the retained scene, set by SetGroupPlacement.
std::array< uint64_t, 2 > contentFingerprint
std::optional< std::multimap< double, int >::iterator > lodEntry
Entry in m_lodGroups while a zoom can show or hide the group.
bool drawsNegative
polarity of the last element drawn
std::vector< POLARITY_RUN > polarityRuns
built from the marks by Flush()
std::array< size_t, RHI_SHAPES > capacity
std::shared_ptr< const RHI_RUN_TABLE > cullRuns
Bounds of the arrays above as last processed, for culling off-screen runs.
RHI_SHAPE_COUNTS Sizes() const
RHI_SHAPE_COUNTS lastCount
Elements of each shape as last processed, normal and negative.
std::vector< RHI_VERTEX > polygonVertices
std::array< RHI_BufferHandle, RHI_SHAPES > buffer
SHAPE_INSTANCES instances
std::vector< POLARITY_MARK > polarityMarks
RHI_SHAPE_COUNTS lastNegCount
std::vector< BITMAP_QUAD > bitmapQuads
Half-open index span touched by patches since the last upload, empty when end <= begin.
void add(uint32_t aStart, uint32_t aCount)
A point in a pool's drawing order where the polarity of what is drawn changes.
int range
index of the layer range that was open
RHI_SHAPE_COUNTS at
elements of each shape drawn before it
Retained scene arena holding one slot per placed group, patched in place so changing one item uploads...
std::vector< PATCH_SPAN > dirty
spans to upload at the next Flush
std::unordered_map< uint32_t, std::vector< uint32_t > > freeSlots
Freed slot starts by slot length, reused last-in first-out so a group re-cached with the same size ge...
uint32_t dead
elements sitting in freed slots
std::vector< T > elements
CPU mirror of the GPU buffer, dead slots included.
size_t capacity
elements the GPU buffer can hold
bool translucent
some element is drawn with less than full alpha
bool visible
hidden layers keep their groups but are not uploaded
bool overlayAlpha
see SetSceneLayerOverlayAlpha
bool inOrder
declared, so it has a place in the draw order
std::vector< POLARITY_RUN > runs
The layer's content in the order and polarity it was placed in.
int bakedAlpha
hoisted alpha, or -1 when elements keep their own
uint32_t alphaCount[256]
Elements per alpha value.
std::vector< int > residents
groups holding a slot here
SCENE_ARENA< RHI_VERTEX > polygons
uint32_t knockoutGroups
residents recorded as knockouts
size_t cullCounted[ARENA_COUNT]
Elements each arena held when cullRuns was counted.
std::shared_ptr< const RHI_RUN_TABLE > cullRuns
Bounds of the arenas as last uploaded, for culling off-screen runs.
SCENE_ARENA< RHI_INSTANCE > instances[ARENA_INSTANCE_COUNT]
std::vector< int > bitmapResidents
the residents that carry bitmap quads
std::optional< std::unordered_multimap< size_t, int > > retainedPrefixIndex
Where a cached group landed in the static pool at the last full build, so a colour or depth change is...
Render-time projection of a grid: GRID_GEOMETRY (kind/origin/pitch/orientation/extent) plus rendering...
Fade of a whole layer towards a colour, laid out as the push constants of layer_dim....
Per-instance data for instanced 2D rendering, packed into 40 bytes.
Position is in world coordinates, color is premultiplied alpha and u, v hold half floats.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D