GrTexture.cpp revision 0342a85091fd430c90a142d155dc9642aa729d9e
1 2/* 3 * Copyright 2011 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#include "GrTexture.h" 11 12#include "GrContext.h" 13#include "GrGpu.h" 14#include "GrRenderTarget.h" 15#include "GrResourceCache.h" 16 17SK_DEFINE_INST_COUNT(GrTexture) 18GR_DEFINE_RESOURCE_CACHE_TYPE(GrTexture) 19 20/** 21 * This method allows us to interrupt the normal deletion process and place 22 * textures back in the texture cache when their ref count goes to zero. 23 */ 24void GrTexture::internal_dispose() const { 25 26 if (this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit) && 27 NULL != this->INHERITED::getContext()) { 28 GrTexture* nonConstThis = const_cast<GrTexture *>(this); 29 this->fRefCnt = 1; // restore ref count to initial setting 30 31 nonConstThis->resetFlag((GrTextureFlags) kReturnToCache_FlagBit); 32 nonConstThis->INHERITED::getContext()->addExistingTextureToCache(nonConstThis); 33 34 // Note: "this" texture might be freed inside addExistingTextureToCache 35 // if it is purged. 36 return; 37 } 38 39 this->INHERITED::internal_dispose(); 40} 41 42bool GrTexture::readPixels(int left, int top, int width, int height, 43 GrPixelConfig config, void* buffer, 44 size_t rowBytes, uint32_t pixelOpsFlags) { 45 // go through context so that all necessary flushing occurs 46 GrContext* context = this->getContext(); 47 if (NULL == context) { 48 return false; 49 } 50 return context->readTexturePixels(this, 51 left, top, width, height, 52 config, buffer, rowBytes, 53 pixelOpsFlags); 54} 55 56void GrTexture::writePixels(int left, int top, int width, int height, 57 GrPixelConfig config, const void* buffer, 58 size_t rowBytes, uint32_t pixelOpsFlags) { 59 // go through context so that all necessary flushing occurs 60 GrContext* context = this->getContext(); 61 if (NULL == context) { 62 return; 63 } 64 context->writeTexturePixels(this, 65 left, top, width, height, 66 config, buffer, rowBytes, 67 pixelOpsFlags); 68} 69 70void GrTexture::releaseRenderTarget() { 71 if (NULL != fRenderTarget) { 72 GrAssert(fRenderTarget->asTexture() == this); 73 GrAssert(fDesc.fFlags & kRenderTarget_GrTextureFlagBit); 74 75 fRenderTarget->onTextureReleaseRenderTarget(); 76 fRenderTarget->unref(); 77 fRenderTarget = NULL; 78 79 fDesc.fFlags = fDesc.fFlags & 80 ~(kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit); 81 fDesc.fSampleCnt = 0; 82 } 83} 84 85void GrTexture::onRelease() { 86 GrAssert(!this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit)); 87 this->releaseRenderTarget(); 88} 89 90void GrTexture::onAbandon() { 91 if (NULL != fRenderTarget) { 92 fRenderTarget->abandon(); 93 } 94} 95 96void GrTexture::validateDesc() const { 97 if (NULL != this->asRenderTarget()) { 98 // This texture has a render target 99 GrAssert(0 != (fDesc.fFlags & kRenderTarget_GrTextureFlagBit)); 100 101 if (NULL != this->asRenderTarget()->getStencilBuffer()) { 102 GrAssert(0 != (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 103 } else { 104 GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 105 } 106 107 GrAssert(fDesc.fSampleCnt == this->asRenderTarget()->numSamples()); 108 } else { 109 GrAssert(0 == (fDesc.fFlags & kRenderTarget_GrTextureFlagBit)); 110 GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 111 GrAssert(0 == fDesc.fSampleCnt); 112 } 113} 114 115// These flags need to fit in <= 8 bits so they can be folded into the texture 116// key 117enum TextureBits { 118 /* 119 * The kNPOT bit is set when the texture is NPOT and is being repeated 120 * but the hardware doesn't support that feature. 121 */ 122 kNPOT_TextureBit = 0x1, 123 /* 124 * The kFilter bit can only be set when the kNPOT flag is set and indicates 125 * whether the resizing of the texture should use filtering. This is 126 * to handle cases where the original texture is indexed to disable 127 * filtering. 128 */ 129 kFilter_TextureBit = 0x2, 130 /* 131 * The kScratch bit is set if the texture is being used as a scratch 132 * texture. 133 */ 134 kScratch_TextureBit = 0x4, 135}; 136 137namespace { 138void gen_texture_key_values(const GrGpu* gpu, 139 const GrTextureParams* params, 140 const GrTextureDesc& desc, 141 const GrCacheData& cacheData, 142 bool scratch, 143 GrCacheID* cacheID) { 144 145 uint64_t clientKey = cacheData.fClientCacheID; 146 147 if (scratch) { 148 // Instead of a client-provided key of the texture contents 149 // we create a key from the descriptor. 150 GrAssert(GrCacheData::kScratch_CacheID == clientKey); 151 clientKey = (desc.fFlags << 8) | ((uint64_t) desc.fConfig << 32); 152 } 153 154 cacheID->fPublicID = clientKey; 155 cacheID->fDomain = cacheData.fResourceDomain; 156 157 // we assume we only need 16 bits of width and height 158 // assert that texture creation will fail anyway if this assumption 159 // would cause key collisions. 160 GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16); 161 cacheID->fResourceSpecific32 = desc.fWidth | (desc.fHeight << 16); 162 163 GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt < 256); 164 cacheID->fResourceSpecific16 = desc.fSampleCnt << 8; 165 166 if (!gpu->getCaps().fNPOTTextureTileSupport) { 167 bool isPow2 = GrIsPow2(desc.fWidth) && GrIsPow2(desc.fHeight); 168 169 bool tiled = NULL != params && params->isTiled(); 170 171 if (tiled && !isPow2) { 172 cacheID->fResourceSpecific16 |= kNPOT_TextureBit; 173 if (params->isBilerp()) { 174 cacheID->fResourceSpecific16 |= kFilter_TextureBit; 175 } 176 } 177 } 178 179 if (scratch) { 180 cacheID->fResourceSpecific16 |= kScratch_TextureBit; 181 } 182} 183} 184 185GrResourceKey GrTexture::ComputeKey(const GrGpu* gpu, 186 const GrTextureParams* params, 187 const GrTextureDesc& desc, 188 const GrCacheData& cacheData, 189 bool scratch) { 190 GrCacheID id(GrTexture::GetResourceType()); 191 gen_texture_key_values(gpu, params, desc, cacheData, scratch, &id); 192 193 uint32_t v[4]; 194 id.toRaw(v); 195 return GrResourceKey(v); 196} 197 198bool GrTexture::NeedsResizing(const GrResourceKey& key) { 199 return 0 != (key.getValue32(3) & kNPOT_TextureBit); 200} 201 202bool GrTexture::IsScratchTexture(const GrResourceKey& key) { 203 return 0 != (key.getValue32(3) & kScratch_TextureBit); 204} 205 206bool GrTexture::NeedsFiltering(const GrResourceKey& key) { 207 return 0 != (key.getValue32(3) & kFilter_TextureBit); 208} 209