blob: 6e014feded1faba16afb4b0607349857a6172ce0 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
robertphillips@google.com5088eb42012-06-28 20:59:13 +000011#include "SkGrPixelRef.h"
piotaixr0e977052014-09-17 16:24:04 -070012
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000013#include "GrContext.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000014#include "GrTexture.h"
junovda5469d2015-06-15 09:48:15 -070015#include "GrTexturePriv.h"
piotaixr0e977052014-09-17 16:24:04 -070016#include "SkBitmapCache.h"
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000017#include "SkGr.h"
bsalomon@google.com669fdc42011-04-05 17:08:27 +000018#include "SkRect.h"
reed@google.com9c49bc32011-07-07 13:42:37 +000019
reed@google.combf790232013-12-13 19:45:58 +000020SkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info)
mtklein7e6d9c02015-08-13 14:02:06 -070021 : INHERITED(info) {}
reed@google.com9c49bc32011-07-07 13:42:37 +000022
reed@google.combf790232013-12-13 19:45:58 +000023SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {}
reed@google.com9c49bc32011-07-07 13:42:37 +000024
reed@google.comd0419b12014-01-06 17:08:27 +000025bool SkROLockPixelsPixelRef::onNewLockPixels(LockRec* rec) {
reed@google.com9c49bc32011-07-07 13:42:37 +000026 fBitmap.reset();
27// SkDebugf("---------- calling readpixels in support of lockpixels\n");
halcanary96fcdcc2015-08-27 07:41:13 -070028 if (!this->onReadPixels(&fBitmap, nullptr)) {
reed@google.com9c49bc32011-07-07 13:42:37 +000029 SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
reed@google.comd0419b12014-01-06 17:08:27 +000030 return false;
reed@google.com9c49bc32011-07-07 13:42:37 +000031 }
32 fBitmap.lockPixels();
halcanary96fcdcc2015-08-27 07:41:13 -070033 if (nullptr == fBitmap.getPixels()) {
reed@google.comd0419b12014-01-06 17:08:27 +000034 return false;
35 }
36
37 rec->fPixels = fBitmap.getPixels();
halcanary96fcdcc2015-08-27 07:41:13 -070038 rec->fColorTable = nullptr;
reed@google.comd0419b12014-01-06 17:08:27 +000039 rec->fRowBytes = fBitmap.rowBytes();
40 return true;
reed@google.com9c49bc32011-07-07 13:42:37 +000041}
42
43void SkROLockPixelsPixelRef::onUnlockPixels() {
44 fBitmap.unlockPixels();
45}
46
47bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
48 return false;
49}
50
51///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com669fdc42011-04-05 17:08:27 +000052
junov96c118e2014-09-26 13:09:47 -070053static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorType dstCT,
jvanverthfa1e8a72014-12-22 08:31:49 -080054 SkColorProfileType dstPT, const SkIRect* subset) {
halcanary96fcdcc2015-08-27 07:41:13 -070055 if (nullptr == texture || kUnknown_SkColorType == dstCT) {
56 return nullptr;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000057 }
58 GrContext* context = texture->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -070059 if (nullptr == context) {
60 return nullptr;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000061 }
bsalomonf2703d82014-10-28 14:33:06 -070062 GrSurfaceDesc desc;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000063
bsalomonf80bfed2014-10-07 05:56:02 -070064 SkIRect srcRect;
65
66 if (!subset) {
67 desc.fWidth = texture->width();
68 desc.fHeight = texture->height();
69 srcRect = SkIRect::MakeWH(texture->width(), texture->height());
70 } else {
scroggo@google.coma2a31922012-12-07 19:14:45 +000071 SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset));
72 // Create a new texture that is the size of subset.
73 desc.fWidth = subset->width();
74 desc.fHeight = subset->height();
bsalomonf80bfed2014-10-07 05:56:02 -070075 srcRect = *subset;
scroggo@google.coma2a31922012-12-07 19:14:45 +000076 }
bsalomon6bc1b5f2015-02-23 09:06:38 -080077 desc.fFlags = kRenderTarget_GrSurfaceFlag;
jvanverthfa1e8a72014-12-22 08:31:49 -080078 desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType, dstPT);
skia.committer@gmail.com96f5fa02013-12-16 07:01:40 +000079
halcanary96fcdcc2015-08-27 07:41:13 -070080 GrTexture* dst = context->textureProvider()->createTexture(desc, false, nullptr, 0);
81 if (nullptr == dst) {
82 return nullptr;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000083 }
84
junov96c118e2014-09-26 13:09:47 -070085 // Blink is relying on the above copy being sent to GL immediately in the case when the source
bsalomonf80bfed2014-10-07 05:56:02 -070086 // is a WebGL canvas backing store. We could have a TODO to remove this flush flag, but we have
87 // a larger TODO to remove SkGrPixelRef entirely.
88 context->copySurface(dst->asRenderTarget(), texture, srcRect, SkIPoint::Make(0,0),
89 GrContext::kFlushWrites_PixelOp);
mtklein7e6d9c02015-08-13 14:02:06 -070090
jvanverthfa1e8a72014-12-22 08:31:49 -080091 SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType,
92 dstPT);
halcanary385fe4d2015-08-26 13:07:48 -070093 SkGrPixelRef* pixelRef = new SkGrPixelRef(info, dst);
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +000094 SkSafeUnref(dst);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000095 return pixelRef;
96}
97
98///////////////////////////////////////////////////////////////////////////////
99
bsalomonbcf0a522014-10-08 08:40:09 -0700100SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface) : INHERITED(info) {
bsalomon71875932014-08-29 08:08:35 -0700101 // For surfaces that are both textures and render targets, the texture owns the
102 // render target but not vice versa. So we ref the texture to keep both alive for
103 // the lifetime of this pixel ref.
104 fSurface = SkSafeRef(surface->asTexture());
halcanary96fcdcc2015-08-27 07:41:13 -0700105 if (nullptr == fSurface) {
bsalomon71875932014-08-29 08:08:35 -0700106 fSurface = SkSafeRef(surface);
reed@google.com61867872013-12-09 13:41:06 +0000107 }
commit-bot@chromium.org8e0993d2014-01-28 15:16:45 +0000108
109 if (fSurface) {
reede5ea5002014-09-03 11:54:58 -0700110 SkASSERT(info.width() <= fSurface->width());
111 SkASSERT(info.height() <= fSurface->height());
commit-bot@chromium.org8e0993d2014-01-28 15:16:45 +0000112 }
reed@google.com61867872013-12-09 13:41:06 +0000113}
114
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000115SkGrPixelRef::~SkGrPixelRef() {
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000116 SkSafeUnref(fSurface);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000117}
118
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000119GrTexture* SkGrPixelRef::getTexture() {
bsalomon49f085d2014-09-05 13:34:00 -0700120 if (fSurface) {
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000121 return fSurface->asTexture();
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000122 }
halcanary96fcdcc2015-08-27 07:41:13 -0700123 return nullptr;
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000124}
125
junovda5469d2015-06-15 09:48:15 -0700126void SkGrPixelRef::onNotifyPixelsChanged() {
127 GrTexture* texture = this->getTexture();
128 if (texture) {
129 texture->texturePriv().dirtyMipMaps(true);
130 }
131}
132
jvanverthfa1e8a72014-12-22 08:31:49 -0800133SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, SkColorProfileType dstPT,
134 const SkIRect* subset) {
halcanary96fcdcc2015-08-27 07:41:13 -0700135 if (nullptr == fSurface) {
136 return nullptr;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000137 }
piotaixr0e977052014-09-17 16:24:04 -0700138
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000139 // Note that when copying a render-target-backed pixel ref, we
140 // return a texture-backed pixel ref instead. This is because
141 // render-target pixel refs are usually created in conjunction with
142 // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
143 // independently of that texture. Texture-backed pixel refs, on the other
144 // hand, own their GrTextures, and are thus self-contained.
jvanverthfa1e8a72014-12-22 08:31:49 -0800145 return copy_to_new_texture_pixelref(fSurface->asTexture(), dstCT, dstPT, subset);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000146}
147
piotaixr0e977052014-09-17 16:24:04 -0700148static bool tryAllocBitmapPixels(SkBitmap* bitmap) {
149 SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator();
halcanary96fcdcc2015-08-27 07:41:13 -0700150 if (nullptr != allocator) {
piotaixr0e977052014-09-17 16:24:04 -0700151 return allocator->allocPixelRef(bitmap, 0);
152 } else {
153 // DiscardableMemory is not available, fallback to default allocator
154 return bitmap->tryAllocPixels();
155 }
156}
157
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000158bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
halcanary96fcdcc2015-08-27 07:41:13 -0700159 if (nullptr == fSurface || fSurface->wasDestroyed()) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000160 return false;
161 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000162
piotaixr0e977052014-09-17 16:24:04 -0700163 SkIRect bounds;
bsalomon49f085d2014-09-05 13:34:00 -0700164 if (subset) {
piotaixr0e977052014-09-17 16:24:04 -0700165 bounds = *subset;
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000166 } else {
piotaixr0e977052014-09-17 16:24:04 -0700167 bounds = SkIRect::MakeWH(this->info().width(), this->info().height());
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000168 }
piotaixr0e977052014-09-17 16:24:04 -0700169
170 //Check the cache
171 if(!SkBitmapCache::Find(this->getGenerationID(), bounds, dst)) {
172 //Cache miss
173
174 SkBitmap cachedBitmap;
175 cachedBitmap.setInfo(this->info().makeWH(bounds.width(), bounds.height()));
176
177 // If we can't alloc the pixels, then fail
178 if (!tryAllocBitmapPixels(&cachedBitmap)) {
179 return false;
180 }
181
182 // Try to read the pixels from the surface
183 void* buffer = cachedBitmap.getPixels();
184 bool readPixelsOk = fSurface->readPixels(bounds.fLeft, bounds.fTop,
185 bounds.width(), bounds.height(),
bsalomon@google.comfec0bc32013-02-07 14:43:04 +0000186 kSkia8888_GrPixelConfig,
piotaixr0e977052014-09-17 16:24:04 -0700187 buffer, cachedBitmap.rowBytes());
188
189 if (!readPixelsOk) {
190 return false;
191 }
192
193 // If we are here, pixels were read correctly from the surface.
194 cachedBitmap.setImmutable();
195 //Add to the cache
reed83787d02015-02-25 07:17:11 -0800196 SkBitmapCache::Add(this, bounds, cachedBitmap);
piotaixr0e977052014-09-17 16:24:04 -0700197
198 dst->swap(cachedBitmap);
199 }
200
201 return true;
202
reed@google.com4281d652011-04-08 18:54:20 +0000203}