blob: a068d8dcc13f6fffb65aa58b608fabafa9fc4db6 [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
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000026void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) {
27 if (ctable) {
28 *ctable = NULL;
29 }
reed@google.com9c49bc32011-07-07 13:42:37 +000030 fBitmap.reset();
31// SkDebugf("---------- calling readpixels in support of lockpixels\n");
32 if (!this->onReadPixels(&fBitmap, NULL)) {
33 SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000034 return NULL;
reed@google.com9c49bc32011-07-07 13:42:37 +000035 }
36 fBitmap.lockPixels();
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000037 return fBitmap.getPixels();
reed@google.com9c49bc32011-07-07 13:42:37 +000038}
39
40void SkROLockPixelsPixelRef::onUnlockPixels() {
41 fBitmap.unlockPixels();
42}
43
44bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
45 return false;
46}
47
48///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com669fdc42011-04-05 17:08:27 +000049
scroggo@google.coma2a31922012-12-07 19:14:45 +000050static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config dstConfig,
51 const SkIRect* subset) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000052 if (NULL == texture) {
53 return NULL;
54 }
55 GrContext* context = texture->getContext();
56 if (NULL == context) {
57 return NULL;
58 }
59 GrTextureDesc desc;
60
scroggo@google.coma2a31922012-12-07 19:14:45 +000061 SkIPoint pointStorage;
62 SkIPoint* topLeft;
63 if (subset != NULL) {
64 SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset));
65 // Create a new texture that is the size of subset.
66 desc.fWidth = subset->width();
67 desc.fHeight = subset->height();
68 pointStorage.set(subset->x(), subset->y());
69 topLeft = &pointStorage;
70 } else {
71 desc.fWidth = texture->width();
72 desc.fHeight = texture->height();
73 topLeft = NULL;
74 }
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000075 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
rileya@google.com24f3ad12012-07-18 21:47:40 +000076 desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000077
reed@google.combf790232013-12-13 19:45:58 +000078 SkImageInfo info;
79 if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
80 return NULL;
81 }
82 info.fWidth = desc.fWidth;
83 info.fHeight = desc.fHeight;
84 info.fAlphaType = kPremul_SkAlphaType;
skia.committer@gmail.com96f5fa02013-12-16 07:01:40 +000085
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000086 GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
87 if (NULL == dst) {
88 return NULL;
89 }
90
scroggo@google.coma2a31922012-12-07 19:14:45 +000091 context->copyTexture(texture, dst->asRenderTarget(), topLeft);
robertphillips@google.comd881bc12012-06-28 20:02:39 +000092
robertphillips@google.com41efe042012-06-29 20:55:14 +000093 // TODO: figure out if this is responsible for Chrome canvas errors
94#if 0
robertphillips@google.comd881bc12012-06-28 20:02:39 +000095 // The render texture we have created (to perform the copy) isn't fully
96 // functional (since it doesn't have a stencil buffer). Release it here
97 // so the caller doesn't try to render to it.
98 // TODO: we can undo this release when dynamic stencil buffer attach/
99 // detach has been implemented
100 dst->releaseRenderTarget();
robertphillips@google.com41efe042012-06-29 20:55:14 +0000101#endif
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000102
reed@google.combf790232013-12-13 19:45:58 +0000103 SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000104 SkSafeUnref(dst);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000105 return pixelRef;
106}
107
108///////////////////////////////////////////////////////////////////////////////
109
reed@google.combf790232013-12-13 19:45:58 +0000110SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface,
111 bool transferCacheLock) : INHERITED(info) {
reed@google.com61867872013-12-09 13:41:06 +0000112 // TODO: figure out if this is responsible for Chrome canvas errors
113#if 0
114 // The GrTexture has a ref to the GrRenderTarget but not vice versa.
115 // If the GrTexture exists take a ref to that (rather than the render
116 // target)
117 fSurface = surface->asTexture();
118#else
119 fSurface = NULL;
120#endif
121 if (NULL == fSurface) {
122 fSurface = surface;
123 }
124 fUnlock = transferCacheLock;
125 SkSafeRef(surface);
126}
127
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000128SkGrPixelRef::~SkGrPixelRef() {
bsalomon@google.com8090e652012-08-28 15:07:11 +0000129 if (fUnlock) {
130 GrContext* context = fSurface->getContext();
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000131 GrTexture* texture = fSurface->asTexture();
bsalomon@google.com8090e652012-08-28 15:07:11 +0000132 if (NULL != context && NULL != texture) {
robertphillips@google.com9fbcad02012-09-09 14:44:15 +0000133 context->unlockScratchTexture(texture);
bsalomon@google.com8090e652012-08-28 15:07:11 +0000134 }
135 }
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000136 SkSafeUnref(fSurface);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000137}
138
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000139GrTexture* SkGrPixelRef::getTexture() {
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000140 if (NULL != fSurface) {
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000141 return fSurface->asTexture();
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000142 }
143 return NULL;
144}
145
scroggo@google.coma2a31922012-12-07 19:14:45 +0000146SkPixelRef* SkGrPixelRef::deepCopy(SkBitmap::Config dstConfig, const SkIRect* subset) {
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000147 if (NULL == fSurface) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000148 return NULL;
149 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000150
151 // Note that when copying a render-target-backed pixel ref, we
152 // return a texture-backed pixel ref instead. This is because
153 // render-target pixel refs are usually created in conjunction with
154 // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
155 // independently of that texture. Texture-backed pixel refs, on the other
156 // hand, own their GrTextures, and are thus self-contained.
scroggo@google.coma2a31922012-12-07 19:14:45 +0000157 return copyToTexturePixelRef(fSurface->asTexture(), dstConfig, subset);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000158}
159
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000160bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
161 if (NULL == fSurface || !fSurface->isValid()) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000162 return false;
163 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000164
165 int left, top, width, height;
166 if (NULL != subset) {
167 left = subset->fLeft;
168 width = subset->width();
169 top = subset->fTop;
170 height = subset->height();
171 } else {
172 left = 0;
173 width = fSurface->width();
174 top = 0;
175 height = fSurface->height();
176 }
177 dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
bsalomon@google.com009bcca2012-12-18 21:40:08 +0000178 if (!dst->allocPixels()) {
179 SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n");
180 return false;
181 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000182 SkAutoLockPixels al(*dst);
183 void* buffer = dst->getPixels();
184 return fSurface->readPixels(left, top, width, height,
bsalomon@google.comfec0bc32013-02-07 14:43:04 +0000185 kSkia8888_GrPixelConfig,
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000186 buffer, dst->rowBytes());
reed@google.com4281d652011-04-08 18:54:20 +0000187}