16ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com/*
26ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com * Copyright 2013 Google Inc.
36ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com *
46ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com * Use of this source code is governed by a BSD-style license that can be
56ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com * found in the LICENSE file.
66ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com */
76ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
86ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com#include "SkDiscardablePixelRef.h"
96ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com#include "SkDiscardableMemory.h"
106168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com#include "SkImageGenerator.h"
116ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
12c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.comSkDiscardablePixelRef::SkDiscardablePixelRef(const SkImageInfo& info,
13c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com                                             SkImageGenerator* generator,
149ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com                                             size_t rowBytes,
159ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com                                             SkDiscardableMemory::Factory* fact)
16c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com    : INHERITED(info)
17c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com    , fGenerator(generator)
189ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com    , fDMFactory(fact)
196ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    , fRowBytes(rowBytes)
20c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com    , fDiscardableMemory(NULL)
21c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com{
226ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkASSERT(fGenerator != NULL);
236ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkASSERT(fRowBytes > 0);
24053509a4127881aa90bd365935125436589c9530commit-bot@chromium.org    // The SkImageGenerator contract requires fGenerator to always
25053509a4127881aa90bd365935125436589c9530commit-bot@chromium.org    // decode the same image on each call to getPixels().
26053509a4127881aa90bd365935125436589c9530commit-bot@chromium.org    this->setImmutable();
279ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com    SkSafeRef(fDMFactory);
286ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
296ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
306ac702e890656e801469060c1b9474912a5b704ahalcanary@google.comSkDiscardablePixelRef::~SkDiscardablePixelRef() {
31113de4128a2a8cfaf886d7a72ee2be0203b79111reed@google.com    if (this->isLocked()) {
32113de4128a2a8cfaf886d7a72ee2be0203b79111reed@google.com        fDiscardableMemory->unlock();
33113de4128a2a8cfaf886d7a72ee2be0203b79111reed@google.com    }
349ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com    SkDELETE(fDiscardableMemory);
359ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com    SkSafeUnref(fDMFactory);
366ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkDELETE(fGenerator);
376ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
386ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
39e406b3ba8294010dfdb8d71eb773f697ffc3cc4arobertphillips@google.comvoid* SkDiscardablePixelRef::onLockPixels(SkColorTable**) {
406ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    if (fDiscardableMemory != NULL) {
416ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com        if (fDiscardableMemory->lock()) {
42e406b3ba8294010dfdb8d71eb773f697ffc3cc4arobertphillips@google.com            return fDiscardableMemory->data();
436ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com        }
449ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com        SkDELETE(fDiscardableMemory);
456ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com        fDiscardableMemory = NULL;
466ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    }
47c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com
48c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com    const size_t size = this->info().getSafeSize(fRowBytes);
49c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com
509ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com    if (fDMFactory != NULL) {
51c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com        fDiscardableMemory = fDMFactory->create(size);
529ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com    } else {
53c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com        fDiscardableMemory = SkDiscardableMemory::Create(size);
549ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com    }
556ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    if (NULL == fDiscardableMemory) {
56e406b3ba8294010dfdb8d71eb773f697ffc3cc4arobertphillips@google.com        return NULL;  // Memory allocation failed.
576ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    }
586ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    void* pixels = fDiscardableMemory->data();
59c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com    if (!fGenerator->getPixels(this->info(), pixels, fRowBytes)) {
60ee2574b16e1cfe10bcab00a78a432a467ecde64areed@google.com        fDiscardableMemory->unlock();
61ee2574b16e1cfe10bcab00a78a432a467ecde64areed@google.com        SkDELETE(fDiscardableMemory);
62ee2574b16e1cfe10bcab00a78a432a467ecde64areed@google.com        fDiscardableMemory = NULL;
63e406b3ba8294010dfdb8d71eb773f697ffc3cc4arobertphillips@google.com        return NULL;
646ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    }
65e406b3ba8294010dfdb8d71eb773f697ffc3cc4arobertphillips@google.com    return pixels;
666ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
676ac702e890656e801469060c1b9474912a5b704ahalcanary@google.comvoid SkDiscardablePixelRef::onUnlockPixels() {
68ee2574b16e1cfe10bcab00a78a432a467ecde64areed@google.com    fDiscardableMemory->unlock();
696ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
706ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
716168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.combool SkInstallDiscardablePixelRef(SkImageGenerator* generator,
726168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com                                  SkBitmap* dst,
736168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com                                  SkDiscardableMemory::Factory* factory) {
746ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkImageInfo info;
756ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkASSERT(generator != NULL);
766ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    if ((NULL == generator)
776ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com        || (!generator->getInfo(&info))
786168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com        || (!dst->setConfig(info, 0))) {
796ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com        SkDELETE(generator);
806ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com        return false;
816ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    }
826168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com    SkASSERT(dst->config() != SkBitmap::kNo_Config);
836168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com    if (dst->empty()) { // Use a normal pixelref.
846168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com        SkDELETE(generator);  // Do not need this anymore.
856168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com        return dst->allocPixels(NULL, NULL);
866168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com    }
876ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkAutoTUnref<SkDiscardablePixelRef> ref(SkNEW_ARGS(SkDiscardablePixelRef,
88c2062d0e1bd6b258229669463ab5ce7020780c8areed@google.com                               (info, generator, dst->rowBytes(), factory)));
896ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    dst->setPixelRef(ref);
906ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    return true;
916ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
92