GrTexture.cpp revision a1e5795279bd085496fa04c59e588f440bf30457
1669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com */ 8669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 10669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com#include "GrTexture.h" 11aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com 12669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com#include "GrContext.h" 1305ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com#include "GrGpu.h" 14aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com#include "GrRenderTarget.h" 15a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com#include "GrResourceCache.h" 168295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com 17669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.combool GrTexture::readPixels(int left, int top, int width, int height, 186f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com GrPixelConfig config, void* buffer, 196f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com size_t rowBytes) { 20669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com // go through context so that all necessary flushing occurs 216f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com GrContext* context = this->getContext(); 226f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com if (NULL == context) { 236f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com return false; 246f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com } 25669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return context->readTexturePixels(this, 266f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com left, top, 276f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com width, height, 286f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com config, buffer, rowBytes); 296f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com} 306f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com 316f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrTexture::writePixels(int left, int top, int width, int height, 326f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com GrPixelConfig config, const void* buffer, 336f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com size_t rowBytes) { 346f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com // go through context so that all necessary flushing occurs 356f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com GrContext* context = this->getContext(); 366f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com if (NULL == context) { 376f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com return; 386f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com } 396f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com context->writeTexturePixels(this, 406f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com left, top, 416f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com width, height, 426f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com config, buffer, rowBytes); 43669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com} 44cee661af926cc977addc6e039b7022975a448acebsalomon@google.com 45aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.comvoid GrTexture::releaseRenderTarget() { 46aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com if (NULL != fRenderTarget) { 47aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com GrAssert(fRenderTarget->asTexture() == this); 4832716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com GrAssert(fDesc.fFlags & kRenderTarget_GrTextureFlagBit); 4932716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com 50aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com fRenderTarget->onTextureReleaseRenderTarget(); 51aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com fRenderTarget->unref(); 52aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com fRenderTarget = NULL; 5332716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com 5432716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com fDesc.fFlags = fDesc.fFlags & 5532716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com ~(kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit); 5632716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com fDesc.fSampleCnt = 0; 57aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com } 58aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com} 59aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com 60aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.comvoid GrTexture::onAbandon() { 61aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com if (NULL != fRenderTarget) { 62aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com fRenderTarget->abandon(); 63aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com } 64aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com} 65aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com 6632716283420df90644c8b8114308f7967aa91d9frobertphillips@google.comvoid GrTexture::validateDesc() const { 6732716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com if (NULL != this->asRenderTarget()) { 6832716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com // This texture has a render target 6932716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com GrAssert(0 != (fDesc.fFlags & kRenderTarget_GrTextureFlagBit)); 7032716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com 7132716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com if (NULL != this->asRenderTarget()->getStencilBuffer()) { 7232716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com GrAssert(0 != (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 7332716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com } else { 7432716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 7532716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com } 7632716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com 7732716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com GrAssert(fDesc.fSampleCnt == this->asRenderTarget()->numSamples()); 7832716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com } else { 7932716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com GrAssert(0 == (fDesc.fFlags & kRenderTarget_GrTextureFlagBit)); 8032716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 8132716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com GrAssert(0 == fDesc.fSampleCnt); 8232716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com } 8332716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com} 84a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 85a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.comenum TextureBits { 86a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com kFirst_TextureBit = (GrResourceKey::kLastPublic_TypeBit << 1), 87a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 88a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com /* 89a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com * The kNPOT bit is set when the texture is NPOT and is being repeated 90a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com * but the hardware doesn't support that feature. 91a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com */ 92a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com kNPOT_TextureBit = kFirst_TextureBit, 93a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com /* 94a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com * The kFilter bit can only be set when the kNPOT flag is set and indicates 95a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com * whether the resizing of the texture should use filtering. This is 96a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com * to handle cases where the original texture is indexed to disable 97a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com * filtering. 98a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com */ 99a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com kFilter_TextureBit = kNPOT_TextureBit << 1, 100a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com /* 101a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com * The kScratch bit is set if the texture is being used as a scratch 102a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com * texture. 103a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com */ 104a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com kScratch_TextureBit = kFilter_TextureBit << 1, 105a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com}; 106a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 107a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.comnamespace { 108a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.comvoid gen_texture_key_values(const GrGpu* gpu, 109a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com const GrSamplerState* sampler, 110a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com GrTexture::TextureKey clientKey, 111a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com const GrTextureDesc& desc, 112a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com bool scratch, 113a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com uint32_t v[4]) { 114a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com GR_STATIC_ASSERT(sizeof(GrTexture::TextureKey) == sizeof(uint64_t)); 115a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 116a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com if (scratch) { 117a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com // Instead of a client-provided key of the texture contents 118a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com // we create a key of from the descriptor. 119a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com GrAssert(0 == clientKey); 120a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com clientKey = (desc.fFlags << 8) | ((uint64_t) desc.fConfig << 32); 121a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com } 122a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 123a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com // we assume we only need 16 bits of width and height 124a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com // assert that texture creation will fail anyway if this assumption 125a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com // would cause key collisions. 126a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16); 127a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com v[0] = clientKey & 0xffffffffUL; 128a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com v[1] = (clientKey >> 32) & 0xffffffffUL; 129a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com v[2] = desc.fWidth | (desc.fHeight << 16); 130a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 131a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com v[3] = (desc.fSampleCnt << 24); 132a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt < 256); 133a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 134a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com if (!gpu->getCaps().fNPOTTextureTileSupport) { 135a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com bool isPow2 = GrIsPow2(desc.fWidth) && GrIsPow2(desc.fHeight); 136a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 137a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com bool tiled = NULL != sampler && 138a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) || 139a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode)); 140a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 141a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com if (tiled && !isPow2) { 142a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com v[3] |= kNPOT_TextureBit; 143a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com if (GrSamplerState::kNearest_Filter != sampler->getFilter()) { 144a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com v[3] |= kFilter_TextureBit; 145a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com } 146a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com } 147a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com } 148a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 149a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com if (scratch) { 150a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com v[3] |= kScratch_TextureBit; 151a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com } 152a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 153a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com v[3] |= GrResourceKey::kTexture_TypeBit; 154a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com} 155a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com} 156a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 157a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.comGrResourceKey GrTexture::ComputeKey(const GrGpu* gpu, 158a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com const GrSamplerState* sampler, 159a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com TextureKey clientKey, 160a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com const GrTextureDesc& desc, 161a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com bool scratch) { 162a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com uint32_t v[4]; 163a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com gen_texture_key_values(gpu, sampler, clientKey, desc, scratch, v); 164a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com return GrResourceKey(v); 165a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com} 166a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 167a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.combool GrTexture::NeedsResizing(const GrResourceKey& key) { 168a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com return 0 != (key.getValue32(3) & kNPOT_TextureBit); 169a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com} 170a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 171a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.combool GrTexture::IsScratchTexture(const GrResourceKey& key) { 172a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com return 0 != (key.getValue32(3) & kScratch_TextureBit); 173a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com} 174a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 175a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.combool GrTexture::NeedsFiltering(const GrResourceKey& key) { 176a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com return 0 != (key.getValue32(3) & kFilter_TextureBit); 177a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com} 178