blob: 4359da2d3ef9b0557ef72ae2bbfe5886fb826f68 [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
74 // The render texture we have created (to perform the copy) isn't fully
75 // functional (since it doesn't have a stencil buffer). Release it here
76 // so the caller doesn't try to render to it.
77 // TODO: we can undo this release when dynamic stencil buffer attach/
78 // detach has been implemented
79 dst->releaseRenderTarget();
80
81 SkGrPixelRef* pixelRef = new SkGrPixelRef(dst);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +000082 GrSafeUnref(dst);
83 return pixelRef;
84}
85
86///////////////////////////////////////////////////////////////////////////////
87
robertphillips@google.comd881bc12012-06-28 20:02:39 +000088SkGrPixelRef::SkGrPixelRef(GrSurface* surface) {
89 // The GrTexture has a ref to the GrRenderTarget but not vice versa.
90 // If the GrTexture exists take a ref to that (rather than the render
91 // target)
92 fSurface = surface->asTexture();
93 if (NULL == fSurface) {
94 fSurface = surface;
bsalomon@google.com669fdc42011-04-05 17:08:27 +000095 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +000096
97 GrSafeRef(surface);
reed@google.com50dfa012011-04-01 19:05:36 +000098}
reed@google.comac10a2d2010-12-22 21:39:39 +000099
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000100SkGrPixelRef::~SkGrPixelRef() {
101 GrSafeUnref(fSurface);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000102}
103
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000104SkGpuTexture* SkGrPixelRef::getTexture() {
105 if (NULL != fSurface) {
106 return (SkGpuTexture*) fSurface->asTexture();
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000107 }
108 return NULL;
109}
110
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000111SkPixelRef* SkGrPixelRef::deepCopy(SkBitmap::Config dstConfig) {
112 if (NULL == fSurface) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000113 return NULL;
114 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000115
116 // Note that when copying a render-target-backed pixel ref, we
117 // return a texture-backed pixel ref instead. This is because
118 // render-target pixel refs are usually created in conjunction with
119 // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
120 // independently of that texture. Texture-backed pixel refs, on the other
121 // hand, own their GrTextures, and are thus self-contained.
122 return copyToTexturePixelRef(fSurface->asTexture(), dstConfig);
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000123}
124
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000125bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
126 if (NULL == fSurface || !fSurface->isValid()) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000127 return false;
128 }
robertphillips@google.comd881bc12012-06-28 20:02:39 +0000129
130 int left, top, width, height;
131 if (NULL != subset) {
132 left = subset->fLeft;
133 width = subset->width();
134 top = subset->fTop;
135 height = subset->height();
136 } else {
137 left = 0;
138 width = fSurface->width();
139 top = 0;
140 height = fSurface->height();
141 }
142 dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
143 dst->allocPixels();
144 SkAutoLockPixels al(*dst);
145 void* buffer = dst->getPixels();
146 return fSurface->readPixels(left, top, width, height,
147 kSkia8888_PM_GrPixelConfig,
148 buffer, dst->rowBytes());
reed@google.com4281d652011-04-08 18:54:20 +0000149}
reed@google.com9c49bc32011-07-07 13:42:37 +0000150