diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index 652708fb7e..20bddbfff7 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -246,6 +246,8 @@ '../src/gpu/GrBinHashKey.h', '../src/gpu/GrBufferAllocPool.cpp', '../src/gpu/GrBufferAllocPool.h', + '../src/gpu/GrCacheID.h', + '../src/gpu/GrCacheID.cpp', '../src/gpu/GrClipData.cpp', '../src/gpu/GrContext.cpp', '../src/gpu/GrCustomStage.cpp', diff --git a/include/gpu/GrTexture.h b/include/gpu/GrTexture.h index d4a7cc61e0..2ccd3014f8 100644 --- a/include/gpu/GrTexture.h +++ b/include/gpu/GrTexture.h @@ -10,6 +10,7 @@ #define GrTexture_DEFINED #include "GrSurface.h" +#include "GrCacheID.h" class GrRenderTarget; class GrResourceKey; @@ -30,6 +31,7 @@ class GrTexture : public GrSurface { public: SK_DECLARE_INST_COUNT(GrTexture) + GR_DECLARE_RESOURCE_CACHE_TYPE() // from GrResource /** diff --git a/src/gpu/GrCacheID.cpp b/src/gpu/GrCacheID.cpp new file mode 100644 index 0000000000..5f60d94e4b --- /dev/null +++ b/src/gpu/GrCacheID.cpp @@ -0,0 +1,44 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrCacheID.h" +#include "SkThread.h" // for sk_atomic_inc + +uint8_t GrCacheID::GetNextDomain() { + // 0 reserved for kUnrestricted_ResourceDomain + static int32_t gNextDomain = 1; + + int32_t domain = sk_atomic_inc(&gNextDomain); + if (domain >= 256) { + GrCrash("Too many Cache Domains"); + } + + return (uint8_t) domain; +} + +uint8_t GrCacheID::GetNextResourceType() { + // 0 reserved for kInvalid_ResourceType + static int32_t gNextResourceType = 1; + + int32_t type = sk_atomic_inc(&gNextResourceType); + if (type >= 256) { + GrCrash("Too many Cache Resource Types"); + } + + return (uint8_t) type; +} + +void GrCacheID::toRaw(uint32_t v[4]) { + GrAssert(4*sizeof(uint32_t) == sizeof(GrCacheID)); + + v[0] = (uint32_t) (fPublicID & 0xffffffffUL); + v[1] = (uint32_t) ((fPublicID >> 32) & 0xffffffffUL); + v[2] = fResourceSpecific32; + v[3] = fDomain << 24 | + fResourceType << 16 | + fResourceSpecific16; +} diff --git a/src/gpu/GrCacheID.h b/src/gpu/GrCacheID.h new file mode 100644 index 0000000000..972ce107cc --- /dev/null +++ b/src/gpu/GrCacheID.h @@ -0,0 +1,104 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrCacheID_DEFINED +#define GrCacheID_DEFINED + +#include "GrTypes.h" + +/////////////////////////////////////////////////////////////////////////////// +#define GR_DECLARE_RESOURCE_CACHE_TYPE() \ + static int8_t GetResourceType(); + +#define GR_DEFINE_RESOURCE_CACHE_TYPE(ClassName) \ + int8_t ClassName::GetResourceType() { \ + static int8_t kResourceTypeID = 0; \ + if (0 == kResourceTypeID) { \ + kResourceTypeID = GrCacheID::GetNextResourceType(); \ + } \ + return kResourceTypeID; \ + } + + +/////////////////////////////////////////////////////////////////////////////// +#define GR_DECLARE_RESOURCE_CACHE_DOMAIN(AccessorName) \ + static int8_t AccessorName(); + +#define GR_DEFINE_RESOURCE_CACHE_DOMAIN(ClassName, AccessorName) \ + int8_t ClassName::AccessorName() { \ + static int8_t kDomainID = 0; \ + if (0 == kDomainID) { \ + kDomainID = GrCacheID::GetNextDomain(); \ + } \ + return kDomainID; \ + } + +/** + * The cache ID adds structure to the IDs used for caching GPU resources. It + * is broken into three portions: + * the public portion - which is filled in by Skia clients + * the private portion - which is used by the cache (domain & type) + * the resource-specific portion - which is filled in by each GrResource- + * derived class. + * + * For the public portion each client of the cache makes up its own + * unique-per-resource identifier (e.g., bitmap genID). A public ID of + * 'kScratch_CacheID' indicates that the resource is a "scratch" resource. + * When used to acquire a resource it indicates the cache user is + * looking for a resource that matches a resource-subclass-specific set of + * “dimensions” such as width, height, buffer size, or pixel config, but not + * for particular resource contents (e.g., texel or vertex values). The public + * IDs are unique within a private ID value but not necessarily across + * private IDs. + * + * The domain portion identifies the cache client while the type field + * indicates the resource type. When the public portion indicates that the + * resource is a scratch resource, the domain field should be kUnrestricted + * so that scratch resources can be recycled across domains. + */ +class GrCacheID { +public: + uint64_t fPublicID; + + uint32_t fResourceSpecific32; + + uint8_t fDomain; +private: + uint8_t fResourceType; + +public: + uint16_t fResourceSpecific16; + + GrCacheID(uint8_t resourceType) + : fPublicID(kDefaultPublicCacheID) + , fDomain(kUnrestricted_ResourceDomain) + , fResourceType(resourceType) { + } + + void toRaw(uint32_t v[4]); + + uint8_t getResourceType() const { return fResourceType; } + + /* + * Default value for public portion of GrCacheID + */ + static const uint64_t kDefaultPublicCacheID = 0; + + static const uint8_t kInvalid_ResourceType = 0; + /** + * All scratch resources should be Unrestricted so they can be used + * by any domain. + */ + static const uint8_t kUnrestricted_ResourceDomain = 0; + + static uint8_t GetNextDomain(); + static uint8_t GetNextResourceType(); + + +}; + +#endif // GrCacheID_DEFINED diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index 0abe86262b..a424b02dfc 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -16,6 +16,9 @@ #include "GrAAConvexPathRenderer.h" #include "GrAAHairLinePathRenderer.h" #include "GrSWMaskHelper.h" +#include "GrCacheID.h" + +GR_DEFINE_RESOURCE_CACHE_DOMAIN(GrClipMaskManager, GetAlphaMaskDomain) //#define GR_AA_CLIP 1 //#define GR_SW_CLIP 1 diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h index a8a00742f2..fed4205653 100644 --- a/src/gpu/GrClipMaskManager.h +++ b/src/gpu/GrClipMaskManager.h @@ -262,6 +262,8 @@ private: */ class GrClipMaskManager : public GrNoncopyable { public: + GR_DECLARE_RESOURCE_CACHE_DOMAIN(GetAlphaMaskDomain) + GrClipMaskManager(GrGpu* gpu) : fGpu(gpu) , fCurrClipMaskType(kNone_ClipMaskType) { diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 49cbec4db9..6ea8531b15 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -177,22 +177,6 @@ GrTexture* GrContext::TextureCacheEntry::texture() const { namespace { -// we should never have more than one stencil buffer with same combo of -// (width,height,samplecount) -void gen_stencil_key_values(int width, int height, - int sampleCnt, uint32_t v[4]) { - v[0] = width; - v[1] = height; - v[2] = sampleCnt; - v[3] = GrResourceKey::kStencilBuffer_TypeBit; -} - -void gen_stencil_key_values(const GrStencilBuffer* sb, - uint32_t v[4]) { - gen_stencil_key_values(sb->width(), sb->height(), - sb->numSamples(), v); -} - void scale_rect(SkRect* rect, float xScale, float yScale) { rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale)); rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale)); @@ -268,17 +252,18 @@ bool GrContext::isTextureInCache(const GrTextureDesc& desc, GrResourceEntry* GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) { ASSERT_OWNED_RESOURCE(sb); - uint32_t v[4]; - gen_stencil_key_values(sb, v); - GrResourceKey resourceKey(v); + + GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(), + sb->height(), + sb->numSamples()); return fTextureCache->createAndLock(resourceKey, sb); } GrStencilBuffer* GrContext::findStencilBuffer(int width, int height, int sampleCnt) { - uint32_t v[4]; - gen_stencil_key_values(width, height, sampleCnt, v); - GrResourceKey resourceKey(v); + GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width, + height, + sampleCnt); GrResourceEntry* entry = fTextureCache->findAndLock(resourceKey, GrResourceCache::kSingle_LockType); if (NULL != entry) { diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h index 24f2b8ffa6..076097dcf2 100644 --- a/src/gpu/GrResourceCache.h +++ b/src/gpu/GrResourceCache.h @@ -41,16 +41,6 @@ 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/GrStencilBuffer.cpp b/src/gpu/GrStencilBuffer.cpp index 4b08e238ef..bacbe78d7f 100644 --- a/src/gpu/GrStencilBuffer.cpp +++ b/src/gpu/GrStencilBuffer.cpp @@ -10,6 +10,9 @@ #include "GrContext.h" #include "GrGpu.h" +#include "GrResourceCache.h" + +GR_DEFINE_RESOURCE_CACHE_TYPE(GrStencilBuffer) void GrStencilBuffer::wasDetachedFromRenderTarget(const GrRenderTarget* rt) { GrAssert(fRTAttachmentCnt > 0); @@ -53,3 +56,32 @@ void GrStencilBuffer::unlockInCache() { } } } + +namespace { +// we should never have more than one stencil buffer with same combo of +// (width,height,samplecount) +void gen_stencil_key_values(int width, + int height, + int sampleCnt, + GrCacheID* cacheID) { + cacheID->fPublicID = GrCacheID::kDefaultPublicCacheID; + cacheID->fResourceSpecific32 = width | (height << 16); + cacheID->fDomain = GrCacheID::kUnrestricted_ResourceDomain; + + GrAssert(sampleCnt >= 0 && sampleCnt < 256); + cacheID->fResourceSpecific16 = sampleCnt << 8; + + // last 8 bits of 'fResourceSpecific16' is free for flags +} +} + +GrResourceKey GrStencilBuffer::ComputeKey(int width, + int height, + int sampleCnt) { + GrCacheID id(GrStencilBuffer::GetResourceType()); + gen_stencil_key_values(width, height, sampleCnt, &id); + + uint32_t v[4]; + id.toRaw(v); + return GrResourceKey(v); +} diff --git a/src/gpu/GrStencilBuffer.h b/src/gpu/GrStencilBuffer.h index 9767b1733f..649e130cd9 100644 --- a/src/gpu/GrStencilBuffer.h +++ b/src/gpu/GrStencilBuffer.h @@ -12,12 +12,16 @@ #include "GrClipData.h" #include "GrResource.h" +#include "GrCacheID.h" class GrRenderTarget; class GrResourceEntry; +class GrResourceKey; class GrStencilBuffer : public GrResource { public: + GR_DECLARE_RESOURCE_CACHE_TYPE() + virtual ~GrStencilBuffer() { // currently each rt that has attached this sb keeps a ref // TODO: allow SB to be purged and detach itself from rts @@ -67,6 +71,8 @@ public: void wasDetachedFromRenderTarget(const GrRenderTarget* rt); + static GrResourceKey ComputeKey(int width, int height, int sampleCnt); + protected: GrStencilBuffer(GrGpu* gpu, int width, int height, int bits, int sampleCnt) : GrResource(gpu) diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp index fbc389397e..ac17a104c4 100644 --- a/src/gpu/GrTexture.cpp +++ b/src/gpu/GrTexture.cpp @@ -15,6 +15,7 @@ #include "GrResourceCache.h" SK_DEFINE_INST_COUNT(GrTexture) +GR_DEFINE_RESOURCE_CACHE_TYPE(GrTexture) /** * This method allows us to interrupt the normal deletion process and place @@ -111,26 +112,26 @@ void GrTexture::validateDesc() const { } } +// These flags need to fit in <= 8 bits so they can be folded into the texture +// key 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, + kNPOT_TextureBit = 0x1, /* * 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, + kFilter_TextureBit = 0x2, /* * The kScratch bit is set if the texture is being used as a scratch * texture. */ - kScratch_TextureBit = kFilter_TextureBit << 1, + kScratch_TextureBit = 0x4, }; namespace { @@ -138,27 +139,28 @@ void gen_texture_key_values(const GrGpu* gpu, const GrTextureParams* params, const GrTextureDesc& desc, bool scratch, - uint32_t v[4]) { + GrCacheID* cacheID) { uint64_t clientKey = desc.fClientCacheID; if (scratch) { // Instead of a client-provided key of the texture contents - // we create a key of from the descriptor. + // we create a key from the descriptor. GrAssert(kScratch_CacheID == clientKey); clientKey = (desc.fFlags << 8) | ((uint64_t) desc.fConfig << 32); } + cacheID->fPublicID = clientKey; + cacheID->fDomain = GrCacheID::kUnrestricted_ResourceDomain; + // 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] = (uint32_t) (clientKey & 0xffffffffUL); - v[1] = (uint32_t) ((clientKey >> 32) & 0xffffffffUL); - v[2] = desc.fWidth | (desc.fHeight << 16); + cacheID->fResourceSpecific32 = desc.fWidth | (desc.fHeight << 16); - v[3] = (desc.fSampleCnt << 24); GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt < 256); + cacheID->fResourceSpecific16 = desc.fSampleCnt << 8; if (!gpu->getCaps().fNPOTTextureTileSupport) { bool isPow2 = GrIsPow2(desc.fWidth) && GrIsPow2(desc.fHeight); @@ -166,18 +168,16 @@ void gen_texture_key_values(const GrGpu* gpu, bool tiled = NULL != params && params->isTiled(); if (tiled && !isPow2) { - v[3] |= kNPOT_TextureBit; + cacheID->fResourceSpecific16 |= kNPOT_TextureBit; if (params->isBilerp()) { - v[3] |= kFilter_TextureBit; + cacheID->fResourceSpecific16 |= kFilter_TextureBit; } } } if (scratch) { - v[3] |= kScratch_TextureBit; + cacheID->fResourceSpecific16 |= kScratch_TextureBit; } - - v[3] |= GrResourceKey::kTexture_TypeBit; } } @@ -185,8 +185,11 @@ GrResourceKey GrTexture::ComputeKey(const GrGpu* gpu, const GrTextureParams* params, const GrTextureDesc& desc, bool scratch) { + GrCacheID id(GrTexture::GetResourceType()); + gen_texture_key_values(gpu, params, desc, scratch, &id); + uint32_t v[4]; - gen_texture_key_values(gpu, params, desc, scratch, v); + id.toRaw(v); return GrResourceKey(v); }