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 "GrNonAtomicRef.h" 12 #include "SkRect.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 constexpr static int kNumLocalWindows = 1; 39 struct Rec; 40 41 const Rec* rec() const { return fCount <= kNumLocalWindows ? nullptr : fRec; } 42 43 int fCount; 44 union { 45 SkIRect fLocalWindows[kNumLocalWindows]; // If fCount <= kNumLocalWindows. 46 Rec* fRec; // If fCount > kNumLocalWindows. 47 }; 48 }; 49 50 struct GrWindowRectangles::Rec : public GrNonAtomicRef<Rec> { 51 Rec(const SkIRect* windows, int numWindows) { 52 SkASSERT(numWindows < kMaxWindows); 53 memcpy(fData, windows, sizeof(SkIRect) * numWindows); 54 } 55 Rec() = default; 56 57 SkIRect fData[kMaxWindows]; 58 }; 59 60 inline const SkIRect* GrWindowRectangles::data() const { 61 return fCount <= kNumLocalWindows ? fLocalWindows : fRec->fData; 62 } 63 64 inline void GrWindowRectangles::reset() { 65 SkSafeUnref(this->rec()); 66 fCount = 0; 67 } 68 69 inline GrWindowRectangles& GrWindowRectangles::operator=(const GrWindowRectangles& that) { 70 SkSafeUnref(this->rec()); 71 fCount = that.fCount; 72 if (fCount <= kNumLocalWindows) { 73 memcpy(fLocalWindows, that.fLocalWindows, fCount * sizeof(SkIRect)); 74 } else { 75 fRec = SkRef(that.fRec); 76 } 77 return *this; 78 } 79 80 inline GrWindowRectangles GrWindowRectangles::makeOffset(int dx, int dy) const { 81 if (!dx && !dy) { 82 return *this; 83 } 84 GrWindowRectangles result; 85 result.fCount = fCount; 86 SkIRect* windows; 87 if (result.fCount > kNumLocalWindows) { 88 result.fRec = new Rec(); 89 windows = result.fRec->fData; 90 } else { 91 windows = result.fLocalWindows; 92 } 93 for (int i = 0; i < fCount; ++i) { 94 windows[i] = this->data()[i].makeOffset(dx, dy); 95 } 96 return result; 97 } 98 99 inline SkIRect& GrWindowRectangles::addWindow() { 100 SkASSERT(fCount < kMaxWindows); 101 if (fCount < kNumLocalWindows) { 102 return fLocalWindows[fCount++]; 103 } 104 if (fCount == kNumLocalWindows) { 105 fRec = new Rec(fLocalWindows, kNumLocalWindows); 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 > kNumLocalWindows && fRec == that.fRec) { 118 return true; 119 } 120 return !fCount || !memcmp(this->data(), that.data(), sizeof(SkIRect) * fCount); 121 } 122 123 #endif 124