ce38a4a877b9f2cad2c645b3ec66b9309aba95a6
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / lazy / SkDiscardablePixelRef.cpp
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkDiscardablePixelRef.h"
9 #include "SkDiscardableMemory.h"
10 #include "SkImageGenerator.h"
11
12 SkDiscardablePixelRef::SkDiscardablePixelRef(const SkImageInfo& info,
13                                              SkImageGenerator* generator,
14                                              size_t rowBytes,
15                                              SkDiscardableMemory::Factory* fact)
16     : INHERITED(info)
17     , fGenerator(generator)
18     , fDMFactory(fact)
19     , fRowBytes(rowBytes)
20     , fDiscardableMemory(NULL)
21 {
22     SkASSERT(fGenerator != NULL);
23     SkASSERT(fRowBytes > 0);
24     // The SkImageGenerator contract requires fGenerator to always
25     // decode the same image on each call to getPixels().
26     this->setImmutable();
27     SkSafeRef(fDMFactory);
28 }
29
30 SkDiscardablePixelRef::~SkDiscardablePixelRef() {
31     if (this->isLocked()) {
32         fDiscardableMemory->unlock();
33     }
34     SkDELETE(fDiscardableMemory);
35     SkSafeUnref(fDMFactory);
36     SkDELETE(fGenerator);
37 }
38
39 bool SkDiscardablePixelRef::onNewLockPixels(LockRec* rec) {
40     if (fDiscardableMemory != NULL) {
41         if (fDiscardableMemory->lock()) {
42             rec->fPixels = fDiscardableMemory->data();
43             rec->fColorTable = fCTable.get();
44             rec->fRowBytes = fRowBytes;
45             return true;
46         }
47         SkDELETE(fDiscardableMemory);
48         fDiscardableMemory = NULL;
49     }
50
51     const size_t size = this->info().getSafeSize(fRowBytes);
52
53     if (fDMFactory != NULL) {
54         fDiscardableMemory = fDMFactory->create(size);
55     } else {
56         fDiscardableMemory = SkDiscardableMemory::Create(size);
57     }
58     if (NULL == fDiscardableMemory) {
59         return false;  // Memory allocation failed.
60     }
61
62     void* pixels = fDiscardableMemory->data();
63     const SkImageInfo& info = this->info();
64     SkPMColor colors[256];
65     int colorCount = 0;
66
67 #ifdef SK_SUPPORT_LEGACY_IMAGEGENERATORAPI
68     if (!fGenerator->getPixels(info, pixels, fRowBytes)) {
69 #else
70     if (!fGenerator->getPixels(info, pixels, fRowBytes, colors, &colorCount)) {
71 #endif
72         fDiscardableMemory->unlock();
73         SkDELETE(fDiscardableMemory);
74         fDiscardableMemory = NULL;
75         return false;
76     }
77
78     // Note: our ctable is not purgable, as it is not stored in the discardablememory block.
79     // This is because SkColorTable is refcntable, and therefore our caller could hold onto it
80     // beyond the scope of a lock/unlock. If we change the API/lifecycle for SkColorTable, we
81     // could move it into the block, but then again perhaps it is small enough that this doesn't
82     // really matter.
83     if (colorCount > 0) {
84         fCTable.reset(SkNEW_ARGS(SkColorTable, (colors, colorCount)));
85     } else {
86         fCTable.reset(NULL);
87     }
88
89     rec->fPixels = pixels;
90     rec->fColorTable = fCTable.get();
91     rec->fRowBytes = fRowBytes;
92     return true;
93 }
94
95 void SkDiscardablePixelRef::onUnlockPixels() {
96     fDiscardableMemory->unlock();
97 }
98
99 bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, SkBitmap* dst,
100                                   SkDiscardableMemory::Factory* factory) {
101     SkImageInfo info;
102     SkAutoTDelete<SkImageGenerator> autoGenerator(generator);
103     if ((NULL == autoGenerator.get())
104         || (!autoGenerator->getInfo(&info))
105         || (!dst->setInfo(info))) {
106         return false;
107     }
108     SkASSERT(dst->colorType() != kUnknown_SkColorType);
109     if (dst->empty()) {  // Use a normal pixelref.
110         return dst->allocPixels();
111     }
112     SkAutoTUnref<SkDiscardablePixelRef> ref(
113         SkNEW_ARGS(SkDiscardablePixelRef,
114                    (info, autoGenerator.detach(), dst->rowBytes(), factory)));
115     dst->setPixelRef(ref);
116     return true;
117 }
118
119 // This is the public API
120 bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, SkBitmap* dst) {
121     return SkInstallDiscardablePixelRef(generator, dst, NULL);
122 }