Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * 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.
      7  */
      8 
      9 
     10 
     11 #include "SkGrPixelRef.h"
     12 #include "GrContext.h"
     13 #include "GrTexture.h"
     14 #include "SkGr.h"
     15 #include "SkRect.h"
     16 
     17 // since we call lockPixels recursively on fBitmap, we need a distinct mutex,
     18 // to avoid deadlock with the default one provided by SkPixelRef.
     19 SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex);
     20 
     21 SkROLockPixelsPixelRef::SkROLockPixelsPixelRef() : INHERITED(&gROLockPixelsPixelRefMutex) {
     22 }
     23 
     24 SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {
     25 }
     26 
     27 void* 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 
     41 void SkROLockPixelsPixelRef::onUnlockPixels() {
     42     fBitmap.unlockPixels();
     43 }
     44 
     45 bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
     46     return false;
     47 }
     48 
     49 ///////////////////////////////////////////////////////////////////////////////
     50 
     51 static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config dstConfig,
     52                                            const SkIRect* subset) {
     53     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     SkIPoint pointStorage;
     63     SkIPoint* topLeft;
     64     if (subset != NULL) {
     65         SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset));
     66         // Create a new texture that is the size of subset.
     67         desc.fWidth = subset->width();
     68         desc.fHeight = subset->height();
     69         pointStorage.set(subset->x(), subset->y());
     70         topLeft = &pointStorage;
     71     } else {
     72         desc.fWidth  = texture->width();
     73         desc.fHeight = texture->height();
     74         topLeft = NULL;
     75     }
     76     desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
     77     desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig);
     78 
     79     GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
     80     if (NULL == dst) {
     81         return NULL;
     82     }
     83 
     84     context->copyTexture(texture, dst->asRenderTarget(), topLeft);
     85 
     86     // TODO: figure out if this is responsible for Chrome canvas errors
     87 #if 0
     88     // The render texture we have created (to perform the copy) isn't fully
     89     // functional (since it doesn't have a stencil buffer). Release it here
     90     // so the caller doesn't try to render to it.
     91     // TODO: we can undo this release when dynamic stencil buffer attach/
     92     // detach has been implemented
     93     dst->releaseRenderTarget();
     94 #endif
     95 
     96     SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (dst));
     97     GrSafeUnref(dst);
     98     return pixelRef;
     99 }
    100 
    101 ///////////////////////////////////////////////////////////////////////////////
    102 
    103 SkGrPixelRef::SkGrPixelRef(GrSurface* surface, bool transferCacheLock) {
    104     // TODO: figure out if this is responsible for Chrome canvas errors
    105 #if 0
    106     // The GrTexture has a ref to the GrRenderTarget but not vice versa.
    107     // If the GrTexture exists take a ref to that (rather than the render
    108     // target)
    109     fSurface = surface->asTexture();
    110 #else
    111     fSurface = NULL;
    112 #endif
    113     if (NULL == fSurface) {
    114         fSurface = surface;
    115     }
    116     fUnlock = transferCacheLock;
    117     GrSafeRef(surface);
    118 }
    119 
    120 SkGrPixelRef::~SkGrPixelRef() {
    121     if (fUnlock) {
    122         GrContext* context = fSurface->getContext();
    123         GrTexture* texture = fSurface->asTexture();
    124         if (NULL != context && NULL != texture) {
    125             context->unlockScratchTexture(texture);
    126         }
    127     }
    128     GrSafeUnref(fSurface);
    129 }
    130 
    131 SkGpuTexture* SkGrPixelRef::getTexture() {
    132     if (NULL != fSurface) {
    133         return (SkGpuTexture*) fSurface->asTexture();
    134     }
    135     return NULL;
    136 }
    137 
    138 SkPixelRef* SkGrPixelRef::deepCopy(SkBitmap::Config dstConfig, const SkIRect* subset) {
    139     if (NULL == fSurface) {
    140         return NULL;
    141     }
    142 
    143     // Note that when copying a render-target-backed pixel ref, we
    144     // return a texture-backed pixel ref instead.  This is because
    145     // render-target pixel refs are usually created in conjunction with
    146     // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
    147     // independently of that texture.  Texture-backed pixel refs, on the other
    148     // hand, own their GrTextures, and are thus self-contained.
    149     return copyToTexturePixelRef(fSurface->asTexture(), dstConfig, subset);
    150 }
    151 
    152 bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
    153     if (NULL == fSurface || !fSurface->isValid()) {
    154         return false;
    155     }
    156 
    157     int left, top, width, height;
    158     if (NULL != subset) {
    159         left = subset->fLeft;
    160         width = subset->width();
    161         top = subset->fTop;
    162         height = subset->height();
    163     } else {
    164         left = 0;
    165         width = fSurface->width();
    166         top = 0;
    167         height = fSurface->height();
    168     }
    169     dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
    170     if (!dst->allocPixels()) {
    171         SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n");
    172         return false;
    173     }
    174     SkAutoLockPixels al(*dst);
    175     void* buffer = dst->getPixels();
    176     return fSurface->readPixels(left, top, width, height,
    177                                 kSkia8888_PM_GrPixelConfig,
    178                                 buffer, dst->rowBytes());
    179 }
    180