Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkRegionPriv_DEFINED
     11 #define SkRegionPriv_DEFINED
     12 
     13 #include "SkRegion.h"
     14 #include "SkThread.h"
     15 
     16 #define assert_sentinel(value, isSentinel) \
     17     SkASSERT(((value) == SkRegion::kRunTypeSentinel) == isSentinel)
     18 
     19 //SkDEBUGCODE(extern int32_t gRgnAllocCounter;)
     20 
     21 struct SkRegion::RunHead {
     22     int32_t fRefCnt;
     23     int32_t fRunCount;
     24 
     25     static RunHead* Alloc(int count)
     26     {
     27         //SkDEBUGCODE(sk_atomic_inc(&gRgnAllocCounter);)
     28         //SkDEBUGF(("************** gRgnAllocCounter::alloc %d\n", gRgnAllocCounter));
     29 
     30         SkASSERT(count >= SkRegion::kRectRegionRuns);
     31 
     32         RunHead* head = (RunHead*)sk_malloc_throw(sizeof(RunHead) + count * sizeof(RunType));
     33         head->fRefCnt = 1;
     34         head->fRunCount = count;
     35         return head;
     36     }
     37 
     38     bool isComplex() const
     39     {
     40         return this != SkRegion_gEmptyRunHeadPtr && this != SkRegion_gRectRunHeadPtr;
     41     }
     42 
     43     SkRegion::RunType* writable_runs()
     44     {
     45         SkASSERT(this->isComplex());
     46         SkASSERT(fRefCnt == 1);
     47         return (SkRegion::RunType*)(this + 1);
     48     }
     49     const SkRegion::RunType* readonly_runs() const
     50     {
     51         SkASSERT(this->isComplex());
     52         return (const SkRegion::RunType*)(this + 1);
     53     }
     54 
     55     RunHead* ensureWritable()
     56     {
     57         SkASSERT(this->isComplex());
     58 
     59         RunHead* writable = this;
     60         if (fRefCnt > 1)
     61         {
     62             // We need to alloc & copy the current region before we call
     63             // sk_atomic_dec because it could be freed in the meantime,
     64             // otherwise.
     65             writable = Alloc(fRunCount);
     66             memcpy(writable->writable_runs(), this->readonly_runs(),
     67                    fRunCount * sizeof(RunType));
     68 
     69             // fRefCount might have changed since we last checked.
     70             // If we own the last reference at this point, we need to
     71             // free the memory.
     72             if (sk_atomic_dec(&fRefCnt) == 1)
     73             {
     74                 sk_free(this);
     75             }
     76         }
     77         return writable;
     78     }
     79 };
     80 
     81 #endif
     82