Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / gpu / AtlasTypes.h
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #ifndef skgpu_AtlasTypes_DEFINED
9 #define skgpu_AtlasTypes_DEFINED
10
11 #include <array>
12
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkRect.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/core/SkTypes.h"
17 #include "include/private/SkTArray.h"
18 #include "include/private/SkTo.h"
19 #include "src/core/SkIPoint16.h"
20 #include "src/core/SkTInternalLList.h"
21 #include "src/gpu/RectanizerSkyline.h"
22
23 class GrOpFlushState;
24 class TestingUploadTarget;
25
26 /**
27  * This file includes internal types that are used by all of our gpu backends for atlases.
28  */
29
30 namespace skgpu {
31
32 struct IRect16 {
33     int16_t fLeft, fTop, fRight, fBottom;
34
35     static IRect16 SK_WARN_UNUSED_RESULT MakeEmpty() {
36         IRect16 r;
37         r.setEmpty();
38         return r;
39     }
40
41     static IRect16 SK_WARN_UNUSED_RESULT MakeWH(int16_t w, int16_t h) {
42         IRect16 r;
43         r.set(0, 0, w, h);
44         return r;
45     }
46
47     static IRect16 SK_WARN_UNUSED_RESULT MakeXYWH(int16_t x, int16_t y, int16_t w, int16_t h) {
48         IRect16 r;
49         r.set(x, y, x + w, y + h);
50         return r;
51     }
52
53     static IRect16 SK_WARN_UNUSED_RESULT Make(const SkIRect& ir) {
54         IRect16 r;
55         r.set(ir);
56         return r;
57     }
58
59     int width() const { return fRight - fLeft; }
60     int height() const { return fBottom - fTop; }
61     int area() const { return this->width() * this->height(); }
62     bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
63
64     void setEmpty() { memset(this, 0, sizeof(*this)); }
65
66     void set(int16_t left, int16_t top, int16_t right, int16_t bottom) {
67         fLeft = left;
68         fTop = top;
69         fRight = right;
70         fBottom = bottom;
71     }
72
73     void set(const SkIRect& r) {
74         fLeft   = SkToS16(r.fLeft);
75         fTop    = SkToS16(r.fTop);
76         fRight  = SkToS16(r.fRight);
77         fBottom = SkToS16(r.fBottom);
78     }
79
80     void offset(int16_t dx, int16_t dy) {
81         fLeft   += dx;
82         fTop    += dy;
83         fRight  += dx;
84         fBottom += dy;
85     }
86 };
87
88 /**
89  *  Formats for masks, used by the font cache. Important that these are 0-based.
90  */
91 enum class MaskFormat : int {
92     kA8,    //!< 1-byte per pixel
93     kA565,  //!< 2-bytes per pixel, RGB represent 3-channel LCD coverage
94     kARGB,  //!< 4-bytes per pixel, color format
95
96     kLast = kARGB
97 };
98 static const int kMaskFormatCount = static_cast<int>(MaskFormat::kLast) + 1;
99
100 /**
101  *  Return the number of bytes-per-pixel for the specified mask format.
102  */
103 inline constexpr int MaskFormatBytesPerPixel(MaskFormat format) {
104     SkASSERT(static_cast<int>(format) < kMaskFormatCount);
105     // kA8   (0) -> 1
106     // kA565 (1) -> 2
107     // kARGB (2) -> 4
108     static_assert(static_cast<int>(MaskFormat::kA8) == 0, "enum_order_dependency");
109     static_assert(static_cast<int>(MaskFormat::kA565) == 1, "enum_order_dependency");
110     static_assert(static_cast<int>(MaskFormat::kARGB) == 2, "enum_order_dependency");
111
112     return SkTo<int>(1u << static_cast<int>(format));
113 }
114
115 static constexpr SkColorType MaskFormatToColorType(MaskFormat format) {
116     switch (format) {
117         case MaskFormat::kA8:
118             return kAlpha_8_SkColorType;
119         case MaskFormat::kA565:
120             return kRGB_565_SkColorType;
121         case MaskFormat::kARGB:
122             return kRGBA_8888_SkColorType;
123     }
124     SkUNREACHABLE;
125 }
126
127 /**
128  * Keep track of generation number for atlases and Plots.
129  */
130 class AtlasGenerationCounter {
131 public:
132     inline static constexpr uint64_t kInvalidGeneration = 0;
133     uint64_t next() {
134         return fGeneration++;
135     }
136
137 private:
138     uint64_t fGeneration{1};
139 };
140
141 /**
142  * DrawToken is used to sequence uploads relative to each other and to batches of draws.
143  */
144 class DrawToken {
145 public:
146     static DrawToken AlreadyFlushedToken() { return DrawToken(0); }
147
148     DrawToken(const DrawToken&) = default;
149     DrawToken& operator=(const DrawToken&) = default;
150
151     bool operator==(const DrawToken& that) const {
152         return fSequenceNumber == that.fSequenceNumber;
153     }
154     bool operator!=(const DrawToken& that) const { return !(*this == that); }
155     bool operator<(const DrawToken that) const {
156         return fSequenceNumber < that.fSequenceNumber;
157     }
158     bool operator<=(const DrawToken that) const {
159         return fSequenceNumber <= that.fSequenceNumber;
160     }
161     bool operator>(const DrawToken that) const {
162         return fSequenceNumber > that.fSequenceNumber;
163     }
164     bool operator>=(const DrawToken that) const {
165         return fSequenceNumber >= that.fSequenceNumber;
166     }
167
168     DrawToken& operator++() {
169         ++fSequenceNumber;
170         return *this;
171     }
172     DrawToken operator++(int) {
173         auto old = fSequenceNumber;
174         ++fSequenceNumber;
175         return DrawToken(old);
176     }
177
178     DrawToken next() const { return DrawToken(fSequenceNumber + 1); }
179
180     /** Is this token in the [start, end] inclusive interval? */
181     bool inInterval(const DrawToken& start, const DrawToken& end) {
182         return *this >= start && *this <= end;
183     }
184
185 private:
186     DrawToken() = delete;
187     explicit DrawToken(uint64_t sequenceNumber) : fSequenceNumber(sequenceNumber) {}
188     uint64_t fSequenceNumber;
189 };
190
191 /*
192  * The TokenTracker encapsulates the incrementing and distribution of tokens.
193  */
194 class TokenTracker {
195 public:
196     /** Gets the token one beyond the last token that has been flushed,
197         either in GrDrawingManager::flush() or Device::flushPendingWorkToRecorder() */
198     DrawToken nextTokenToFlush() const { return fLastFlushedToken.next(); }
199
200     /** Gets the next draw token. This can be used to record that the next draw
201         issued will use a resource (e.g. texture) while preparing that draw. */
202     DrawToken nextDrawToken() const { return fLastIssuedToken.next(); }
203
204 private:
205     // Only these classes get to increment the token counters
206     friend class ::GrOpFlushState;
207     friend class ::TestingUploadTarget;
208
209     /** Issues the next token for a draw. */
210     DrawToken issueDrawToken() { return ++fLastIssuedToken; }
211
212     /** Advances the last flushed token by one. */
213     DrawToken flushToken() { return ++fLastFlushedToken; }
214
215     DrawToken fLastIssuedToken = DrawToken::AlreadyFlushedToken();
216     DrawToken fLastFlushedToken = DrawToken::AlreadyFlushedToken();
217 };
218
219 /**
220  * A PlotLocator specifies the plot and is analogous to a directory path:
221  *    page/plot/plotGeneration
222  *
223  * In fact PlotLocator is a portion of a glyph image location in the atlas fully specified by:
224  *    format/atlasGeneration/page/plot/plotGeneration/rect
225  *
226  * TODO: Remove the small path renderer's use of the PlotLocator for eviction.
227  */
228 class PlotLocator {
229 public:
230     // These are both restricted by the space they occupy in the PlotLocator.
231     // maxPages is also limited by being crammed into the glyph uvs.
232     // maxPlots is also limited by the fPlotAlreadyUpdated bitfield in
233     // GrDrawOpAtlas::BulkUseTokenUpdater.
234     inline static constexpr auto kMaxMultitexturePages = 4;
235     inline static constexpr int kMaxPlots = 32;
236
237     PlotLocator(uint32_t pageIdx, uint32_t plotIdx, uint64_t generation)
238             : fGenID(generation)
239             , fPlotIndex(plotIdx)
240             , fPageIndex(pageIdx) {
241         SkASSERT(pageIdx < kMaxMultitexturePages);
242         SkASSERT(plotIdx < kMaxPlots);
243         SkASSERT(generation < ((uint64_t)1 << 48));
244     }
245
246     PlotLocator()
247             : fGenID(AtlasGenerationCounter::kInvalidGeneration)
248             , fPlotIndex(0)
249             , fPageIndex(0) {}
250
251     bool isValid() const {
252         return fGenID != 0 || fPlotIndex != 0 || fPageIndex != 0;
253     }
254
255     void makeInvalid() {
256         fGenID = 0;
257         fPlotIndex = 0;
258         fPageIndex = 0;
259     }
260
261     bool operator==(const PlotLocator& other) const {
262         return fGenID == other.fGenID &&
263                fPlotIndex == other.fPlotIndex &&
264                fPageIndex == other.fPageIndex; }
265
266     uint32_t pageIndex() const { return fPageIndex; }
267     uint32_t plotIndex() const { return fPlotIndex; }
268     uint64_t genID() const { return fGenID; }
269
270 private:
271     uint64_t fGenID:48;
272     uint64_t fPlotIndex:8;
273     uint64_t fPageIndex:8;
274 };
275
276 // AtlasLocator handles atlas position information. It keeps a left-top, right-bottom pair of
277 // encoded UV coordinates. The bits 13 & 14 of the U coordinates hold the atlas page index.
278 // This information is handed directly as is from fUVs. This encoding has the nice property
279 // that width = fUVs[2] - fUVs[0]; the page encoding in the top bits subtracts to zero.
280 class AtlasLocator {
281 public:
282     std::array<uint16_t, 4> getUVs() const {
283         return fUVs;
284     }
285
286     void invalidatePlotLocator() { fPlotLocator.makeInvalid(); }
287
288     // TODO: Remove the small path renderer's use of this for eviction
289     PlotLocator plotLocator() const { return fPlotLocator; }
290
291     uint32_t pageIndex() const { return fPlotLocator.pageIndex(); }
292
293     uint32_t plotIndex() const { return fPlotLocator.plotIndex(); }
294
295     uint64_t genID() const { return fPlotLocator.genID(); }
296
297     SkIPoint topLeft() const {
298         return {fUVs[0] & 0x1FFF, fUVs[1]};
299     }
300
301     uint16_t width() const {
302         return fUVs[2] - fUVs[0];
303     }
304
305     uint16_t height() const {
306         return fUVs[3] - fUVs[1];
307     }
308
309     void insetSrc(int padding) {
310         SkASSERT(2 * padding <= this->width());
311         SkASSERT(2 * padding <= this->height());
312
313         fUVs[0] += padding;
314         fUVs[1] += padding;
315         fUVs[2] -= padding;
316         fUVs[3] -= padding;
317     }
318
319     void updatePlotLocator(PlotLocator p) {
320         fPlotLocator = p;
321         SkASSERT(fPlotLocator.pageIndex() <= 3);
322         uint16_t page = fPlotLocator.pageIndex() << 13;
323         fUVs[0] = (fUVs[0] & 0x1FFF) | page;
324         fUVs[2] = (fUVs[2] & 0x1FFF) | page;
325     }
326
327     void updateRect(skgpu::IRect16 rect) {
328         SkASSERT(rect.fLeft <= rect.fRight);
329         SkASSERT(rect.fRight <= 0x1FFF);
330         fUVs[0] = (fUVs[0] & 0xE000) | rect.fLeft;
331         fUVs[1] = rect.fTop;
332         fUVs[2] = (fUVs[2] & 0xE000) | rect.fRight;
333         fUVs[3] = rect.fBottom;
334     }
335
336 private:
337     PlotLocator fPlotLocator{0, 0, 0};
338
339     // The inset padded bounds in the atlas in the lower 13 bits, and page index in bits 13 &
340     // 14 of the Us.
341     std::array<uint16_t, 4> fUVs{0, 0, 0, 0};
342 };
343
344 /**
345  * An interface for eviction callbacks. Whenever an atlas evicts a specific PlotLocator,
346  * it will call all of the registered listeners so they can process the eviction.
347  */
348 class PlotEvictionCallback {
349 public:
350     virtual ~PlotEvictionCallback() = default;
351     virtual void evict(PlotLocator) = 0;
352 };
353
354 /**
355  * A class which can be handed back to an atlas for updating plots in bulk.  The
356  * current max number of plots per page an atlas can handle is 32. If in the future
357  * this is insufficient then we can move to a 64 bit int.
358  */
359 class BulkUsePlotUpdater {
360 public:
361     BulkUsePlotUpdater() {
362         memset(fPlotAlreadyUpdated, 0, sizeof(fPlotAlreadyUpdated));
363     }
364     BulkUsePlotUpdater(const BulkUsePlotUpdater& that)
365             : fPlotsToUpdate(that.fPlotsToUpdate) {
366         memcpy(fPlotAlreadyUpdated, that.fPlotAlreadyUpdated, sizeof(fPlotAlreadyUpdated));
367     }
368
369     bool add(const skgpu::AtlasLocator& atlasLocator) {
370         int plotIdx = atlasLocator.plotIndex();
371         int pageIdx = atlasLocator.pageIndex();
372         if (this->find(pageIdx, plotIdx)) {
373             return false;
374         }
375         this->set(pageIdx, plotIdx);
376         return true;
377     }
378
379     void reset() {
380         fPlotsToUpdate.reset();
381         memset(fPlotAlreadyUpdated, 0, sizeof(fPlotAlreadyUpdated));
382     }
383
384     struct PlotData {
385         PlotData(int pageIdx, int plotIdx) : fPageIndex(pageIdx), fPlotIndex(plotIdx) {}
386         uint32_t fPageIndex;
387         uint32_t fPlotIndex;
388     };
389
390     int count() const { return fPlotsToUpdate.count(); }
391
392     const PlotData& plotData(int index) const { return fPlotsToUpdate[index]; }
393
394 private:
395     bool find(int pageIdx, int index) const {
396         SkASSERT(index < skgpu::PlotLocator::kMaxPlots);
397         return (fPlotAlreadyUpdated[pageIdx] >> index) & 1;
398     }
399
400     void set(int pageIdx, int index) {
401         SkASSERT(!this->find(pageIdx, index));
402         fPlotAlreadyUpdated[pageIdx] |= (1 << index);
403         fPlotsToUpdate.push_back(PlotData(pageIdx, index));
404     }
405
406     inline static constexpr int kMinItems = 4;
407     SkSTArray<kMinItems, PlotData, true> fPlotsToUpdate;
408     // TODO: increase this to uint64_t to allow more plots per page
409     uint32_t fPlotAlreadyUpdated[skgpu::PlotLocator::kMaxMultitexturePages];
410 };
411
412 /**
413  * The backing texture for an atlas is broken into a spatial grid of Plots. The Plots
414  * keep track of subimage placement via their Rectanizer. A Plot may be subclassed if
415  * the atlas class needs to track additional information.
416  */
417 class Plot : public SkRefCnt {
418     SK_DECLARE_INTERNAL_LLIST_INTERFACE(Plot);
419
420 public:
421     Plot(int pageIndex, int plotIndex, AtlasGenerationCounter* generationCounter,
422          int offX, int offY, int width, int height, SkColorType colorType, size_t bpp);
423
424     uint32_t pageIndex() const { return fPageIndex; }
425
426     /** plotIndex() is a unique id for the plot relative to the owning GrAtlas and page. */
427     uint32_t plotIndex() const { return fPlotIndex; }
428     /**
429      * genID() is incremented when the plot is evicted due to a atlas spill. It is used to know
430      * if a particular subimage is still present in the atlas.
431      */
432     uint64_t genID() const { return fGenID; }
433     PlotLocator plotLocator() const {
434         SkASSERT(fPlotLocator.isValid());
435         return fPlotLocator;
436     }
437     SkDEBUGCODE(size_t bpp() const { return fBytesPerPixel; })
438
439     bool addSubImage(int width, int height, const void* image, AtlasLocator* atlasLocator);
440
441     /**
442      * To manage the lifetime of a plot, we use two tokens. We use the last upload token to
443      * know when we can 'piggy back' uploads, i.e. if the last upload hasn't been flushed to
444      * the gpu, we don't need to issue a new upload even if we update the cpu backing store. We
445      * use lastUse to determine when we can evict a plot from the cache, i.e. if the last use
446      * has already flushed through the gpu then we can reuse the plot.
447      */
448     skgpu::DrawToken lastUploadToken() const { return fLastUpload; }
449     skgpu::DrawToken lastUseToken() const { return fLastUse; }
450     void setLastUploadToken(skgpu::DrawToken token) { fLastUpload = token; }
451     void setLastUseToken(skgpu::DrawToken token) { fLastUse = token; }
452
453     int flushesSinceLastUsed() { return fFlushesSinceLastUse; }
454     void resetFlushesSinceLastUsed() { fFlushesSinceLastUse = 0; }
455     void incFlushesSinceLastUsed() { fFlushesSinceLastUse++; }
456
457     std::pair<const void*, SkIRect> prepareForUpload();
458     void resetRects();
459
460     /**
461      * Create a clone of this plot. The cloned plot will take the place of the current plot in
462      * the atlas
463      */
464     sk_sp<Plot> clone() const {
465         return sk_sp<Plot>(new Plot(
466             fPageIndex, fPlotIndex, fGenerationCounter, fX, fY, fWidth, fHeight, fColorType,
467             fBytesPerPixel));
468     }
469
470 #ifdef SK_DEBUG
471     void resetListPtrs() {
472         fPrev = fNext = nullptr;
473         fList = nullptr;
474     }
475 #endif
476
477 private:
478     ~Plot() override;
479
480     skgpu::DrawToken fLastUpload;
481     skgpu::DrawToken fLastUse;
482     int              fFlushesSinceLastUse;
483
484     struct {
485         const uint32_t fPageIndex : 16;
486         const uint32_t fPlotIndex : 16;
487     };
488     AtlasGenerationCounter* const fGenerationCounter;
489     uint64_t fGenID;
490     PlotLocator fPlotLocator;
491     unsigned char* fData;
492     const int fWidth;
493     const int fHeight;
494     const int fX;
495     const int fY;
496     skgpu::RectanizerSkyline fRectanizer;
497     const SkIPoint16 fOffset;  // the offset of the plot in the backing texture
498     const SkColorType fColorType;
499     const size_t fBytesPerPixel;
500     SkIRect fDirtyRect;
501     SkDEBUGCODE(bool fDirty);
502 };
503
504 typedef SkTInternalLList<Plot> PlotList;
505
506 } // namespace skgpu
507
508 #endif // skgpu_AtlasTypes_DEFINED