blob: 7e0e2cdcebb97b143e9021ccbc35fe0ffaa18b33 [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
21SkROLockPixelsPixelRef::SkROLockPixelsPixelRef() : INHERITED(&gROLockPixelsPixelRefMutex) {
22}
23
24SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {
25}
26
27void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) {
28 if (ctable) {
29 *ctable = NULL;
30 }
31 fBitmap.reset();
32// SkDebugf("---------- calling readpixels in support of lockpixels\n");
33 if (!this->onReadPixels(&fBitmap, NULL)) {
34 SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
35 return NULL;
36 }
37 fBitmap.lockPixels();
38 return fBitmap.getPixels();
39}
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
robertphillips@google.comd881bc12012-06-28 20:02:39 +000051static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture,
52 SkBitmap::Config dstConfig) {
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
62 desc.fWidth = texture->width();
63 desc.fHeight = texture->height();
64 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
robertphillips@google.coma1e57952012-06-04 20:05:28 +000065 desc.fConfig = SkGr::BitmapConfig2PixelConfig(dstConfig);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000066
67 GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
68 if (NULL == dst) {
69 return NULL;
70 }
71
72 context->copyTexture(texture, dst->asRenderTarget());
robertphillips@google.comd881bc12012-06-28 20:02:39 +000073
robertphillips@google.com41efe042012-06-29 20:55:14 +000074 // TODO: figure out if this is responsible for Chrome canvas errors
75#if 0
robertphillips@google.comd881bc12012-06-28 20:02:39 +000076 // The render texture we have created (to perform the copy) isn't fully
77 // functional (since it doesn't have a stencil buffer). Release it here
78 // so the caller doesn't try to render to it.
79 // TODO: we can undo this release when dynamic stencil buffer attach/
80 // detach has been implemented
81 dst->releaseRenderTarget();
robertphillips@google.com41efe042012-06-29 20:55:14 +000082#endif
robertphillips@google.comd881bc12012-06-28 20:02:39 +000083
tomhudson@google.comc377baf2012-07-09 20:17:56 +000084 SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (dst));
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000085 GrSafeUnref(dst);
86 return pixelRef;
87}
88
89///////////////////////////////////////////////////////////////////////////////
90
robertphillips@google.comd881bc12012-06-28 20:02:39 +000091SkGrPixelRef::SkGrPixelRef(GrSurface* surface) {
robertphillips@google.com41efe042012-06-29 20:55:14 +000092 // TODO: figure out if this is responsible for Chrome canvas errors
93#if 0
robertphillips@google.comd881bc12012-06-28 20:02:39 +000094 // The GrTexture has a ref to the GrRenderTarget but not vice versa.
95 // If the GrTexture exists take a ref to that (rather than the render
96 // target)
97 fSurface = surface->asTexture();
robertphillips@google.com41efe042012-06-29 20:55:14 +000098#else
99 fSurface = NULL;
100#endif
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000101 if (NULL == fSurface) {
102 fSurface = surface;
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000103 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000104
105 GrSafeRef(surface);
reed@google.com50dfa012011-04-01 19:05:36 +0000106}
reed@google.comac10a2d2010-12-22 21:39:39 +0000107
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000108SkGrPixelRef::~SkGrPixelRef() {
109 GrSafeUnref(fSurface);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000110}
111
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000112SkGpuTexture* SkGrPixelRef::getTexture() {
113 if (NULL != fSurface) {
114 return (SkGpuTexture*) fSurface->asTexture();
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000115 }
116 return NULL;
117}
118
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000119SkPixelRef* SkGrPixelRef::deepCopy(SkBitmap::Config dstConfig) {
120 if (NULL == fSurface) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000121 return NULL;
122 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000123
124 // Note that when copying a render-target-backed pixel ref, we
125 // return a texture-backed pixel ref instead. This is because
126 // render-target pixel refs are usually created in conjunction with
127 // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
128 // independently of that texture. Texture-backed pixel refs, on the other
129 // hand, own their GrTextures, and are thus self-contained.
130 return copyToTexturePixelRef(fSurface->asTexture(), dstConfig);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000131}
132
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000133bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
134 if (NULL == fSurface || !fSurface->isValid()) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000135 return false;
136 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000137
138 int left, top, width, height;
139 if (NULL != subset) {
140 left = subset->fLeft;
141 width = subset->width();
142 top = subset->fTop;
143 height = subset->height();
144 } else {
145 left = 0;
146 width = fSurface->width();
147 top = 0;
148 height = fSurface->height();
149 }
150 dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
151 dst->allocPixels();
152 SkAutoLockPixels al(*dst);
153 void* buffer = dst->getPixels();
154 return fSurface->readPixels(left, top, width, height,
155 kSkia8888_PM_GrPixelConfig,
156 buffer, dst->rowBytes());
reed@google.com4281d652011-04-08 18:54:20 +0000157}
reed@google.com9c49bc32011-07-07 13:42:37 +0000158