1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/SkGrPixelRef.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,195 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2010 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 + 1.14 +#include "SkGrPixelRef.h" 1.15 +#include "GrContext.h" 1.16 +#include "GrTexture.h" 1.17 +#include "SkGr.h" 1.18 +#include "SkRect.h" 1.19 + 1.20 +// since we call lockPixels recursively on fBitmap, we need a distinct mutex, 1.21 +// to avoid deadlock with the default one provided by SkPixelRef. 1.22 +SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex); 1.23 + 1.24 +SkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info) 1.25 + : INHERITED(info, &gROLockPixelsPixelRefMutex) {} 1.26 + 1.27 +SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {} 1.28 + 1.29 +bool SkROLockPixelsPixelRef::onNewLockPixels(LockRec* rec) { 1.30 + fBitmap.reset(); 1.31 +// SkDebugf("---------- calling readpixels in support of lockpixels\n"); 1.32 + if (!this->onReadPixels(&fBitmap, NULL)) { 1.33 + SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n"); 1.34 + return false; 1.35 + } 1.36 + fBitmap.lockPixels(); 1.37 + if (NULL == fBitmap.getPixels()) { 1.38 + return false; 1.39 + } 1.40 + 1.41 + rec->fPixels = fBitmap.getPixels(); 1.42 + rec->fColorTable = NULL; 1.43 + rec->fRowBytes = fBitmap.rowBytes(); 1.44 + return true; 1.45 +} 1.46 + 1.47 +void SkROLockPixelsPixelRef::onUnlockPixels() { 1.48 + fBitmap.unlockPixels(); 1.49 +} 1.50 + 1.51 +bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const { 1.52 + return false; 1.53 +} 1.54 + 1.55 +/////////////////////////////////////////////////////////////////////////////// 1.56 + 1.57 +static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config dstConfig, 1.58 + const SkIRect* subset) { 1.59 + if (NULL == texture) { 1.60 + return NULL; 1.61 + } 1.62 + GrContext* context = texture->getContext(); 1.63 + if (NULL == context) { 1.64 + return NULL; 1.65 + } 1.66 + GrTextureDesc desc; 1.67 + 1.68 + SkIPoint pointStorage; 1.69 + SkIPoint* topLeft; 1.70 + if (subset != NULL) { 1.71 + SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset)); 1.72 + // Create a new texture that is the size of subset. 1.73 + desc.fWidth = subset->width(); 1.74 + desc.fHeight = subset->height(); 1.75 + pointStorage.set(subset->x(), subset->y()); 1.76 + topLeft = &pointStorage; 1.77 + } else { 1.78 + desc.fWidth = texture->width(); 1.79 + desc.fHeight = texture->height(); 1.80 + topLeft = NULL; 1.81 + } 1.82 + desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 1.83 + desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig); 1.84 + 1.85 + SkImageInfo info; 1.86 + if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) { 1.87 + return NULL; 1.88 + } 1.89 + info.fWidth = desc.fWidth; 1.90 + info.fHeight = desc.fHeight; 1.91 + info.fAlphaType = kPremul_SkAlphaType; 1.92 + 1.93 + GrTexture* dst = context->createUncachedTexture(desc, NULL, 0); 1.94 + if (NULL == dst) { 1.95 + return NULL; 1.96 + } 1.97 + 1.98 + context->copyTexture(texture, dst->asRenderTarget(), topLeft); 1.99 + 1.100 + // TODO: figure out if this is responsible for Chrome canvas errors 1.101 +#if 0 1.102 + // The render texture we have created (to perform the copy) isn't fully 1.103 + // functional (since it doesn't have a stencil buffer). Release it here 1.104 + // so the caller doesn't try to render to it. 1.105 + // TODO: we can undo this release when dynamic stencil buffer attach/ 1.106 + // detach has been implemented 1.107 + dst->releaseRenderTarget(); 1.108 +#endif 1.109 + 1.110 + SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst)); 1.111 + SkSafeUnref(dst); 1.112 + return pixelRef; 1.113 +} 1.114 + 1.115 +/////////////////////////////////////////////////////////////////////////////// 1.116 + 1.117 +SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface, 1.118 + bool transferCacheLock) : INHERITED(info) { 1.119 + // TODO: figure out if this is responsible for Chrome canvas errors 1.120 +#if 0 1.121 + // The GrTexture has a ref to the GrRenderTarget but not vice versa. 1.122 + // If the GrTexture exists take a ref to that (rather than the render 1.123 + // target) 1.124 + fSurface = surface->asTexture(); 1.125 +#else 1.126 + fSurface = NULL; 1.127 +#endif 1.128 + if (NULL == fSurface) { 1.129 + fSurface = surface; 1.130 + } 1.131 + fUnlock = transferCacheLock; 1.132 + SkSafeRef(surface); 1.133 + 1.134 + if (fSurface) { 1.135 + SkASSERT(info.fWidth <= fSurface->width()); 1.136 + SkASSERT(info.fHeight <= fSurface->height()); 1.137 + } 1.138 +} 1.139 + 1.140 +SkGrPixelRef::~SkGrPixelRef() { 1.141 + if (fUnlock) { 1.142 + GrContext* context = fSurface->getContext(); 1.143 + GrTexture* texture = fSurface->asTexture(); 1.144 + if (NULL != context && NULL != texture) { 1.145 + context->unlockScratchTexture(texture); 1.146 + } 1.147 + } 1.148 + SkSafeUnref(fSurface); 1.149 +} 1.150 + 1.151 +GrTexture* SkGrPixelRef::getTexture() { 1.152 + if (NULL != fSurface) { 1.153 + return fSurface->asTexture(); 1.154 + } 1.155 + return NULL; 1.156 +} 1.157 + 1.158 +SkPixelRef* SkGrPixelRef::deepCopy(SkBitmap::Config dstConfig, const SkIRect* subset) { 1.159 + if (NULL == fSurface) { 1.160 + return NULL; 1.161 + } 1.162 + 1.163 + // Note that when copying a render-target-backed pixel ref, we 1.164 + // return a texture-backed pixel ref instead. This is because 1.165 + // render-target pixel refs are usually created in conjunction with 1.166 + // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live 1.167 + // independently of that texture. Texture-backed pixel refs, on the other 1.168 + // hand, own their GrTextures, and are thus self-contained. 1.169 + return copyToTexturePixelRef(fSurface->asTexture(), dstConfig, subset); 1.170 +} 1.171 + 1.172 +bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { 1.173 + if (NULL == fSurface || !fSurface->isValid()) { 1.174 + return false; 1.175 + } 1.176 + 1.177 + int left, top, width, height; 1.178 + if (NULL != subset) { 1.179 + left = subset->fLeft; 1.180 + width = subset->width(); 1.181 + top = subset->fTop; 1.182 + height = subset->height(); 1.183 + } else { 1.184 + left = 0; 1.185 + width = this->info().fWidth; 1.186 + top = 0; 1.187 + height = this->info().fHeight; 1.188 + } 1.189 + if (!dst->allocPixels(SkImageInfo::MakeN32Premul(width, height))) { 1.190 + SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n"); 1.191 + return false; 1.192 + } 1.193 + SkAutoLockPixels al(*dst); 1.194 + void* buffer = dst->getPixels(); 1.195 + return fSurface->readPixels(left, top, width, height, 1.196 + kSkia8888_GrPixelConfig, 1.197 + buffer, dst->rowBytes()); 1.198 +}