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