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 0 : static RunHead* Alloc(int count)
26 : {
27 : //SkDEBUGCODE(sk_atomic_inc(&gRgnAllocCounter);)
28 : //SkDEBUGF(("************** gRgnAllocCounter::alloc %d\n", gRgnAllocCounter));
29 :
30 0 : SkASSERT(count >= SkRegion::kRectRegionRuns);
31 :
32 0 : RunHead* head = (RunHead*)sk_malloc_throw(sizeof(RunHead) + count * sizeof(RunType));
33 0 : head->fRefCnt = 1;
34 0 : head->fRunCount = count;
35 0 : return head;
36 : }
37 :
38 0 : bool isComplex() const
39 : {
40 0 : return this != SkRegion_gEmptyRunHeadPtr && this != SkRegion_gRectRunHeadPtr;
41 : }
42 :
43 0 : SkRegion::RunType* writable_runs()
44 : {
45 0 : SkASSERT(this->isComplex());
46 0 : SkASSERT(fRefCnt == 1);
47 0 : return (SkRegion::RunType*)(this + 1);
48 : }
49 0 : const SkRegion::RunType* readonly_runs() const
50 : {
51 0 : SkASSERT(this->isComplex());
52 0 : return (const SkRegion::RunType*)(this + 1);
53 : }
54 :
55 0 : RunHead* ensureWritable()
56 : {
57 0 : SkASSERT(this->isComplex());
58 :
59 0 : RunHead* writable = this;
60 0 : 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 0 : writable = Alloc(fRunCount);
66 0 : memcpy(writable->writable_runs(), this->readonly_runs(),
67 0 : 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 0 : if (sk_atomic_dec(&fRefCnt) == 1)
73 : {
74 0 : sk_free(this);
75 : }
76 : }
77 0 : return writable;
78 : }
79 : };
80 :
81 : #endif
|