diff options
author | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-06-04 20:05:28 +0000 |
---|---|---|
committer | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-06-04 20:05:28 +0000 |
commit | a1e5795279bd085496fa04c59e588f440bf30457 (patch) | |
tree | 7ad0fb599faa8cca9839b435736b9523e0690ffa /src/gpu | |
parent | 778e1635030ab77b29b592a9dcafc112ad60ce65 (diff) |
GrTexture can now create its own cache key
http://codereview.appspot.com/6269047/
git-svn-id: http://skia.googlecode.com/svn/trunk@4148 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrContext.cpp | 125 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.h | 10 | ||||
-rw-r--r-- | src/gpu/GrTexture.cpp | 95 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 31 | ||||
-rw-r--r-- | src/gpu/SkGr.cpp | 10 | ||||
-rw-r--r-- | src/gpu/SkGrTexturePixelRef.cpp | 2 |
6 files changed, 156 insertions, 117 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index b7ada614a3..072bc47314 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -163,17 +163,6 @@ int GrContext::PaintStageVertexLayoutBits( //////////////////////////////////////////////////////////////////////////////// -enum { - // flags for textures - kNPOTBit = 0x1, - kFilterBit = 0x2, - kScratchBit = 0x4, - - // resource type - kTextureBit = 0x8, - kStencilBufferBit = 0x10 -}; - GrTexture* GrContext::TextureCacheEntry::texture() const { if (NULL == fEntry) { return NULL; @@ -183,50 +172,6 @@ GrTexture* GrContext::TextureCacheEntry::texture() const { } namespace { -// returns true if this is a "special" texture because of gpu NPOT limitations -bool gen_texture_key_values(const GrGpu* gpu, - const GrSamplerState* sampler, - GrContext::TextureKey clientKey, - int width, - int height, - int sampleCnt, - bool scratch, - uint32_t v[4]) { - GR_STATIC_ASSERT(sizeof(GrContext::TextureKey) == sizeof(uint64_t)); - // we assume we only need 16 bits of width and height - // assert that texture creation will fail anyway if this assumption - // would cause key collisions. - GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16); - v[0] = clientKey & 0xffffffffUL; - v[1] = (clientKey >> 32) & 0xffffffffUL; - v[2] = width | (height << 16); - - v[3] = (sampleCnt << 24); - GrAssert(sampleCnt >= 0 && sampleCnt < 256); - - if (!gpu->getCaps().fNPOTTextureTileSupport) { - bool isPow2 = GrIsPow2(width) && GrIsPow2(height); - - bool tiled = NULL != sampler && - ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) || - (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode)); - - if (tiled && !isPow2) { - v[3] |= kNPOTBit; - if (GrSamplerState::kNearest_Filter != sampler->getFilter()) { - v[3] |= kFilterBit; - } - } - } - - if (scratch) { - v[3] |= kScratchBit; - } - - v[3] |= kTextureBit; - - return v[3] & kNPOTBit; -} // we should never have more than one stencil buffer with same combo of // (width,height,samplecount) @@ -235,7 +180,7 @@ void gen_stencil_key_values(int width, int height, v[0] = width; v[1] = height; v[2] = sampleCnt; - v[3] = kStencilBufferBit; + v[3] = GrResourceKey::kStencilBuffer_TypeBit; } void gen_stencil_key_values(const GrStencilBuffer* sb, @@ -307,24 +252,18 @@ void convolve_gaussian(GrGpu* gpu, } GrContext::TextureCacheEntry GrContext::findAndLockTexture( - TextureKey key, - int width, - int height, + GrTexture::TextureKey key, + const GrTextureDesc& desc, const GrSamplerState* sampler) { - uint32_t v[4]; - gen_texture_key_values(fGpu, sampler, key, width, height, 0, false, v); - GrResourceKey resourceKey(v); + GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, sampler, key, desc, false); return TextureCacheEntry(fTextureCache->findAndLock(resourceKey, GrResourceCache::kNested_LockType)); } -bool GrContext::isTextureInCache(TextureKey key, - int width, - int height, +bool GrContext::isTextureInCache(GrTexture::TextureKey key, + const GrTextureDesc& desc, const GrSamplerState* sampler) const { - uint32_t v[4]; - gen_texture_key_values(fGpu, sampler, key, width, height, 0, false, v); - GrResourceKey resourceKey(v); + GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, sampler, key, desc, false); return fTextureCache->hasKey(resourceKey); } @@ -384,7 +323,7 @@ static void stretchImage(void* dst, } GrContext::TextureCacheEntry GrContext::createAndLockTexture( - TextureKey key, + GrTexture::TextureKey key, const GrSamplerState* sampler, const GrTextureDesc& desc, void* srcData, @@ -396,17 +335,16 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture( #endif TextureCacheEntry entry; - uint32_t v[4]; - bool special = gen_texture_key_values(fGpu, sampler, key, - desc.fWidth, desc.fHeight, - desc.fSampleCnt, false, v); - GrResourceKey resourceKey(v); - if (special) { + GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, sampler, key, + desc, false); + + if (GrTexture::NeedsResizing(resourceKey)) { + // The desired texture is NPOT and tiled but that isn't supported by + // the current hardware. Resize the texture to be a POT GrAssert(NULL != sampler); TextureCacheEntry clampEntry = this->findAndLockTexture(key, - desc.fWidth, - desc.fHeight, + desc, NULL); if (NULL == clampEntry.texture()) { @@ -437,10 +375,10 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture( // if filtering is not desired then we want to ensure all // texels in the resampled image are copies of texels from // the original. - if (GrSamplerState::kNearest_Filter == sampler->getFilter()) { - filter = GrSamplerState::kNearest_Filter; - } else { + if (GrTexture::NeedsFiltering(resourceKey)) { filter = GrSamplerState::kBilinear_Filter; + } else { + filter = GrSamplerState::kNearest_Filter; } drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode, filter); @@ -497,21 +435,6 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture( return entry; } -namespace { -inline void gen_scratch_tex_key_values(const GrGpu* gpu, - const GrTextureDesc& desc, - uint32_t v[4]) { - // Instead of a client-provided key of the texture contents - // we create a key of from the descriptor. - GrContext::TextureKey descKey = (desc.fFlags << 8) | - ((uint64_t) desc.fConfig << 32); - // this code path isn't friendly to tiling with NPOT restricitons - // We just pass ClampNoFilter() - gen_texture_key_values(gpu, NULL, descKey, desc.fWidth, - desc.fHeight, desc.fSampleCnt, true, v); -} -} - GrContext::TextureCacheEntry GrContext::lockScratchTexture( const GrTextureDesc& inDesc, ScratchTexMatch match) { @@ -531,9 +454,7 @@ GrContext::TextureCacheEntry GrContext::lockScratchTexture( bool doubledH = false; do { - uint32_t v[4]; - gen_scratch_tex_key_values(fGpu, desc, v); - GrResourceKey key(v); + GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, 0, desc, true); entry = fTextureCache->findAndLock(key, GrResourceCache::kNested_LockType); // if we miss, relax the fit of the flags... @@ -566,9 +487,9 @@ GrContext::TextureCacheEntry GrContext::lockScratchTexture( desc.fHeight = origHeight; GrTexture* texture = fGpu->createTexture(desc, NULL, 0); if (NULL != texture) { - uint32_t v[4]; - gen_scratch_tex_key_values(fGpu, desc, v); - GrResourceKey key(v); + GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, 0, + texture->desc(), + true); entry = fTextureCache->createAndLock(key, texture); } } @@ -587,7 +508,7 @@ void GrContext::unlockTexture(TextureCacheEntry entry) { // If this is a scratch texture we detached it from the cache // while it was locked (to avoid two callers simultaneously getting // the same texture). - if (kScratchBit & entry.cacheEntry()->key().getValue32(3)) { + if (GrTexture::IsScratchTexture(entry.cacheEntry()->key())) { fTextureCache->reattachAndUnlock(entry.cacheEntry()); } else { fTextureCache->unlock(entry.cacheEntry()); diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h index f86fcd270f..b83e8ec348 100644 --- a/src/gpu/GrResourceCache.h +++ b/src/gpu/GrResourceCache.h @@ -41,6 +41,16 @@ public: kHashMask = kHashCount - 1 }; + enum TypeBits { + // resource types + kTexture_TypeBit = 0x01, + kStencilBuffer_TypeBit = 0x02, + + // Derived classes may add additional bits + kDummy_TypeBit, + kLastPublic_TypeBit = kDummy_TypeBit-1, + }; + GrResourceKey(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) { fP[0] = p0; fP[1] = p1; diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp index 00ae8d0a41..e05b62ba5b 100644 --- a/src/gpu/GrTexture.cpp +++ b/src/gpu/GrTexture.cpp @@ -12,6 +12,7 @@ #include "GrContext.h" #include "GrGpu.h" #include "GrRenderTarget.h" +#include "GrResourceCache.h" bool GrTexture::readPixels(int left, int top, int width, int height, GrPixelConfig config, void* buffer, @@ -80,3 +81,97 @@ void GrTexture::validateDesc() const { GrAssert(0 == fDesc.fSampleCnt); } } + +enum TextureBits { + kFirst_TextureBit = (GrResourceKey::kLastPublic_TypeBit << 1), + + /* + * The kNPOT bit is set when the texture is NPOT and is being repeated + * but the hardware doesn't support that feature. + */ + kNPOT_TextureBit = kFirst_TextureBit, + /* + * The kFilter bit can only be set when the kNPOT flag is set and indicates + * whether the resizing of the texture should use filtering. This is + * to handle cases where the original texture is indexed to disable + * filtering. + */ + kFilter_TextureBit = kNPOT_TextureBit << 1, + /* + * The kScratch bit is set if the texture is being used as a scratch + * texture. + */ + kScratch_TextureBit = kFilter_TextureBit << 1, +}; + +namespace { +void gen_texture_key_values(const GrGpu* gpu, + const GrSamplerState* sampler, + GrTexture::TextureKey clientKey, + const GrTextureDesc& desc, + bool scratch, + uint32_t v[4]) { + GR_STATIC_ASSERT(sizeof(GrTexture::TextureKey) == sizeof(uint64_t)); + + if (scratch) { + // Instead of a client-provided key of the texture contents + // we create a key of from the descriptor. + GrAssert(0 == clientKey); + clientKey = (desc.fFlags << 8) | ((uint64_t) desc.fConfig << 32); + } + + // we assume we only need 16 bits of width and height + // assert that texture creation will fail anyway if this assumption + // would cause key collisions. + GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16); + v[0] = clientKey & 0xffffffffUL; + v[1] = (clientKey >> 32) & 0xffffffffUL; + v[2] = desc.fWidth | (desc.fHeight << 16); + + v[3] = (desc.fSampleCnt << 24); + GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt < 256); + + if (!gpu->getCaps().fNPOTTextureTileSupport) { + bool isPow2 = GrIsPow2(desc.fWidth) && GrIsPow2(desc.fHeight); + + bool tiled = NULL != sampler && + ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) || + (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode)); + + if (tiled && !isPow2) { + v[3] |= kNPOT_TextureBit; + if (GrSamplerState::kNearest_Filter != sampler->getFilter()) { + v[3] |= kFilter_TextureBit; + } + } + } + + if (scratch) { + v[3] |= kScratch_TextureBit; + } + + v[3] |= GrResourceKey::kTexture_TypeBit; +} +} + +GrResourceKey GrTexture::ComputeKey(const GrGpu* gpu, + const GrSamplerState* sampler, + TextureKey clientKey, + const GrTextureDesc& desc, + bool scratch) { + uint32_t v[4]; + gen_texture_key_values(gpu, sampler, clientKey, desc, scratch, v); + return GrResourceKey(v); +} + +bool GrTexture::NeedsResizing(const GrResourceKey& key) { + return 0 != (key.getValue32(3) & kNPOT_TextureBit); +} + +bool GrTexture::IsScratchTexture(const GrResourceKey& key) { + return 0 != (key.getValue32(3) & kScratch_TextureBit); +} + +bool GrTexture::NeedsFiltering(const GrResourceKey& key) { + return 0 != (key.getValue32(3) & kFilter_TextureBit); +} diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 056c5d8179..d9d23495ce 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -230,7 +230,7 @@ SkGpuDevice::SkGpuDevice(GrContext* context, kRenderTarget_GrTextureFlagBit, width, height, - SkGr::Bitmap2PixelConfig(bm), + SkGr::BitmapConfig2PixelConfig(bm.config()), 0 // samples }; @@ -337,8 +337,7 @@ void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y, if (SkBitmap::kARGB_8888_Config == bitmap.config()) { config = config8888_to_gr_config(config8888); } else { - config= SkGr::BitmapConfig2PixelConfig(bitmap.config(), - bitmap.isOpaque()); + config= SkGr::BitmapConfig2PixelConfig(bitmap.config()); } fRenderTarget->writePixels(x, y, bitmap.width(), bitmap.height(), @@ -1831,11 +1830,18 @@ SkGpuDevice::TexCache SkGpuDevice::lockCachedTexture( GrContext* ctx = this->context(); if (!bitmap.isVolatile()) { - GrContext::TextureKey key = bitmap.getGenerationID(); + GrTexture::TextureKey key = bitmap.getGenerationID(); key |= ((uint64_t) bitmap.pixelRefOffset()) << 32; - entry = ctx->findAndLockTexture(key, bitmap.width(), - bitmap.height(), sampler); + GrTextureDesc desc = { + kNone_GrTextureFlags, + bitmap.width(), + bitmap.height(), + SkGr::BitmapConfig2PixelConfig(bitmap.config()), + 0 // samples + }; + + entry = ctx->findAndLockTexture(key, desc, sampler); if (NULL == entry.texture()) { entry = sk_gr_create_bitmap_texture(ctx, key, sampler, bitmap); @@ -1857,11 +1863,18 @@ void SkGpuDevice::unlockCachedTexture(TexCache cache) { bool SkGpuDevice::isBitmapInTextureCache(const SkBitmap& bitmap, const GrSamplerState& sampler) const { - GrContext::TextureKey key = bitmap.getGenerationID(); + GrTexture::TextureKey key = bitmap.getGenerationID(); key |= ((uint64_t) bitmap.pixelRefOffset()) << 32; - return this->context()->isTextureInCache(key, bitmap.width(), - bitmap.height(), &sampler); + GrTextureDesc desc = { + kNone_GrTextureFlags, + bitmap.width(), + bitmap.height(), + SkGr::BitmapConfig2PixelConfig(bitmap.config()), + 0 // samples + }; + + return this->context()->isTextureInCache(key, desc, &sampler); } diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 12967e2690..92a3aff932 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -57,7 +57,7 @@ static void build_compressed_data(void* buffer, const SkBitmap& bitmap) { //////////////////////////////////////////////////////////////////////////////// GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx, - GrContext::TextureKey key, + GrTexture::TextureKey key, const GrSamplerState* sampler, const SkBitmap& origBitmap) { SkAutoLockPixels alp(origBitmap); @@ -75,7 +75,7 @@ GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx, kNone_GrTextureFlags, bitmap->width(), bitmap->height(), - SkGr::Bitmap2PixelConfig(*bitmap), + SkGr::BitmapConfig2PixelConfig(bitmap->config()), 0 // samples }; @@ -112,7 +112,7 @@ GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx, } } - desc.fConfig = SkGr::Bitmap2PixelConfig(*bitmap); + desc.fConfig = SkGr::BitmapConfig2PixelConfig(bitmap->config()); if (gUNCACHED_KEY != key) { return ctx->createAndLockTexture(key, sampler, desc, bitmap->getPixels(), @@ -194,8 +194,7 @@ GrPathFill SkGrClipIterator::getPathFill() const { /////////////////////////////////////////////////////////////////////////////// -GrPixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config, - bool isOpaque) { +GrPixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config) { switch (config) { case SkBitmap::kA8_Config: return kAlpha_8_GrPixelConfig; @@ -208,6 +207,7 @@ GrPixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config, case SkBitmap::kARGB_8888_Config: return kSkia8888_PM_GrPixelConfig; default: + // kNo_Config, kA1_Config missing, and kRLE_Index8_Config return kUnknown_GrPixelConfig; } } diff --git a/src/gpu/SkGrTexturePixelRef.cpp b/src/gpu/SkGrTexturePixelRef.cpp index c81e9c09b3..485d572c0b 100644 --- a/src/gpu/SkGrTexturePixelRef.cpp +++ b/src/gpu/SkGrTexturePixelRef.cpp @@ -62,7 +62,7 @@ static SkGrTexturePixelRef* copyToTexturePixelRef(GrTexture* texture, desc.fWidth = texture->width(); desc.fHeight = texture->height(); desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; - desc.fConfig = SkGr::BitmapConfig2PixelConfig(dstConfig, false); + desc.fConfig = SkGr::BitmapConfig2PixelConfig(dstConfig); desc.fSampleCnt = 0; GrTexture* dst = context->createUncachedTexture(desc, NULL, 0); |