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
21struct 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