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(const SkImageInfo& info)
     22     : INHERITED(info, &gROLockPixelsPixelRefMutex) {}
     23 
     24 SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {}
     25 
     26 void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) {
     27     if (ctable) {
     28         *ctable = NULL;
     29     }
     30     fBitmap.reset();
     31 //    SkDebugf("---------- calling readpixels in support of lockpixels\n");
     32     if (!this->onReadPixels(&fBitmap, NULL)) {
     33         SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
     34         return NULL;
     35     }
     36     fBitmap.lockPixels();
     37     return fBitmap.getPixels();
     38 }
     39 
     40 void SkROLockPixelsPixelRef::onUnlockPixels() {
     41     fBitmap.unlockPixels();
     42 }
     43 
     44 bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
     45     return false;
     46 }
     47 
     48 ///////////////////////////////////////////////////////////////////////////////
     49 
     50 static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config dstConfig,
     51                                            const SkIRect* subset) {
     52     if (NULL == texture) {
     53         return NULL;
     54     }
     55     GrContext* context = texture->getContext();
     56     if (NULL == context) {
     57         return NULL;
     58     }
     59     GrTextureDesc desc;
     60 
     61     SkIPoint pointStorage;
     62     SkIPoint* topLeft;
     63     if (subset != NULL) {
     64         SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset));
     65         // Create a new texture that is the size of subset.
     66         desc.fWidth = subset->width();
     67         desc.fHeight = subset->height();
     68         pointStorage.set(subset->x(), subset->y());
     69         topLeft = &pointStorage;
     70     } else {
     71         desc.fWidth  = texture->width();
     72         desc.fHeight = texture->height();
     73         topLeft = NULL;
     74     }
     75     desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
     76     desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig);
     77 
     78     SkImageInfo info;
     79     if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
     80         return NULL;
     81     }
     82     info.fWidth = desc.fWidth;
     83     info.fHeight = desc.fHeight;
     84     info.fAlphaType = kPremul_SkAlphaType;
     85 
     86     GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
     87     if (NULL == dst) {
     88         return NULL;
     89     }
     90 
     91     context->copyTexture(texture, dst->asRenderTarget(), topLeft);
     92 
     93     // TODO: figure out if this is responsible for Chrome canvas errors
     94 #if 0
     95     // The render texture we have created (to perform the copy) isn't fully
     96     // functional (since it doesn't have a stencil buffer). Release it here
     97     // so the caller doesn't try to render to it.
     98     // TODO: we can undo this release when dynamic stencil buffer attach/
     99     // detach has been implemented
    100     dst->releaseRenderTarget();
    101 #endif
    102 
    103     SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
    104     SkSafeUnref(dst);
    105     return pixelRef;
    106 }
    107 
    108 ///////////////////////////////////////////////////////////////////////////////
    109 
    110 SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface,
    111                            bool transferCacheLock) : INHERITED(info) {
    112     // TODO: figure out if this is responsible for Chrome canvas errors
    113 #if 0
    114     // The GrTexture has a ref to the GrRenderTarget but not vice versa.
    115     // If the GrTexture exists take a ref to that (rather than the render
    116     // target)
    117     fSurface = surface->asTexture();
    118 #else
    119     fSurface = NULL;
    120 #endif
    121     if (NULL == fSurface) {
    122         fSurface = surface;
    123     }
    124     fUnlock = transferCacheLock;
    125     SkSafeRef(surface);
    126 }
    127 
    128 SkGrPixelRef::~SkGrPixelRef() {
    129     if (fUnlock) {
    130         GrContext* context = fSurface->getContext();
    131         GrTexture* texture = fSurface->asTexture();
    132         if (NULL != context && NULL != texture) {
    133             context->unlockScratchTexture(texture);
    134         }
    135     }
    136     SkSafeUnref(fSurface);
    137 }
    138 
    139 GrTexture* SkGrPixelRef::getTexture() {
    140     if (NULL != fSurface) {
    141         return fSurface->asTexture();
    142     }
    143     return NULL;
    144 }
    145 
    146 SkPixelRef* SkGrPixelRef::deepCopy(SkBitmap::Config dstConfig, const SkIRect* subset) {
    147     if (NULL == fSurface) {
    148         return NULL;
    149     }
    150 
    151     // Note that when copying a render-target-backed pixel ref, we
    152     // return a texture-backed pixel ref instead.  This is because
    153     // render-target pixel refs are usually created in conjunction with
    154     // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
    155     // independently of that texture.  Texture-backed pixel refs, on the other
    156     // hand, own their GrTextures, and are thus self-contained.
    157     return copyToTexturePixelRef(fSurface->asTexture(), dstConfig, subset);
    158 }
    159 
    160 bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
    161     if (NULL == fSurface || !fSurface->isValid()) {
    162         return false;
    163     }
    164 
    165     int left, top, width, height;
    166     if (NULL != subset) {
    167         left = subset->fLeft;
    168         width = subset->width();
    169         top = subset->fTop;
    170         height = subset->height();
    171     } else {
    172         left = 0;
    173         width = fSurface->width();
    174         top = 0;
    175         height = fSurface->height();
    176     }
    177     dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
    178     if (!dst->allocPixels()) {
    179         SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n");
    180         return false;
    181     }
    182     SkAutoLockPixels al(*dst);
    183     void* buffer = dst->getPixels();
    184     return fSurface->readPixels(left, top, width, height,
    185                                 kSkia8888_GrPixelConfig,
    186                                 buffer, dst->rowBytes());
    187 }
    188