| /* |
| * 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 |