xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrWindowRectangles.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2016 Google Inc.
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 GrWindowRectangles_DEFINED
9 #define GrWindowRectangles_DEFINED
10 
11 #include "include/core/SkRect.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/private/base/SkAssert.h"
14 #include "src/gpu/ganesh/GrNonAtomicRef.h"
15 
16 #include <cstring>
17 
18 class GrWindowRectangles {
19 public:
20     constexpr static int kMaxWindows = 8;
21 
GrWindowRectangles()22     GrWindowRectangles() : fCount(0) {}
GrWindowRectangles(const GrWindowRectangles & that)23     GrWindowRectangles(const GrWindowRectangles& that) : fCount(0) { *this = that; }
~GrWindowRectangles()24     ~GrWindowRectangles() { SkSafeUnref(this->rec()); }
25 
26     GrWindowRectangles makeOffset(int dx, int dy) const;
27 
empty()28     bool empty() const { return !fCount; }
count()29     int count() const { return fCount; }
30     const SkIRect* data() const;
31 
32     void reset();
33     GrWindowRectangles& operator=(const GrWindowRectangles&);
34 
addWindow(const SkIRect & window)35     SkIRect& addWindow(const SkIRect& window) { return this->addWindow() = window; }
36     SkIRect& addWindow();
37 
38     bool operator!=(const GrWindowRectangles& that) const { return !(*this == that); }
39     bool operator==(const GrWindowRectangles&) const;
40 
41 private:
42     struct Rec;
43 
rec()44     const Rec* rec() const { return fCount <= 1 ? nullptr : fRec; }
45 
46     int fCount;
47     union {
48         SkIRect   fLocalWindow; // If fCount <= 1
49         Rec*      fRec;         // If fCount >  1.
50     };
51 };
52 
53 struct GrWindowRectangles::Rec : public GrNonAtomicRef<Rec> {
RecRec54     Rec(const SkIRect* windows, int numWindows) {
55         SkASSERT(numWindows <= kMaxWindows);
56         memcpy(fData, windows, sizeof(SkIRect) * numWindows);
57     }
58     Rec() = default;
59 
60     SkIRect fData[kMaxWindows];
61 };
62 
data()63 inline const SkIRect* GrWindowRectangles::data() const {
64     return fCount <= 1 ? &fLocalWindow : fRec->fData;
65 }
66 
reset()67 inline void GrWindowRectangles::reset() {
68     SkSafeUnref(this->rec());
69     fCount = 0;
70 }
71 
72 inline GrWindowRectangles& GrWindowRectangles::operator=(const GrWindowRectangles& that) {
73     SkSafeUnref(this->rec());
74     fCount = that.fCount;
75     if (fCount <= 1) {
76         fLocalWindow = that.fLocalWindow;
77     } else {
78         fRec = SkRef(that.fRec);
79     }
80     return *this;
81 }
82 
makeOffset(int dx,int dy)83 inline GrWindowRectangles GrWindowRectangles::makeOffset(int dx, int dy) const {
84     if (!dx && !dy) {
85         return *this;
86     }
87     GrWindowRectangles result;
88     result.fCount = fCount;
89     SkIRect* windows;
90     if (result.fCount > 1) {
91         result.fRec = new Rec();
92         windows = result.fRec->fData;
93     } else {
94         windows = &result.fLocalWindow;
95     }
96     for (int i = 0; i < fCount; ++i) {
97         windows[i] = this->data()[i].makeOffset(dx, dy);
98     }
99     return result;
100 }
101 
addWindow()102 inline SkIRect& GrWindowRectangles::addWindow() {
103     SkASSERT(fCount < kMaxWindows);
104     if (fCount == 0) {
105         fCount = 1;
106         return fLocalWindow;
107     }
108     if (fCount == 1) {
109         fRec = new Rec(&fLocalWindow, 1);
110     } else if (!fRec->unique()) { // Simple copy-on-write.
111         fRec->unref();
112         fRec = new Rec(fRec->fData, fCount);
113     }
114     return fRec->fData[fCount++];
115 }
116 
117 inline bool GrWindowRectangles::operator==(const GrWindowRectangles& that) const {
118     if (fCount != that.fCount) {
119         return false;
120     }
121     if (fCount > 1 && fRec == that.fRec) {
122         return true;
123     }
124     return !fCount || !memcmp(this->data(), that.data(), sizeof(SkIRect) * fCount);
125 }
126 
127 #endif
128