Home | History | Annotate | Download | only in gpu
      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