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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/gpu/GrTexture.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,195 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2011 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 +#include "GrTexture.h"
    1.14 +
    1.15 +#include "GrContext.h"
    1.16 +#include "GrDrawTargetCaps.h"
    1.17 +#include "GrGpu.h"
    1.18 +#include "GrRenderTarget.h"
    1.19 +#include "GrResourceCache.h"
    1.20 +
    1.21 +GrTexture::~GrTexture() {
    1.22 +    if (NULL != fRenderTarget.get()) {
    1.23 +        fRenderTarget.get()->owningTextureDestroyed();
    1.24 +    }
    1.25 +}
    1.26 +
    1.27 +/**
    1.28 + * This method allows us to interrupt the normal deletion process and place
    1.29 + * textures back in the texture cache when their ref count goes to zero.
    1.30 + */
    1.31 +void GrTexture::internal_dispose() const {
    1.32 +
    1.33 +    if (this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit) &&
    1.34 +        NULL != this->INHERITED::getContext()) {
    1.35 +        GrTexture* nonConstThis = const_cast<GrTexture *>(this);
    1.36 +        this->fRefCnt = 1;      // restore ref count to initial setting
    1.37 +
    1.38 +        nonConstThis->resetFlag((GrTextureFlags) kReturnToCache_FlagBit);
    1.39 +        nonConstThis->INHERITED::getContext()->addExistingTextureToCache(nonConstThis);
    1.40 +
    1.41 +        // Note: "this" texture might be freed inside addExistingTextureToCache
    1.42 +        // if it is purged.
    1.43 +        return;
    1.44 +    }
    1.45 +
    1.46 +    SkASSERT(0 == this->getDeferredRefCount());
    1.47 +    this->INHERITED::internal_dispose();
    1.48 +}
    1.49 +
    1.50 +bool GrTexture::readPixels(int left, int top, int width, int height,
    1.51 +                           GrPixelConfig config, void* buffer,
    1.52 +                           size_t rowBytes, uint32_t pixelOpsFlags) {
    1.53 +    // go through context so that all necessary flushing occurs
    1.54 +    GrContext* context = this->getContext();
    1.55 +    if (NULL == context) {
    1.56 +        return false;
    1.57 +    }
    1.58 +    return context->readTexturePixels(this,
    1.59 +                                      left, top, width, height,
    1.60 +                                      config, buffer, rowBytes,
    1.61 +                                      pixelOpsFlags);
    1.62 +}
    1.63 +
    1.64 +void GrTexture::writePixels(int left, int top, int width, int height,
    1.65 +                            GrPixelConfig config, const void* buffer,
    1.66 +                            size_t rowBytes, uint32_t pixelOpsFlags) {
    1.67 +    // go through context so that all necessary flushing occurs
    1.68 +    GrContext* context = this->getContext();
    1.69 +    if (NULL == context) {
    1.70 +        return;
    1.71 +    }
    1.72 +    context->writeTexturePixels(this,
    1.73 +                                left, top, width, height,
    1.74 +                                config, buffer, rowBytes,
    1.75 +                                pixelOpsFlags);
    1.76 +}
    1.77 +
    1.78 +void GrTexture::onRelease() {
    1.79 +    SkASSERT(!this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit));
    1.80 +    INHERITED::onRelease();
    1.81 +}
    1.82 +
    1.83 +void GrTexture::onAbandon() {
    1.84 +    if (NULL != fRenderTarget.get()) {
    1.85 +        fRenderTarget->abandon();
    1.86 +    }
    1.87 +    INHERITED::onAbandon();
    1.88 +}
    1.89 +
    1.90 +void GrTexture::validateDesc() const {
    1.91 +    if (NULL != this->asRenderTarget()) {
    1.92 +        // This texture has a render target
    1.93 +        SkASSERT(0 != (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
    1.94 +
    1.95 +        if (NULL != this->asRenderTarget()->getStencilBuffer()) {
    1.96 +            SkASSERT(0 != (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
    1.97 +        } else {
    1.98 +            SkASSERT(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
    1.99 +        }
   1.100 +
   1.101 +        SkASSERT(fDesc.fSampleCnt == this->asRenderTarget()->numSamples());
   1.102 +    } else {
   1.103 +        SkASSERT(0 == (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
   1.104 +        SkASSERT(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
   1.105 +        SkASSERT(0 == fDesc.fSampleCnt);
   1.106 +    }
   1.107 +}
   1.108 +
   1.109 +// These flags need to fit in a GrResourceKey::ResourceFlags so they can be folded into the texture
   1.110 +// key
   1.111 +enum TextureFlags {
   1.112 +    /**
   1.113 +     * The kStretchToPOT bit is set when the texture is NPOT and is being repeated but the
   1.114 +     * hardware doesn't support that feature.
   1.115 +     */
   1.116 +    kStretchToPOT_TextureFlag = 0x1,
   1.117 +    /**
   1.118 +     * The kBilerp bit can only be set when the kStretchToPOT flag is set and indicates whether the
   1.119 +     * stretched texture should be bilerped.
   1.120 +     */
   1.121 +     kBilerp_TextureFlag       = 0x2,
   1.122 +};
   1.123 +
   1.124 +namespace {
   1.125 +GrResourceKey::ResourceFlags get_texture_flags(const GrGpu* gpu,
   1.126 +                                               const GrTextureParams* params,
   1.127 +                                               const GrTextureDesc& desc) {
   1.128 +    GrResourceKey::ResourceFlags flags = 0;
   1.129 +    bool tiled = NULL != params && params->isTiled();
   1.130 +    if (tiled && !gpu->caps()->npotTextureTileSupport()) {
   1.131 +        if (!GrIsPow2(desc.fWidth) || !GrIsPow2(desc.fHeight)) {
   1.132 +            flags |= kStretchToPOT_TextureFlag;
   1.133 +            switch(params->filterMode()) {
   1.134 +                case GrTextureParams::kNone_FilterMode:
   1.135 +                    break;
   1.136 +                case GrTextureParams::kBilerp_FilterMode:
   1.137 +                case GrTextureParams::kMipMap_FilterMode:
   1.138 +                    flags |= kBilerp_TextureFlag;
   1.139 +                    break;
   1.140 +            }
   1.141 +        }
   1.142 +    }
   1.143 +    return flags;
   1.144 +}
   1.145 +
   1.146 +GrResourceKey::ResourceType texture_resource_type() {
   1.147 +    static const GrResourceKey::ResourceType gType = GrResourceKey::GenerateResourceType();
   1.148 +    return gType;
   1.149 +}
   1.150 +
   1.151 +// FIXME:  This should be refactored with the code in gl/GrGpuGL.cpp.
   1.152 +GrSurfaceOrigin resolve_origin(const GrTextureDesc& desc) {
   1.153 +    // By default, GrRenderTargets are GL's normal orientation so that they
   1.154 +    // can be drawn to by the outside world without the client having
   1.155 +    // to render upside down.
   1.156 +    bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
   1.157 +    if (kDefault_GrSurfaceOrigin == desc.fOrigin) {
   1.158 +        return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
   1.159 +    } else {
   1.160 +        return desc.fOrigin;
   1.161 +    }
   1.162 +}
   1.163 +}
   1.164 +
   1.165 +GrResourceKey GrTexture::ComputeKey(const GrGpu* gpu,
   1.166 +                                    const GrTextureParams* params,
   1.167 +                                    const GrTextureDesc& desc,
   1.168 +                                    const GrCacheID& cacheID) {
   1.169 +    GrResourceKey::ResourceFlags flags = get_texture_flags(gpu, params, desc);
   1.170 +    return GrResourceKey(cacheID, texture_resource_type(), flags);
   1.171 +}
   1.172 +
   1.173 +GrResourceKey GrTexture::ComputeScratchKey(const GrTextureDesc& desc) {
   1.174 +    GrCacheID::Key idKey;
   1.175 +    // Instead of a client-provided key of the texture contents we create a key from the
   1.176 +    // descriptor.
   1.177 +    GR_STATIC_ASSERT(sizeof(idKey) >= 16);
   1.178 +    SkASSERT(desc.fHeight < (1 << 16));
   1.179 +    SkASSERT(desc.fWidth < (1 << 16));
   1.180 +    idKey.fData32[0] = (desc.fWidth) | (desc.fHeight << 16);
   1.181 +    idKey.fData32[1] = desc.fConfig | desc.fSampleCnt << 16;
   1.182 +    idKey.fData32[2] = desc.fFlags;
   1.183 +    idKey.fData32[3] = resolve_origin(desc);    // Only needs 2 bits actually
   1.184 +    static const int kPadSize = sizeof(idKey) - 16;
   1.185 +    GR_STATIC_ASSERT(kPadSize >= 0);
   1.186 +    memset(idKey.fData8 + 16, 0, kPadSize);
   1.187 +
   1.188 +    GrCacheID cacheID(GrResourceKey::ScratchDomain(), idKey);
   1.189 +    return GrResourceKey(cacheID, texture_resource_type(), 0);
   1.190 +}
   1.191 +
   1.192 +bool GrTexture::NeedsResizing(const GrResourceKey& key) {
   1.193 +    return SkToBool(key.getResourceFlags() & kStretchToPOT_TextureFlag);
   1.194 +}
   1.195 +
   1.196 +bool GrTexture::NeedsBilerp(const GrResourceKey& key) {
   1.197 +    return SkToBool(key.getResourceFlags() & kBilerp_TextureFlag);
   1.198 +}

mercurial