1ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 10ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 115088eb49fedac4180e2d5822e2636b3c6edeef9arobertphillips@google.com#include "SkGrPixelRef.h" 12ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org#include "GrContext.h" 13ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTexture.h" 14ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org#include "SkGr.h" 15669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com#include "SkRect.h" 169c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com 179c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com// since we call lockPixels recursively on fBitmap, we need a distinct mutex, 189c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com// to avoid deadlock with the default one provided by SkPixelRef. 191771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.comSK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex); 209c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com 21bf790232f6d94b54239dbc210d8beee7411ca458reed@google.comSkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info) 22bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com : INHERITED(info, &gROLockPixelsPixelRefMutex) {} 239c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com 24bf790232f6d94b54239dbc210d8beee7411ca458reed@google.comSkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {} 259c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com 26d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.combool SkROLockPixelsPixelRef::onNewLockPixels(LockRec* rec) { 279c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com fBitmap.reset(); 289c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com// SkDebugf("---------- calling readpixels in support of lockpixels\n"); 299c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com if (!this->onReadPixels(&fBitmap, NULL)) { 309c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n"); 31d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com return false; 329c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com } 339c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com fBitmap.lockPixels(); 34d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com if (NULL == fBitmap.getPixels()) { 35d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com return false; 36d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com } 37d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com 38d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com rec->fPixels = fBitmap.getPixels(); 39d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com rec->fColorTable = NULL; 40d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com rec->fRowBytes = fBitmap.rowBytes(); 41d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com return true; 429c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com} 439c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com 449c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.comvoid SkROLockPixelsPixelRef::onUnlockPixels() { 459c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com fBitmap.unlockPixels(); 469c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com} 479c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com 489c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.combool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const { 499c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com return false; 509c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com} 519c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com 529c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com/////////////////////////////////////////////////////////////////////////////// 53669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com 54e4538f5b46d70798e34eb078f5d5e76a59d02318reedstatic SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkColorType dstCT, 55eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org const SkIRect* subset) { 56e4538f5b46d70798e34eb078f5d5e76a59d02318reed if (NULL == texture || kUnknown_SkColorType == dstCT) { 57ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org return NULL; 58ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org } 59ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org GrContext* context = texture->getContext(); 60ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org if (NULL == context) { 61ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org return NULL; 62ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org } 63ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org GrTextureDesc desc; 64ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org 65a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com SkIPoint pointStorage; 66a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com SkIPoint* topLeft; 67a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com if (subset != NULL) { 68a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset)); 69a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com // Create a new texture that is the size of subset. 70a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com desc.fWidth = subset->width(); 71a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com desc.fHeight = subset->height(); 72a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com pointStorage.set(subset->x(), subset->y()); 73a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com topLeft = &pointStorage; 74a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com } else { 75a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com desc.fWidth = texture->width(); 76a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com desc.fHeight = texture->height(); 77a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com topLeft = NULL; 78a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com } 79ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 80e4538f5b46d70798e34eb078f5d5e76a59d02318reed desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType); 8196f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com 82ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org GrTexture* dst = context->createUncachedTexture(desc, NULL, 0); 83ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org if (NULL == dst) { 84ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org return NULL; 85ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org } 86ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org 87a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com context->copyTexture(texture, dst->asRenderTarget(), topLeft); 88d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com 8941efe04af99b11440b6de39919f92bc9d1514f5crobertphillips@google.com // TODO: figure out if this is responsible for Chrome canvas errors 9041efe04af99b11440b6de39919f92bc9d1514f5crobertphillips@google.com#if 0 91d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // The render texture we have created (to perform the copy) isn't fully 92d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // functional (since it doesn't have a stencil buffer). Release it here 93d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // so the caller doesn't try to render to it. 94d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // TODO: we can undo this release when dynamic stencil buffer attach/ 95d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // detach has been implemented 96d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com dst->releaseRenderTarget(); 9741efe04af99b11440b6de39919f92bc9d1514f5crobertphillips@google.com#endif 98d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com 99e4538f5b46d70798e34eb078f5d5e76a59d02318reed SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType); 100bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst)); 101a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org SkSafeUnref(dst); 102ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org return pixelRef; 103ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org} 104ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org 105ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org/////////////////////////////////////////////////////////////////////////////// 106ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org 107bf790232f6d94b54239dbc210d8beee7411ca458reed@google.comSkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface, 108bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com bool transferCacheLock) : INHERITED(info) { 10961867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com // TODO: figure out if this is responsible for Chrome canvas errors 11061867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com#if 0 11161867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com // The GrTexture has a ref to the GrRenderTarget but not vice versa. 11261867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com // If the GrTexture exists take a ref to that (rather than the render 11361867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com // target) 11461867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com fSurface = surface->asTexture(); 11561867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com#else 11661867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com fSurface = NULL; 11761867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com#endif 11861867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com if (NULL == fSurface) { 11961867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com fSurface = surface; 12061867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com } 12161867875ef8083ca39a76acc8ffeedd2623d4b35reed@google.com fUnlock = transferCacheLock; 122a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org SkSafeRef(surface); 1238e0993d8d8408e538d99229eabf710ad90d97259commit-bot@chromium.org 1248e0993d8d8408e538d99229eabf710ad90d97259commit-bot@chromium.org if (fSurface) { 1258e0993d8d8408e538d99229eabf710ad90d97259commit-bot@chromium.org SkASSERT(info.fWidth <= fSurface->width()); 1268e0993d8d8408e538d99229eabf710ad90d97259commit-bot@chromium.org SkASSERT(info.fHeight <= fSurface->height()); 1278e0993d8d8408e538d99229eabf710ad90d97259commit-bot@chromium.org } 128669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com} 129669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com 130d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.comSkGrPixelRef::~SkGrPixelRef() { 1318090e651fc1055e0a36f5f17c851faafda949b2cbsalomon@google.com if (fUnlock) { 1328090e651fc1055e0a36f5f17c851faafda949b2cbsalomon@google.com GrContext* context = fSurface->getContext(); 133d07cb0c0370de521169500c26b8d534a001cf580robertphillips@google.com GrTexture* texture = fSurface->asTexture(); 1348090e651fc1055e0a36f5f17c851faafda949b2cbsalomon@google.com if (NULL != context && NULL != texture) { 1359fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.com context->unlockScratchTexture(texture); 1368090e651fc1055e0a36f5f17c851faafda949b2cbsalomon@google.com } 1378090e651fc1055e0a36f5f17c851faafda949b2cbsalomon@google.com } 138a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org SkSafeUnref(fSurface); 139669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com} 140669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com 141b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.orgGrTexture* SkGrPixelRef::getTexture() { 142d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com if (NULL != fSurface) { 143b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org return fSurface->asTexture(); 144669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com } 145669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return NULL; 14650dfa0130b0705414df7ba7da9915139f6320b09reed@google.com} 147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 148e4538f5b46d70798e34eb078f5d5e76a59d02318reedSkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, const SkIRect* subset) { 149d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com if (NULL == fSurface) { 150ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org return NULL; 151ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org } 152e4538f5b46d70798e34eb078f5d5e76a59d02318reed 153d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // Note that when copying a render-target-backed pixel ref, we 154d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // return a texture-backed pixel ref instead. This is because 155d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // render-target pixel refs are usually created in conjunction with 156d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live 157d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // independently of that texture. Texture-backed pixel refs, on the other 158d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com // hand, own their GrTextures, and are thus self-contained. 159e4538f5b46d70798e34eb078f5d5e76a59d02318reed return copyToTexturePixelRef(fSurface->asTexture(), dstCT, subset); 160ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org} 161ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org 162d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.combool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { 163089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org if (NULL == fSurface || fSurface->wasDestroyed()) { 164669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return false; 165669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com } 166d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com 167d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com int left, top, width, height; 168d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com if (NULL != subset) { 169d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com left = subset->fLeft; 170d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com width = subset->width(); 171d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com top = subset->fTop; 172d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com height = subset->height(); 173d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com } else { 174d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com left = 0; 1758e0993d8d8408e538d99229eabf710ad90d97259commit-bot@chromium.org width = this->info().fWidth; 176d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com top = 0; 1778e0993d8d8408e538d99229eabf710ad90d97259commit-bot@chromium.org height = this->info().fHeight; 178d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com } 1799ebcac54635cde63110d73ad7c43d70772e7872freed@google.com if (!dst->allocPixels(SkImageInfo::MakeN32Premul(width, height))) { 180009bcca7457b3711d48604df7547ffdb937fad50bsalomon@google.com SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n"); 181009bcca7457b3711d48604df7547ffdb937fad50bsalomon@google.com return false; 182009bcca7457b3711d48604df7547ffdb937fad50bsalomon@google.com } 183d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com SkAutoLockPixels al(*dst); 184d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com void* buffer = dst->getPixels(); 185d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com return fSurface->readPixels(left, top, width, height, 186fec0bc3fc13481f5bcb341ab2d2d695911f39bd4bsalomon@google.com kSkia8888_GrPixelConfig, 187d881bc194d7c24294029b5c08e6e549a9fd9b6f3robertphillips@google.com buffer, dst->rowBytes()); 1884281d650934475fd50fdd61fab94421d7454e44dreed@google.com} 189