1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPixelRef.h"
98b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
108b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com#ifdef SK_USE_POSIX_THREADS
14dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com
15dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    static SkBaseMutex gPixelRefMutexRing[] = {
16b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
17b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
18b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
19b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
20b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein
21b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
22b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
23b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
24b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
25b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein
26b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
27b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
28b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
29b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
30b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein
31b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
32b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
33b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
34b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein        SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
35dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    };
36dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com
37dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    // must be a power-of-2. undef to just use 1 mutex
38dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    #define PIXELREF_MUTEX_RING_COUNT SK_ARRAY_COUNT(gPixelRefMutexRing)
39dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com
40dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com#else // not pthreads
41dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com
42dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    // must be a power-of-2. undef to just use 1 mutex
43dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    #define PIXELREF_MUTEX_RING_COUNT       32
44dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    static SkBaseMutex gPixelRefMutexRing[PIXELREF_MUTEX_RING_COUNT];
45dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com
46ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com#endif
47ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com
48803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.comstatic SkBaseMutex* get_default_mutex() {
49dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    static int32_t gPixelRefMutexRingIndex;
50dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com
51dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com    SkASSERT(SkIsPow2(PIXELREF_MUTEX_RING_COUNT));
52dd96eb4f5c84a8225396d9ce0ca65d4d8966d741reed@google.com
53ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    // atomic_inc might be overkill here. It may be fine if once in a while
54ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    // we hit a race-condition and two subsequent calls get the same index...
55ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    int index = sk_atomic_inc(&gPixelRefMutexRingIndex);
56ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)];
57ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com}
58ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com
59ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com///////////////////////////////////////////////////////////////////////////////
60586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com
61100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.comint32_t SkNextPixelRefGenerationID();
62100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.com
639c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.comint32_t SkNextPixelRefGenerationID() {
64586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    static int32_t  gPixelRefGenerationID;
65586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    // do a loop in case our global wraps around, as we never want to
66586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    // return a 0
67586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    int32_t genID;
68586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    do {
69586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com        genID = sk_atomic_inc(&gPixelRefGenerationID) + 1;
70586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    } while (0 == genID);
71586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    return genID;
72586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com}
73586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com
74ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com///////////////////////////////////////////////////////////////////////////////
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.comvoid SkPixelRef::setMutex(SkBaseMutex* mutex) {
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == mutex) {
78ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com        mutex = get_default_mutex();
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMutex = mutex;
81ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com}
82ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com
83ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com// just need a > 0 value, so pick a funny one to aid in debugging
84ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com#define SKPIXELREF_PRELOCKED_LOCKCOUNT     123456789
85ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com
86d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.comSkPixelRef::SkPixelRef(const SkImageInfo& info) : fInfo(info) {
87d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    this->setMutex(NULL);
88d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    fRec.zero();
890daa1adb03b4b1fc11d854cb7754416ac05a31e8robertphillips@google.com    fLockCount = 0;
900daa1adb03b4b1fc11d854cb7754416ac05a31e8robertphillips@google.com    this->needsNewGenID();
910daa1adb03b4b1fc11d854cb7754416ac05a31e8robertphillips@google.com    fIsImmutable = false;
920daa1adb03b4b1fc11d854cb7754416ac05a31e8robertphillips@google.com    fPreLocked = false;
930daa1adb03b4b1fc11d854cb7754416ac05a31e8robertphillips@google.com}
940daa1adb03b4b1fc11d854cb7754416ac05a31e8robertphillips@google.com
95d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com
96d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.comSkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) : fInfo(info) {
97d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    this->setMutex(mutex);
98d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    fRec.zero();
99f1715706f761e7e254f601abf33581702fa8fe17reed@google.com    fLockCount = 0;
100f1715706f761e7e254f601abf33581702fa8fe17reed@google.com    this->needsNewGenID();
101f1715706f761e7e254f601abf33581702fa8fe17reed@google.com    fIsImmutable = false;
102f1715706f761e7e254f601abf33581702fa8fe17reed@google.com    fPreLocked = false;
103f1715706f761e7e254f601abf33581702fa8fe17reed@google.com}
104f1715706f761e7e254f601abf33581702fa8fe17reed@google.com
1058b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgstatic SkImageInfo read_info(SkReadBuffer& buffer) {
10633cc989f23d091be2463ada7c12e334be204a80freed@google.com    SkImageInfo info;
10733cc989f23d091be2463ada7c12e334be204a80freed@google.com    info.unflatten(buffer);
10833cc989f23d091be2463ada7c12e334be204a80freed@google.com    return info;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkPixelRef::SkPixelRef(SkReadBuffer& buffer, SkBaseMutex* mutex)
11233cc989f23d091be2463ada7c12e334be204a80freed@google.com        : INHERITED(buffer)
11333cc989f23d091be2463ada7c12e334be204a80freed@google.com        , fInfo(read_info(buffer))
11433cc989f23d091be2463ada7c12e334be204a80freed@google.com{
115ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    this->setMutex(mutex);
116d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    fRec.zero();
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLockCount = 0;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fIsImmutable = buffer.readBool();
119c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    fGenerationID = buffer.readUInt();
12050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    fUniqueGenerationID = false;  // Conservatively assuming the original still exists.
121ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    fPreLocked = false;
122ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com}
123ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com
12450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgSkPixelRef::~SkPixelRef() {
12550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    this->callGenIDChangeListeners();
12650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org}
12750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
12850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgvoid SkPixelRef::needsNewGenID() {
12950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    fGenerationID = 0;
13050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    fUniqueGenerationID = false;
13150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org}
13250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
13350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgvoid SkPixelRef::cloneGenID(const SkPixelRef& that) {
13450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    // This is subtle.  We must call that.getGenerationID() to make sure its genID isn't 0.
13550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    this->fGenerationID = that.getGenerationID();
13650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    this->fUniqueGenerationID = false;
13750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    that.fUniqueGenerationID = false;
13850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org}
13950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
1407627c657b039ea9aa2a01a7d74e652fe7e27def4reed@google.comvoid SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) {
1412a3f08b0a71d044ba48694ed04b3dc1ce846e9d9reed@google.com#ifndef SK_IGNORE_PIXELREF_SETPRELOCKED
142ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    // only call me in your constructor, otherwise fLockCount tracking can get
143ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    // out of sync.
144d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    fRec.fPixels = pixels;
145d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    fRec.fColorTable = ctable;
146d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    fRec.fRowBytes = rowBytes;
147ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
148ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    fPreLocked = true;
1492a3f08b0a71d044ba48694ed04b3dc1ce846e9d9reed@google.com#endif
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1528b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPixelRef::flatten(SkWriteBuffer& buffer) const {
1535370cd969d8f3957e4306068e6195ac1bca3d6cddjsollen@google.com    this->INHERITED::flatten(buffer);
154bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    fInfo.flatten(buffer);
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeBool(fIsImmutable);
1567aa876bfbf0cf6f2a9d19bd4669ae50658f20821bsalomon@google.com    // We write the gen ID into the picture for within-process recording. This
1577aa876bfbf0cf6f2a9d19bd4669ae50658f20821bsalomon@google.com    // is safe since the same genID will never refer to two different sets of
1587aa876bfbf0cf6f2a9d19bd4669ae50658f20821bsalomon@google.com    // pixels (barring overflow). However, each process has its own "namespace"
1597aa876bfbf0cf6f2a9d19bd4669ae50658f20821bsalomon@google.com    // of genIDs. So for cross-process recording we write a zero which will
1607aa876bfbf0cf6f2a9d19bd4669ae50658f20821bsalomon@google.com    // trigger assignment of a new genID in playback.
1617aa876bfbf0cf6f2a9d19bd4669ae50658f20821bsalomon@google.com    if (buffer.isCrossProcess()) {
162c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.writeUInt(0);
1637aa876bfbf0cf6f2a9d19bd4669ae50658f20821bsalomon@google.com    } else {
164c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.writeUInt(fGenerationID);
16550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        fUniqueGenerationID = false;  // Conservative, a copy is probably about to exist.
1667aa876bfbf0cf6f2a9d19bd4669ae50658f20821bsalomon@google.com    }
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
169d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.combool SkPixelRef::lockPixels(LockRec* rec) {
170ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
17198272d91421c52211e0e0137f494c1cad01c3c68skia.committer@gmail.com
172ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    if (!fPreLocked) {
173ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com        SkAutoMutexAcquire  ac(*fMutex);
17498272d91421c52211e0e0137f494c1cad01c3c68skia.committer@gmail.com
17527f890219b09e4774da75e6a11ec82849eadae5acommit-bot@chromium.org        if (1 == ++fLockCount) {
176d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com            SkASSERT(fRec.isZero());
177d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com
178d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com            LockRec rec;
179d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com            if (!this->onNewLockPixels(&rec)) {
180d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com                return false;
181c83a91f4721739f05f9df51d496d50b5d028b132reed@google.com            }
182d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com            SkASSERT(!rec.isZero());    // else why did onNewLock return true?
183d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com            fRec = rec;
184ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com        }
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
186d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    *rec = fRec;
187d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    return true;
188d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com}
189d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com
190d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.combool SkPixelRef::lockPixels() {
191d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    LockRec rec;
192d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    return this->lockPixels(&rec);
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPixelRef::unlockPixels() {
196ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
197fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
198ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com    if (!fPreLocked) {
199ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com        SkAutoMutexAcquire  ac(*fMutex);
20093c5f9e787ae06b113c422e4aaabb48c278ea9c5reed@google.com
201ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com        SkASSERT(fLockCount > 0);
202ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com        if (0 == --fLockCount) {
203c83a91f4721739f05f9df51d496d50b5d028b132reed@google.com            // don't call onUnlockPixels unless onLockPixels succeeded
204d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com            if (fRec.fPixels) {
205c83a91f4721739f05f9df51d496d50b5d028b132reed@google.com                this->onUnlockPixels();
206d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com                fRec.zero();
207c83a91f4721739f05f9df51d496d50b5d028b132reed@google.com            } else {
208d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com                SkASSERT(fRec.isZero());
209c83a91f4721739f05f9df51d496d50b5d028b132reed@google.com            }
210ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com        }
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2149c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.combool SkPixelRef::lockPixelsAreWritable() const {
2159c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com    return this->onLockPixelsAreWritable();
2169c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com}
2179c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com
2189c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.combool SkPixelRef::onLockPixelsAreWritable() const {
2199c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com    return true;
2209c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com}
2219c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com
222cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.combool SkPixelRef::onImplementsDecodeInto() {
223cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com    return false;
224cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com}
225cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com
226cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.combool SkPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) {
227cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com    return false;
228cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com}
229cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comuint32_t SkPixelRef::getGenerationID() const {
231586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    if (0 == fGenerationID) {
232586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com        fGenerationID = SkNextPixelRefGenerationID();
23350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        fUniqueGenerationID = true;  // The only time we can be sure of this!
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
235586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    return fGenerationID;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgvoid SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) {
23950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    if (NULL == listener || !fUniqueGenerationID) {
24050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        // No point in tracking this if we're not going to call it.
24150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        SkDELETE(listener);
24250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        return;
24350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    }
24450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    *fGenIDChangeListeners.append() = listener;
24550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org}
24650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
24750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgvoid SkPixelRef::callGenIDChangeListeners() {
24850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID.
24950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    if (fUniqueGenerationID) {
25050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        for (int i = 0; i < fGenIDChangeListeners.count(); i++) {
25150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org            fGenIDChangeListeners[i]->onChange();
25250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        }
25350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    }
25450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    // Listeners get at most one shot, so whether these triggered or not, blow them away.
25550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    fGenIDChangeListeners.deleteAll();
25650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org}
25750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
258c1587f94a77eaafe257a6ecf504364d40362c66areed@google.comvoid SkPixelRef::notifyPixelsChanged() {
2593eab80cc1f2031b582b37aed6176e1f8df67b72freed@android.com#ifdef SK_DEBUG
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fIsImmutable) {
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2633eab80cc1f2031b582b37aed6176e1f8df67b72freed@android.com#endif
26450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    this->callGenIDChangeListeners();
26550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    this->needsNewGenID();
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268c1587f94a77eaafe257a6ecf504364d40362c66areed@google.comvoid SkPixelRef::changeAlphaType(SkAlphaType at) {
269c1587f94a77eaafe257a6ecf504364d40362c66areed@google.com    *const_cast<SkAlphaType*>(&fInfo.fAlphaType) = at;
270c1587f94a77eaafe257a6ecf504364d40362c66areed@google.com}
271c1587f94a77eaafe257a6ecf504364d40362c66areed@google.com
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPixelRef::setImmutable() {
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fIsImmutable = true;
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27650dfa0130b0705414df7ba7da9915139f6320b09reed@google.combool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
27750dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    return this->onReadPixels(dst, subset);
27850dfa0130b0705414df7ba7da9915139f6320b09reed@google.com}
27950dfa0130b0705414df7ba7da9915139f6320b09reed@google.com
28050dfa0130b0705414df7ba7da9915139f6320b09reed@google.combool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
28150dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    return false;
28250dfa0130b0705414df7ba7da9915139f6320b09reed@google.com}
28350dfa0130b0705414df7ba7da9915139f6320b09reed@google.com
284eb776128f5024cc50886634382731220f7424a9areed@google.comSkData* SkPixelRef::onRefEncodedData() {
285eb776128f5024cc50886634382731220f7424a9areed@google.com    return NULL;
286eb776128f5024cc50886634382731220f7424a9areed@google.com}
287eb776128f5024cc50886634382731220f7424a9areed@google.com
288cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.orgsize_t SkPixelRef::getAllocatedSizeInBytes() const {
289cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    return 0;
290cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org}
291cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29456c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
29557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.comvoid SkPixelRef::globalRef(void* data) {
29657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    this->ref();
29757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com}
29857f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com
29957f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.comvoid SkPixelRef::globalUnref() {
30057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    this->unref();
30157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com}
30293c5f9e787ae06b113c422e4aaabb48c278ea9c5reed@google.com#endif
303