|  | /* | 
|  | * Copyright 2016 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #ifndef GrWindowRectangles_DEFINED | 
|  | #define GrWindowRectangles_DEFINED | 
|  |  | 
|  | #include "include/core/SkRect.h" | 
|  | #include "src/gpu/GrNonAtomicRef.h" | 
|  |  | 
|  | class GrWindowRectangles { | 
|  | public: | 
|  | constexpr static int kMaxWindows = 8; | 
|  |  | 
|  | GrWindowRectangles() : fCount(0) {} | 
|  | GrWindowRectangles(const GrWindowRectangles& that) : fCount(0) { *this = that; } | 
|  | ~GrWindowRectangles() { SkSafeUnref(this->rec()); } | 
|  |  | 
|  | GrWindowRectangles makeOffset(int dx, int dy) const; | 
|  |  | 
|  | bool empty() const { return !fCount; } | 
|  | int count() const { return fCount; } | 
|  | const SkIRect* data() const; | 
|  |  | 
|  | void reset(); | 
|  | GrWindowRectangles& operator=(const GrWindowRectangles&); | 
|  |  | 
|  | SkIRect& addWindow(const SkIRect& window) { return this->addWindow() = window; } | 
|  | SkIRect& addWindow(); | 
|  |  | 
|  | bool operator!=(const GrWindowRectangles& that) const { return !(*this == that); } | 
|  | bool operator==(const GrWindowRectangles&) const; | 
|  |  | 
|  | private: | 
|  | constexpr static int kNumLocalWindows = 1; | 
|  | struct Rec; | 
|  |  | 
|  | const Rec* rec() const { return fCount <= kNumLocalWindows ? nullptr : fRec; } | 
|  |  | 
|  | int fCount; | 
|  | union { | 
|  | SkIRect   fLocalWindows[kNumLocalWindows]; // If fCount <= kNumLocalWindows. | 
|  | Rec*      fRec;                            // If fCount > kNumLocalWindows. | 
|  | }; | 
|  | }; | 
|  |  | 
|  | struct GrWindowRectangles::Rec : public GrNonAtomicRef<Rec> { | 
|  | Rec(const SkIRect* windows, int numWindows) { | 
|  | SkASSERT(numWindows < kMaxWindows); | 
|  | memcpy(fData, windows, sizeof(SkIRect) * numWindows); | 
|  | } | 
|  | Rec() = default; | 
|  |  | 
|  | SkIRect fData[kMaxWindows]; | 
|  | }; | 
|  |  | 
|  | inline const SkIRect* GrWindowRectangles::data() const { | 
|  | return fCount <= kNumLocalWindows ? fLocalWindows : fRec->fData; | 
|  | } | 
|  |  | 
|  | inline void GrWindowRectangles::reset() { | 
|  | SkSafeUnref(this->rec()); | 
|  | fCount = 0; | 
|  | } | 
|  |  | 
|  | inline GrWindowRectangles& GrWindowRectangles::operator=(const GrWindowRectangles& that) { | 
|  | SkSafeUnref(this->rec()); | 
|  | fCount = that.fCount; | 
|  | if (fCount <= kNumLocalWindows) { | 
|  | memcpy(fLocalWindows, that.fLocalWindows, fCount * sizeof(SkIRect)); | 
|  | } else { | 
|  | fRec = SkRef(that.fRec); | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | inline GrWindowRectangles GrWindowRectangles::makeOffset(int dx, int dy) const { | 
|  | if (!dx && !dy) { | 
|  | return *this; | 
|  | } | 
|  | GrWindowRectangles result; | 
|  | result.fCount = fCount; | 
|  | SkIRect* windows; | 
|  | if (result.fCount > kNumLocalWindows) { | 
|  | result.fRec = new Rec(); | 
|  | windows = result.fRec->fData; | 
|  | } else { | 
|  | windows = result.fLocalWindows; | 
|  | } | 
|  | for (int i = 0; i < fCount; ++i) { | 
|  | windows[i] = this->data()[i].makeOffset(dx, dy); | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | inline SkIRect& GrWindowRectangles::addWindow() { | 
|  | SkASSERT(fCount < kMaxWindows); | 
|  | if (fCount < kNumLocalWindows) { | 
|  | return fLocalWindows[fCount++]; | 
|  | } | 
|  | if (fCount == kNumLocalWindows) { | 
|  | fRec = new Rec(fLocalWindows, kNumLocalWindows); | 
|  | } else if (!fRec->unique()) { // Simple copy-on-write. | 
|  | fRec->unref(); | 
|  | fRec = new Rec(fRec->fData, fCount); | 
|  | } | 
|  | return fRec->fData[fCount++]; | 
|  | } | 
|  |  | 
|  | inline bool GrWindowRectangles::operator==(const GrWindowRectangles& that) const { | 
|  | if (fCount != that.fCount) { | 
|  | return false; | 
|  | } | 
|  | if (fCount > kNumLocalWindows && fRec == that.fRec) { | 
|  | return true; | 
|  | } | 
|  | return !fCount || !memcmp(this->data(), that.data(), sizeof(SkIRect) * fCount); | 
|  | } | 
|  |  | 
|  | #endif |