blob: d378032c062dd243a6021185499d7afce0447a5f [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"
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000012#include "GrContext.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000013#include "GrTexture.h"
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000014#include "SkGr.h"
bsalomon@google.com669fdc42011-04-05 17:08:27 +000015#include "SkRect.h"
reed@google.com9c49bc32011-07-07 13:42:37 +000016
17// since we call lockPixels recursively on fBitmap, we need a distinct mutex,
18// to avoid deadlock with the default one provided by SkPixelRef.
digit@google.com1771cbf2012-01-26 21:26:40 +000019SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex);
reed@google.com9c49bc32011-07-07 13:42:37 +000020
reed@google.combf790232013-12-13 19:45:58 +000021SkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info)
22 : INHERITED(info, &gROLockPixelsPixelRefMutex) {}
reed@google.com9c49bc32011-07-07 13:42:37 +000023
reed@google.combf790232013-12-13 19:45:58 +000024SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {}
reed@google.com9c49bc32011-07-07 13:42:37 +000025
reed@google.comd0419b12014-01-06 17:08:27 +000026bool SkROLockPixelsPixelRef::onNewLockPixels(LockRec* rec) {
reed@google.com9c49bc32011-07-07 13:42:37 +000027 fBitmap.reset();
28// SkDebugf("---------- calling readpixels in support of lockpixels\n");
29 if (!this->onReadPixels(&fBitmap, NULL)) {
30 SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
reed@google.comd0419b12014-01-06 17:08:27 +000031 return false;
reed@google.com9c49bc32011-07-07 13:42:37 +000032 }
33 fBitmap.lockPixels();
reed@google.comd0419b12014-01-06 17:08:27 +000034 if (NULL == fBitmap.getPixels()) {
35 return false;
36 }
37
38 rec->fPixels = fBitmap.getPixels();
39 rec->fColorTable = NULL;
40 rec->fRowBytes = fBitmap.rowBytes();
41 return true;
reed@google.com9c49bc32011-07-07 13:42:37 +000042}
43
44void SkROLockPixelsPixelRef::onUnlockPixels() {
45 fBitmap.unlockPixels();
46}
47
48bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
49 return false;
50}
51
52///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com669fdc42011-04-05 17:08:27 +000053
reede4538f52014-06-11 06:09:50 -070054static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkColorType dstCT,
commit-bot@chromium.orgeeef0cc2014-05-21 15:58:00 +000055 const SkIRect* subset) {
reede4538f52014-06-11 06:09:50 -070056 if (NULL == texture || kUnknown_SkColorType == dstCT) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000057 return NULL;
58 }
59 GrContext* context = texture->getContext();
60 if (NULL == context) {
61 return NULL;
62 }
63 GrTextureDesc desc;
64
scroggo@google.coma2a31922012-12-07 19:14:45 +000065 SkIPoint pointStorage;
66 SkIPoint* topLeft;
67 if (subset != NULL) {
68 SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset));
69 // Create a new texture that is the size of subset.
70 desc.fWidth = subset->width();
71 desc.fHeight = subset->height();
72 pointStorage.set(subset->x(), subset->y());
73 topLeft = &pointStorage;
74 } else {
75 desc.fWidth = texture->width();
76 desc.fHeight = texture->height();
77 topLeft = NULL;
78 }
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000079 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
reede4538f52014-06-11 06:09:50 -070080 desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType);
skia.committer@gmail.com96f5fa02013-12-16 07:01:40 +000081
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000082 GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
83 if (NULL == dst) {
84 return NULL;
85 }
86
scroggo@google.coma2a31922012-12-07 19:14:45 +000087 context->copyTexture(texture, dst->asRenderTarget(), topLeft);
robertphillips@google.comd881bc12012-06-28 20:02:39 +000088
robertphillips@google.com41efe042012-06-29 20:55:14 +000089 // TODO: figure out if this is responsible for Chrome canvas errors
90#if 0
robertphillips@google.comd881bc12012-06-28 20:02:39 +000091 // The render texture we have created (to perform the copy) isn't fully
92 // functional (since it doesn't have a stencil buffer). Release it here
93 // so the caller doesn't try to render to it.
94 // TODO: we can undo this release when dynamic stencil buffer attach/
95 // detach has been implemented
96 dst->releaseRenderTarget();
robertphillips@google.com41efe042012-06-29 20:55:14 +000097#endif
robertphillips@google.comd881bc12012-06-28 20:02:39 +000098
reede4538f52014-06-11 06:09:50 -070099 SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType);
reed@google.combf790232013-12-13 19:45:58 +0000100 SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000101 SkSafeUnref(dst);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000102 return pixelRef;
103}
104
105///////////////////////////////////////////////////////////////////////////////
106
reed@google.combf790232013-12-13 19:45:58 +0000107SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface,
108 bool transferCacheLock) : INHERITED(info) {
bsalomon71875932014-08-29 08:08:35 -0700109 // For surfaces that are both textures and render targets, the texture owns the
110 // render target but not vice versa. So we ref the texture to keep both alive for
111 // the lifetime of this pixel ref.
112 fSurface = SkSafeRef(surface->asTexture());
reed@google.com61867872013-12-09 13:41:06 +0000113 if (NULL == fSurface) {
bsalomon71875932014-08-29 08:08:35 -0700114 fSurface = SkSafeRef(surface);
reed@google.com61867872013-12-09 13:41:06 +0000115 }
116 fUnlock = transferCacheLock;
commit-bot@chromium.org8e0993d2014-01-28 15:16:45 +0000117
118 if (fSurface) {
119 SkASSERT(info.fWidth <= fSurface->width());
120 SkASSERT(info.fHeight <= fSurface->height());
121 }
reed@google.com61867872013-12-09 13:41:06 +0000122}
123
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000124SkGrPixelRef::~SkGrPixelRef() {
bsalomon@google.com8090e652012-08-28 15:07:11 +0000125 if (fUnlock) {
126 GrContext* context = fSurface->getContext();
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000127 GrTexture* texture = fSurface->asTexture();
bsalomon@google.com8090e652012-08-28 15:07:11 +0000128 if (NULL != context && NULL != texture) {
robertphillips@google.com9fbcad02012-09-09 14:44:15 +0000129 context->unlockScratchTexture(texture);
bsalomon@google.com8090e652012-08-28 15:07:11 +0000130 }
131 }
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000132 SkSafeUnref(fSurface);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000133}
134
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000135GrTexture* SkGrPixelRef::getTexture() {
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000136 if (NULL != fSurface) {
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000137 return fSurface->asTexture();
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000138 }
139 return NULL;
140}
141
reede4538f52014-06-11 06:09:50 -0700142SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, const SkIRect* subset) {
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000143 if (NULL == fSurface) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000144 return NULL;
145 }
reede4538f52014-06-11 06:09:50 -0700146
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000147 // Note that when copying a render-target-backed pixel ref, we
148 // return a texture-backed pixel ref instead. This is because
149 // render-target pixel refs are usually created in conjunction with
150 // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
151 // independently of that texture. Texture-backed pixel refs, on the other
152 // hand, own their GrTextures, and are thus self-contained.
reede4538f52014-06-11 06:09:50 -0700153 return copyToTexturePixelRef(fSurface->asTexture(), dstCT, subset);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000154}
155
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000156bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
commit-bot@chromium.org089a7802014-05-02 21:38:22 +0000157 if (NULL == fSurface || fSurface->wasDestroyed()) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000158 return false;
159 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000160
161 int left, top, width, height;
162 if (NULL != subset) {
163 left = subset->fLeft;
164 width = subset->width();
165 top = subset->fTop;
166 height = subset->height();
167 } else {
168 left = 0;
commit-bot@chromium.org8e0993d2014-01-28 15:16:45 +0000169 width = this->info().fWidth;
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000170 top = 0;
commit-bot@chromium.org8e0993d2014-01-28 15:16:45 +0000171 height = this->info().fHeight;
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000172 }
reed@google.com9ebcac52014-01-24 18:53:42 +0000173 if (!dst->allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
bsalomon@google.com009bcca2012-12-18 21:40:08 +0000174 SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n");
175 return false;
176 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000177 SkAutoLockPixels al(*dst);
178 void* buffer = dst->getPixels();
179 return fSurface->readPixels(left, top, width, height,
bsalomon@google.comfec0bc32013-02-07 14:43:04 +0000180 kSkia8888_GrPixelConfig,
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000181 buffer, dst->rowBytes());
reed@google.com4281d652011-04-08 18:54:20 +0000182}