gfx/skia/trunk/src/gpu/SkGrPixelRef.cpp

changeset 0
6474c204b198
     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 +}

mercurial