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