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 +}