halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 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" |
halcanary@google.com | edd370f | 2013-12-10 21:11:12 +0000 | [diff] [blame] | 10 | #include "SkImageGenerator.h" |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 11 | |
reed@google.com | bf79023 | 2013-12-13 19:45:58 +0000 | [diff] [blame] | 12 | SkDiscardablePixelRef::SkDiscardablePixelRef(const SkImageInfo& info, |
| 13 | SkImageGenerator* generator, |
halcanary@google.com | 2c7c7ee | 2013-12-05 18:31:42 +0000 | [diff] [blame] | 14 | size_t rowBytes, |
| 15 | SkDiscardableMemory::Factory* fact) |
reed@google.com | bf79023 | 2013-12-13 19:45:58 +0000 | [diff] [blame] | 16 | : INHERITED(info) |
| 17 | , fGenerator(generator) |
halcanary@google.com | 2c7c7ee | 2013-12-05 18:31:42 +0000 | [diff] [blame] | 18 | , fDMFactory(fact) |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 19 | , fRowBytes(rowBytes) |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 20 | , fDiscardableMemory(nullptr) |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 21 | , fDiscardableMemoryIsLocked(false) |
reed@google.com | bf79023 | 2013-12-13 19:45:58 +0000 | [diff] [blame] | 22 | { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 23 | SkASSERT(fGenerator != nullptr); |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 24 | SkASSERT(fRowBytes > 0); |
commit-bot@chromium.org | dd59799 | 2013-12-02 22:32:54 +0000 | [diff] [blame] | 25 | // The SkImageGenerator contract requires fGenerator to always |
| 26 | // decode the same image on each call to getPixels(). |
| 27 | this->setImmutable(); |
halcanary@google.com | 2c7c7ee | 2013-12-05 18:31:42 +0000 | [diff] [blame] | 28 | SkSafeRef(fDMFactory); |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 29 | } |
| 30 | |
| 31 | SkDiscardablePixelRef::~SkDiscardablePixelRef() { |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 32 | if (fDiscardableMemoryIsLocked) { |
reed@google.com | 1d0654f | 2013-12-12 22:37:32 +0000 | [diff] [blame] | 33 | fDiscardableMemory->unlock(); |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 34 | fDiscardableMemoryIsLocked = false; |
reed@google.com | 1d0654f | 2013-12-12 22:37:32 +0000 | [diff] [blame] | 35 | } |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 36 | delete fDiscardableMemory; |
halcanary@google.com | 2c7c7ee | 2013-12-05 18:31:42 +0000 | [diff] [blame] | 37 | SkSafeUnref(fDMFactory); |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 38 | delete fGenerator; |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 39 | } |
| 40 | |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 41 | bool SkDiscardablePixelRef::onNewLockPixels(LockRec* rec) { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 42 | if (fDiscardableMemory != nullptr) { |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 43 | if (fDiscardableMemory->lock()) { |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 44 | fDiscardableMemoryIsLocked = true; |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 45 | rec->fPixels = fDiscardableMemory->data(); |
halcanary | 7f8aad8 | 2014-07-28 08:23:55 -0700 | [diff] [blame] | 46 | rec->fColorTable = fCTable.get(); |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 47 | rec->fRowBytes = fRowBytes; |
| 48 | return true; |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 49 | } |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 50 | delete fDiscardableMemory; |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 51 | fDiscardableMemory = nullptr; |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 52 | fDiscardableMemoryIsLocked = false; |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 53 | } |
skia.committer@gmail.com | 98272d9 | 2014-01-04 07:01:40 +0000 | [diff] [blame] | 54 | |
reed@google.com | bf79023 | 2013-12-13 19:45:58 +0000 | [diff] [blame] | 55 | const size_t size = this->info().getSafeSize(fRowBytes); |
| 56 | |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 57 | if (fDMFactory != nullptr) { |
reed@google.com | bf79023 | 2013-12-13 19:45:58 +0000 | [diff] [blame] | 58 | fDiscardableMemory = fDMFactory->create(size); |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 59 | fDiscardableMemoryIsLocked = true; |
halcanary@google.com | 2c7c7ee | 2013-12-05 18:31:42 +0000 | [diff] [blame] | 60 | } else { |
reed@google.com | bf79023 | 2013-12-13 19:45:58 +0000 | [diff] [blame] | 61 | fDiscardableMemory = SkDiscardableMemory::Create(size); |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 62 | fDiscardableMemoryIsLocked = true; |
halcanary@google.com | 2c7c7ee | 2013-12-05 18:31:42 +0000 | [diff] [blame] | 63 | } |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 64 | if (nullptr == fDiscardableMemory) { |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 65 | fDiscardableMemoryIsLocked = false; |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 66 | return false; // Memory allocation failed. |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 67 | } |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 68 | |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 69 | void* pixels = fDiscardableMemory->data(); |
commit-bot@chromium.org | 00f8d6c | 2014-05-29 15:57:20 +0000 | [diff] [blame] | 70 | const SkImageInfo& info = this->info(); |
| 71 | SkPMColor colors[256]; |
| 72 | int colorCount = 0; |
| 73 | |
scroggo | 5315fd4 | 2015-07-09 09:08:00 -0700 | [diff] [blame] | 74 | if (!fGenerator->getPixels(info, pixels, fRowBytes, colors, &colorCount)) { |
| 75 | fDiscardableMemory->unlock(); |
| 76 | fDiscardableMemoryIsLocked = false; |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 77 | delete fDiscardableMemory; |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 78 | fDiscardableMemory = nullptr; |
scroggo | 5315fd4 | 2015-07-09 09:08:00 -0700 | [diff] [blame] | 79 | return false; |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 80 | } |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 81 | |
bsalomon | 63c992f | 2015-01-23 12:47:59 -0800 | [diff] [blame] | 82 | // Note: our ctable is not purgeable, as it is not stored in the discardablememory block. |
commit-bot@chromium.org | 00f8d6c | 2014-05-29 15:57:20 +0000 | [diff] [blame] | 83 | // This is because SkColorTable is refcntable, and therefore our caller could hold onto it |
| 84 | // beyond the scope of a lock/unlock. If we change the API/lifecycle for SkColorTable, we |
| 85 | // could move it into the block, but then again perhaps it is small enough that this doesn't |
| 86 | // really matter. |
| 87 | if (colorCount > 0) { |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 88 | fCTable.reset(new SkColorTable(colors, colorCount)); |
commit-bot@chromium.org | 00f8d6c | 2014-05-29 15:57:20 +0000 | [diff] [blame] | 89 | } else { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 90 | fCTable.reset(nullptr); |
commit-bot@chromium.org | 00f8d6c | 2014-05-29 15:57:20 +0000 | [diff] [blame] | 91 | } |
| 92 | |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 93 | rec->fPixels = pixels; |
commit-bot@chromium.org | 00f8d6c | 2014-05-29 15:57:20 +0000 | [diff] [blame] | 94 | rec->fColorTable = fCTable.get(); |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 95 | rec->fRowBytes = fRowBytes; |
| 96 | return true; |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 97 | } |
reed@google.com | d0419b1 | 2014-01-06 17:08:27 +0000 | [diff] [blame] | 98 | |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 99 | void SkDiscardablePixelRef::onUnlockPixels() { |
reed@google.com | c83a91f | 2013-12-13 13:41:14 +0000 | [diff] [blame] | 100 | fDiscardableMemory->unlock(); |
mtklein | 96d68b7 | 2015-02-20 12:40:40 -0800 | [diff] [blame] | 101 | fDiscardableMemoryIsLocked = false; |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 102 | } |
| 103 | |
reed | d114645 | 2015-09-25 06:56:57 -0700 | [diff] [blame^] | 104 | bool SkDEPRECATED_InstallDiscardablePixelRef(SkImageGenerator* generator, const SkIRect* subset, |
| 105 | SkBitmap* dst, SkDiscardableMemory::Factory* factory) { |
halcanary@google.com | 3d50ea1 | 2014-01-02 13:15:13 +0000 | [diff] [blame] | 106 | SkAutoTDelete<SkImageGenerator> autoGenerator(generator); |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 107 | if (nullptr == autoGenerator.get()) { |
reed | 3ef71e3 | 2015-03-19 08:31:14 -0700 | [diff] [blame] | 108 | return false; |
| 109 | } |
reed | 871872f | 2015-06-22 12:48:26 -0700 | [diff] [blame] | 110 | |
| 111 | SkImageInfo prInfo = autoGenerator->getInfo(); |
| 112 | if (prInfo.isEmpty()) { |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 113 | return false; |
| 114 | } |
reed | b75b2c0 | 2014-08-29 08:23:55 -0700 | [diff] [blame] | 115 | |
reed | 871872f | 2015-06-22 12:48:26 -0700 | [diff] [blame] | 116 | SkIPoint origin = SkIPoint::Make(0, 0); |
| 117 | SkImageInfo bmInfo = prInfo; |
| 118 | if (subset) { |
| 119 | const SkIRect prBounds = SkIRect::MakeWH(prInfo.width(), prInfo.height()); |
| 120 | if (subset->isEmpty() || !prBounds.contains(*subset)) { |
| 121 | return false; |
| 122 | } |
| 123 | bmInfo = prInfo.makeWH(subset->width(), subset->height()); |
| 124 | origin.set(subset->x(), subset->y()); |
| 125 | } |
| 126 | |
| 127 | // must compute our desired rowBytes w.r.t. the pixelRef's dimensions, not ours, which may be |
| 128 | // smaller. |
| 129 | if (!dst->setInfo(bmInfo, prInfo.minRowBytes())) { |
| 130 | return false; |
| 131 | } |
| 132 | |
| 133 | // Since dst->setInfo() may have changed/fixed-up info, we check from the bitmap |
| 134 | SkASSERT(dst->info().colorType() != kUnknown_SkColorType); |
| 135 | |
halcanary@google.com | 3d50ea1 | 2014-01-02 13:15:13 +0000 | [diff] [blame] | 136 | if (dst->empty()) { // Use a normal pixelref. |
reed | 8482504 | 2014-09-02 12:50:45 -0700 | [diff] [blame] | 137 | return dst->tryAllocPixels(); |
halcanary@google.com | edd370f | 2013-12-10 21:11:12 +0000 | [diff] [blame] | 138 | } |
halcanary@google.com | 3d50ea1 | 2014-01-02 13:15:13 +0000 | [diff] [blame] | 139 | SkAutoTUnref<SkDiscardablePixelRef> ref( |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 140 | new SkDiscardablePixelRef(prInfo, autoGenerator.detach(), dst->rowBytes(), factory)); |
reed | 871872f | 2015-06-22 12:48:26 -0700 | [diff] [blame] | 141 | dst->setPixelRef(ref, origin.x(), origin.y()); |
halcanary@google.com | ad04eb4 | 2013-11-21 15:32:08 +0000 | [diff] [blame] | 142 | return true; |
| 143 | } |
commit-bot@chromium.org | 2d970b5 | 2014-05-27 14:14:22 +0000 | [diff] [blame] | 144 | |
reed | 5965c8a | 2015-01-07 18:04:45 -0800 | [diff] [blame] | 145 | // These are the public API |
| 146 | |
reed | d114645 | 2015-09-25 06:56:57 -0700 | [diff] [blame^] | 147 | bool SkDEPRECATED_InstallDiscardablePixelRef(SkImageGenerator* generator, SkBitmap* dst) { |
| 148 | return SkDEPRECATED_InstallDiscardablePixelRef(generator, nullptr, dst, nullptr); |
commit-bot@chromium.org | 2d970b5 | 2014-05-27 14:14:22 +0000 | [diff] [blame] | 149 | } |
reed | 5965c8a | 2015-01-07 18:04:45 -0800 | [diff] [blame] | 150 | |
reed | d114645 | 2015-09-25 06:56:57 -0700 | [diff] [blame^] | 151 | bool SkDEPRECATED_InstallDiscardablePixelRef(SkData* encoded, SkBitmap* dst) { |
reed | 1c84634 | 2015-07-09 11:47:36 -0700 | [diff] [blame] | 152 | SkImageGenerator* generator = SkImageGenerator::NewFromEncoded(encoded); |
reed | d114645 | 2015-09-25 06:56:57 -0700 | [diff] [blame^] | 153 | return generator ? |
| 154 | SkDEPRECATED_InstallDiscardablePixelRef(generator, nullptr, dst, nullptr) : false; |
reed | 5965c8a | 2015-01-07 18:04:45 -0800 | [diff] [blame] | 155 | } |