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