blob: 012942667c72b8c134ef8333b2deb708cd11c8ee [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
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000021SkROLockPixelsPixelRef::SkROLockPixelsPixelRef() : INHERITED(&gROLockPixelsPixelRefMutex) {
reed@google.com9c49bc32011-07-07 13:42:37 +000022}
23
24SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {
25}
26
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000027void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) {
28 if (ctable) {
29 *ctable = NULL;
30 }
reed@google.com9c49bc32011-07-07 13:42:37 +000031 fBitmap.reset();
32// SkDebugf("---------- calling readpixels in support of lockpixels\n");
33 if (!this->onReadPixels(&fBitmap, NULL)) {
34 SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000035 return NULL;
reed@google.com9c49bc32011-07-07 13:42:37 +000036 }
37 fBitmap.lockPixels();
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000038 return fBitmap.getPixels();
reed@google.com9c49bc32011-07-07 13:42:37 +000039}
40
41void SkROLockPixelsPixelRef::onUnlockPixels() {
42 fBitmap.unlockPixels();
43}
44
45bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
46 return false;
47}
48
49///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com669fdc42011-04-05 17:08:27 +000050
scroggo@google.coma2a31922012-12-07 19:14:45 +000051static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config dstConfig,
52 const SkIRect* subset) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000053 if (NULL == texture) {
54 return NULL;
55 }
56 GrContext* context = texture->getContext();
57 if (NULL == context) {
58 return NULL;
59 }
60 GrTextureDesc desc;
61
scroggo@google.coma2a31922012-12-07 19:14:45 +000062 SkIPoint pointStorage;
63 SkIPoint* topLeft;
64 if (subset != NULL) {
65 SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset));
66 // Create a new texture that is the size of subset.
67 desc.fWidth = subset->width();
68 desc.fHeight = subset->height();
69 pointStorage.set(subset->x(), subset->y());
70 topLeft = &pointStorage;
71 } else {
72 desc.fWidth = texture->width();
73 desc.fHeight = texture->height();
74 topLeft = NULL;
75 }
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000076 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
rileya@google.com24f3ad12012-07-18 21:47:40 +000077 desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000078
79 GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
80 if (NULL == dst) {
81 return NULL;
82 }
83
scroggo@google.coma2a31922012-12-07 19:14:45 +000084 context->copyTexture(texture, dst->asRenderTarget(), topLeft);
robertphillips@google.comd881bc12012-06-28 20:02:39 +000085
robertphillips@google.com41efe042012-06-29 20:55:14 +000086 // TODO: figure out if this is responsible for Chrome canvas errors
87#if 0
robertphillips@google.comd881bc12012-06-28 20:02:39 +000088 // The render texture we have created (to perform the copy) isn't fully
89 // functional (since it doesn't have a stencil buffer). Release it here
90 // so the caller doesn't try to render to it.
91 // TODO: we can undo this release when dynamic stencil buffer attach/
92 // detach has been implemented
93 dst->releaseRenderTarget();
robertphillips@google.com41efe042012-06-29 20:55:14 +000094#endif
robertphillips@google.comd881bc12012-06-28 20:02:39 +000095
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000096 SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (dst));
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +000097 SkSafeUnref(dst);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000098 return pixelRef;
99}
100
101///////////////////////////////////////////////////////////////////////////////
102
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +0000103SkGrPixelRef::SkGrPixelRef(GrSurface* surface, bool transferCacheLock) {
104 // TODO: figure out if this is responsible for Chrome canvas errors
105#if 0
106 // The GrTexture has a ref to the GrRenderTarget but not vice versa.
107 // If the GrTexture exists take a ref to that (rather than the render
108 // target)
109 fSurface = surface->asTexture();
110#else
111 fSurface = NULL;
112#endif
113 if (NULL == fSurface) {
114 fSurface = surface;
115 }
116 fUnlock = transferCacheLock;
117 SkSafeRef(surface);
118}
119
120SkGrPixelRef::SkGrPixelRef(const SkImageInfo&, GrSurface* surface, bool transferCacheLock) {
reed@google.com61867872013-12-09 13:41:06 +0000121 // TODO: figure out if this is responsible for Chrome canvas errors
122#if 0
123 // The GrTexture has a ref to the GrRenderTarget but not vice versa.
124 // If the GrTexture exists take a ref to that (rather than the render
125 // target)
126 fSurface = surface->asTexture();
127#else
128 fSurface = NULL;
129#endif
130 if (NULL == fSurface) {
131 fSurface = surface;
132 }
133 fUnlock = transferCacheLock;
134 SkSafeRef(surface);
135}
136
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000137SkGrPixelRef::~SkGrPixelRef() {
bsalomon@google.com8090e652012-08-28 15:07:11 +0000138 if (fUnlock) {
139 GrContext* context = fSurface->getContext();
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000140 GrTexture* texture = fSurface->asTexture();
bsalomon@google.com8090e652012-08-28 15:07:11 +0000141 if (NULL != context && NULL != texture) {
robertphillips@google.com9fbcad02012-09-09 14:44:15 +0000142 context->unlockScratchTexture(texture);
bsalomon@google.com8090e652012-08-28 15:07:11 +0000143 }
144 }
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000145 SkSafeUnref(fSurface);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000146}
147
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000148GrTexture* SkGrPixelRef::getTexture() {
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000149 if (NULL != fSurface) {
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000150 return fSurface->asTexture();
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000151 }
152 return NULL;
153}
154
scroggo@google.coma2a31922012-12-07 19:14:45 +0000155SkPixelRef* SkGrPixelRef::deepCopy(SkBitmap::Config dstConfig, const SkIRect* subset) {
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000156 if (NULL == fSurface) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000157 return NULL;
158 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000159
160 // Note that when copying a render-target-backed pixel ref, we
161 // return a texture-backed pixel ref instead. This is because
162 // render-target pixel refs are usually created in conjunction with
163 // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
164 // independently of that texture. Texture-backed pixel refs, on the other
165 // hand, own their GrTextures, and are thus self-contained.
scroggo@google.coma2a31922012-12-07 19:14:45 +0000166 return copyToTexturePixelRef(fSurface->asTexture(), dstConfig, subset);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000167}
168
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000169bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
170 if (NULL == fSurface || !fSurface->isValid()) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000171 return false;
172 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000173
174 int left, top, width, height;
175 if (NULL != subset) {
176 left = subset->fLeft;
177 width = subset->width();
178 top = subset->fTop;
179 height = subset->height();
180 } else {
181 left = 0;
182 width = fSurface->width();
183 top = 0;
184 height = fSurface->height();
185 }
186 dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
bsalomon@google.com009bcca2012-12-18 21:40:08 +0000187 if (!dst->allocPixels()) {
188 SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n");
189 return false;
190 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000191 SkAutoLockPixels al(*dst);
192 void* buffer = dst->getPixels();
193 return fSurface->readPixels(left, top, width, height,
bsalomon@google.comfec0bc32013-02-07 14:43:04 +0000194 kSkia8888_GrPixelConfig,
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000195 buffer, dst->rowBytes());
reed@google.com4281d652011-04-08 18:54:20 +0000196}