180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc. 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrTexture.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrContext.h" 137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrDrawTargetCaps.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGpu.h" 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrRenderTarget.h" 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrResourceCache.h" 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(GrTexture) 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGrTexture::~GrTexture() { 217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (NULL != fRenderTarget.get()) { 227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fRenderTarget.get()->owningTextureDestroyed(); 237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * This method allows us to interrupt the normal deletion process and place 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * textures back in the texture cache when their ref count goes to zero. 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::internal_dispose() const { 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit) && 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NULL != this->INHERITED::getContext()) { 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrTexture* nonConstThis = const_cast<GrTexture *>(this); 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->fRefCnt = 1; // restore ref count to initial setting 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru nonConstThis->resetFlag((GrTextureFlags) kReturnToCache_FlagBit); 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru nonConstThis->INHERITED::getContext()->addExistingTextureToCache(nonConstThis); 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Note: "this" texture might be freed inside addExistingTextureToCache 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // if it is purged. 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->INHERITED::internal_dispose(); 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrTexture::readPixels(int left, int top, int width, int height, 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPixelConfig config, void* buffer, 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t rowBytes, uint32_t pixelOpsFlags) { 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // go through context so that all necessary flushing occurs 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrContext* context = this->getContext(); 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == context) { 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return context->readTexturePixels(this, 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru left, top, width, height, 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru config, buffer, rowBytes, 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pixelOpsFlags); 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::writePixels(int left, int top, int width, int height, 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPixelConfig config, const void* buffer, 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t rowBytes, uint32_t pixelOpsFlags) { 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // go through context so that all necessary flushing occurs 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrContext* context = this->getContext(); 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == context) { 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru context->writeTexturePixels(this, 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru left, top, width, height, 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru config, buffer, rowBytes, 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pixelOpsFlags); 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::onRelease() { 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(!this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit)); 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru INHERITED::onRelease(); 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::onAbandon() { 827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (NULL != fRenderTarget.get()) { 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRenderTarget->abandon(); 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru INHERITED::onAbandon(); 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::validateDesc() const { 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL != this->asRenderTarget()) { 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // This texture has a render target 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(0 != (fDesc.fFlags & kRenderTarget_GrTextureFlagBit)); 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL != this->asRenderTarget()->getStencilBuffer()) { 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(0 != (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(fDesc.fSampleCnt == this->asRenderTarget()->numSamples()); 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(0 == (fDesc.fFlags & kRenderTarget_GrTextureFlagBit)); 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit)); 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(0 == fDesc.fSampleCnt); 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 107d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger// These flags need to fit in a GrResourceKey::ResourceFlags so they can be folded into the texture 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// key 109d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerenum TextureFlags { 110d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger /** 111d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger * The kStretchToPOT bit is set when the texture is NPOT and is being repeated but the 112d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger * hardware doesn't support that feature. 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 114d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger kStretchToPOT_TextureFlag = 0x1, 115d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger /** 11658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * The kBilerp bit can only be set when the kStretchToPOT flag is set and indicates whether the 11758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * stretched texture should be bilerped. 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 11958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger kBilerp_TextureFlag = 0x2, 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace { 123d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrResourceKey::ResourceFlags get_texture_flags(const GrGpu* gpu, 124d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const GrTextureParams* params, 125d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const GrTextureDesc& desc) { 126d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrResourceKey::ResourceFlags flags = 0; 127d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger bool tiled = NULL != params && params->isTiled(); 1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (tiled && !gpu->caps()->npotTextureTileSupport()) { 129d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger if (!GrIsPow2(desc.fWidth) || !GrIsPow2(desc.fHeight)) { 130d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger flags |= kStretchToPOT_TextureFlag; 13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger switch(params->filterMode()) { 13258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger case GrTextureParams::kNone_FilterMode: 13358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger break; 13458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger case GrTextureParams::kBilerp_FilterMode: 13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger case GrTextureParams::kMipMap_FilterMode: 13658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger flags |= kBilerp_TextureFlag; 13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger break; 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 141d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return flags; 142d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger} 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 144d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrResourceKey::ResourceType texture_resource_type() { 145d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger static const GrResourceKey::ResourceType gType = GrResourceKey::GenerateResourceType(); 146d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return gType; 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 148096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 149096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// FIXME: This should be refactored with the code in gl/GrGpuGL.cpp. 150096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerGrSurfaceOrigin resolve_origin(const GrTextureDesc& desc) { 151096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // By default, GrRenderTargets are GL's normal orientation so that they 152096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // can be drawn to by the outside world without the client having 153096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // to render upside down. 154096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit); 155096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (kDefault_GrSurfaceOrigin == desc.fOrigin) { 156096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin; 157096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } else { 158096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return desc.fOrigin; 159096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 160096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrResourceKey GrTexture::ComputeKey(const GrGpu* gpu, 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrTextureParams* params, 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrTextureDesc& desc, 166d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const GrCacheID& cacheID) { 167d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrResourceKey::ResourceFlags flags = get_texture_flags(gpu, params, desc); 168d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return GrResourceKey(cacheID, texture_resource_type(), flags); 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 171d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrResourceKey GrTexture::ComputeScratchKey(const GrTextureDesc& desc) { 172d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrCacheID::Key idKey; 173d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger // Instead of a client-provided key of the texture contents we create a key from the 174d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger // descriptor. 175096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GR_STATIC_ASSERT(sizeof(idKey) >= 16); 176d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrAssert(desc.fHeight < (1 << 16)); 177d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrAssert(desc.fWidth < (1 << 16)); 178d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger idKey.fData32[0] = (desc.fWidth) | (desc.fHeight << 16); 179d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger idKey.fData32[1] = desc.fConfig | desc.fSampleCnt << 16; 180d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger idKey.fData32[2] = desc.fFlags; 181096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger idKey.fData32[3] = resolve_origin(desc); // Only needs 2 bits actually 182096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger static const int kPadSize = sizeof(idKey) - 16; 183096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GR_STATIC_ASSERT(kPadSize >= 0); 184096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger memset(idKey.fData8 + 16, 0, kPadSize); 185d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 186d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrCacheID cacheID(GrResourceKey::ScratchDomain(), idKey); 187d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return GrResourceKey(cacheID, texture_resource_type(), 0); 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 190d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerbool GrTexture::NeedsResizing(const GrResourceKey& key) { 191d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return SkToBool(key.getResourceFlags() & kStretchToPOT_TextureFlag); 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool GrTexture::NeedsBilerp(const GrResourceKey& key) { 19558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return SkToBool(key.getResourceFlags() & kBilerp_TextureFlag); 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 197