Chromium Code Reviews| Index: src/gpu/GrWindowRectangles.h |
| diff --git a/src/gpu/GrWindowRectangles.h b/src/gpu/GrWindowRectangles.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..50cb5b7b495e35640de3f727949b9943aef16826 |
| --- /dev/null |
| +++ b/src/gpu/GrWindowRectangles.h |
| @@ -0,0 +1,127 @@ |
| +/* |
| + * 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 "GrCaps.h" |
| +#include <limits> |
| + |
| +class GrWindowRectangles { |
| +public: |
| + enum class Mode : bool { |
| + kExclusive, |
| + kInclusive |
| + }; |
| + |
| + GrWindowRectangles(Mode mode = Mode::kExclusive) : fMode(mode), fCount(0) {} |
| + GrWindowRectangles(const GrWindowRectangles& that) : fCount(0) { *this = that; } |
| + ~GrWindowRectangles() { SkSafeUnref(this->rec()); } |
| + |
| + Mode mode() const { return fMode; } |
| + uint16_t count() const { return fCount; } |
| + const SkIRect* data() const; |
| + |
| + void reset(Mode mode = Mode::kExclusive); |
| + GrWindowRectangles& operator=(const GrWindowRectangles&); |
| + |
| + void addWindow(const SkIRect& window, const GrCaps& caps) { this->addWindow(caps) = window; } |
| + SkIRect& addWindow(const GrCaps& caps); |
|
csmartdalton
2016/08/16 05:20:17
I'm thinking I'll replace this GrCaps param with j
csmartdalton
2016/08/16 23:38:34
Done. Just used a compile-time constant max as dis
|
| + |
| + bool operator!=(const GrWindowRectangles& that) const { return !(*this == that); } |
| + bool operator==(const GrWindowRectangles&) const; |
| + |
| +private: |
| + constexpr static int kNumLocalWindows = 1; |
|
bsalomon
2016/08/16 19:03:55
What in practice is the limit for the number of wi
csmartdalton
2016/08/16 19:49:45
I believe it's 8 on NVIDIA. GrGLCaps limits us to
|
| + class Rec; |
| + |
| + const Rec* rec() const { return fCount <= kNumLocalWindows ? nullptr : fRec; } |
| + |
| + Mode fMode; |
| + uint8_t fCount; |
| + union { |
| + SkIRect fLocalWindows[kNumLocalWindows]; // If fCount <= kNumLocalWindows. |
| + Rec* fRec; // If fCount > kNumLocalWindows. |
| + }; |
| +}; |
| + |
| +class GrWindowRectangles::Rec { |
|
bsalomon
2016/08/16 19:03:55
Inherit from GrNonAtomicRef?
csmartdalton
2016/08/16 19:49:45
GrWindowRectangles does need to peek at the ref co
csmartdalton
2016/08/16 23:38:34
Done.
|
| +public: |
| + static Rec* Create(const SkIRect* windows, int numWindows, const GrCaps& caps) { |
| + // "maxWindowRectangles - 1" because sizeof(Rec) already accounts for the first SkIRect. |
| + void* p = sk_malloc_throw(sizeof(Rec) + sizeof(SkIRect) * (caps.maxWindowRectangles() - 1)); |
| + return new (p) Rec(windows, numWindows, caps.maxWindowRectangles()); |
| + } |
| + |
| + int refCnt() const { return fRefCnt; } |
| + void ref() const { ++fRefCnt; } |
| + void unref() const { if (--fRefCnt <= 0) sk_free(const_cast<Rec*>(this)); } |
| + |
| + SkDEBUGCODE(int dataLength() const { return fDataLength; }) |
| + SkIRect* data() { return fData; } |
| + |
| +private: |
| + Rec(const SkIRect* windows, int numWindows, int SkDEBUGCODE(dataLength)) |
| + : SkDEBUGCODE(fDataLength(dataLength),) fRefCnt(1) { |
| + SkASSERT(numWindows <= fDataLength); |
| + memcpy(fData, windows, sizeof(SkIRect) * numWindows); |
| + } |
| + |
| + SkDEBUGCODE(const int fDataLength;) |
| + mutable int fRefCnt; |
| + SkIRect fData[1]; |
| +}; |
| + |
| +inline const SkIRect* GrWindowRectangles::data() const { |
| + return fCount <= kNumLocalWindows ? fLocalWindows : fRec->data(); |
| +} |
| + |
| +inline void GrWindowRectangles::reset(Mode mode) { |
| + SkSafeUnref(this->rec()); |
| + fMode = mode; |
| + fCount = 0; |
| +} |
| + |
| +inline GrWindowRectangles& GrWindowRectangles::operator=(const GrWindowRectangles& that) { |
| + SkSafeUnref(this->rec()); |
| + fMode = that.fMode; |
| + fCount = that.fCount; |
| + if (fCount <= kNumLocalWindows) { |
| + memcpy(fLocalWindows, that.fLocalWindows, fCount * sizeof(SkIRect)); |
| + } else { |
| + fRec = SkRef(that.fRec); |
| + } |
| + return *this; |
| +} |
| + |
| +inline SkIRect& GrWindowRectangles::addWindow(const GrCaps& caps) { |
| + SkASSERT(fCount < caps.maxWindowRectangles()); |
| + if (fCount < kNumLocalWindows) { |
| + return fLocalWindows[fCount++]; |
| + } |
| + if (fCount == kNumLocalWindows) { |
| + fRec = Rec::Create(fLocalWindows, kNumLocalWindows, caps); |
| + } else if (fRec->refCnt() > 1) { // Simple copy-on-write. |
| + fRec->unref(); |
| + fRec = Rec::Create(fRec->data(), fCount, caps); |
| + } |
| + SkASSERT(fRec->dataLength() == caps.maxWindowRectangles()); |
| + SkASSERT(fRec->dataLength() <= std::numeric_limits<decltype(fCount)>::max()); |
| + return fRec->data()[fCount++]; |
| +} |
| + |
| +inline bool GrWindowRectangles::operator==(const GrWindowRectangles& that) const { |
| + if (fMode != that.fMode || fCount != that.fCount) { |
| + return false; |
| + } |
| + if (fCount > kNumLocalWindows && fRec == that.fRec) { |
| + return true; |
| + } |
| + return !fCount || !memcmp(this->data(), that.data(), sizeof(SkIRect) * fCount); |
| +} |
| + |
| +#endif |