diff --git a/bench/GrResourceCacheBench.cpp b/bench/GrResourceCacheBench.cpp index 2a593c5e38..7469217c3f 100644 --- a/bench/GrResourceCacheBench.cpp +++ b/bench/GrResourceCacheBench.cpp @@ -28,15 +28,12 @@ public: this->registerWithCache(); } - static GrResourceKey ComputeKey(int i) { - GrCacheID::Key key; - memset(&key, 0, sizeof(key)); - key.fData32[0] = i; - static int gDomain = GrCacheID::GenerateDomain(); - return GrResourceKey(GrCacheID(gDomain, key), 0); + static void ComputeKey(int i, GrContentKey* key) { + static GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey::Builder builder(key, kDomain, 1); + builder[0] = i; } - private: size_t onGpuMemorySize() const SK_OVERRIDE { return 100; } @@ -45,7 +42,8 @@ private: static void populate_cache(GrGpu* gpu, int resourceCount) { for (int i = 0; i < resourceCount; ++i) { - GrResourceKey key = BenchResource::ComputeKey(i); + GrContentKey key; + BenchResource::ComputeKey(i, &key); GrGpuResource* resource = SkNEW_ARGS(BenchResource, (gpu)); resource->cacheAccess().setContentKey(key); resource->unref(); @@ -127,7 +125,8 @@ protected: SkASSERT(CACHE_SIZE_COUNT == cache2->getResourceCount()); for (int i = 0; i < loops; ++i) { for (int k = 0; k < CACHE_SIZE_COUNT; ++k) { - GrResourceKey key = BenchResource::ComputeKey(k); + GrContentKey key; + BenchResource::ComputeKey(k, &key); SkAutoTUnref resource(cache2->findAndRefContentResource(key)); SkASSERT(resource); } diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 77b29ff57e..c29e1b3526 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -62,7 +62,6 @@ '<(skia_src_path)/gpu/GrBlend.h', '<(skia_src_path)/gpu/GrBufferAllocPool.cpp', '<(skia_src_path)/gpu/GrBufferAllocPool.h', - '<(skia_src_path)/gpu/GrCacheID.cpp', '<(skia_src_path)/gpu/GrClipData.cpp', '<(skia_src_path)/gpu/GrClipMaskCache.h', '<(skia_src_path)/gpu/GrClipMaskCache.cpp', diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index 70d34c5c97..e6fdeb89f7 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -172,14 +172,14 @@ public: /** * Stores a custom resource in the cache, based on the specified key. */ - void addResourceToCache(const GrResourceKey&, GrGpuResource*); + void addResourceToCache(const GrContentKey&, GrGpuResource*); /** * Finds a resource in the cache, based on the specified key. This is intended for use in * conjunction with addResourceToCache(). The return value will be NULL if not found. The * caller must balance with a call to unref(). */ - GrGpuResource* findAndRefCachedResource(const GrResourceKey&); + GrGpuResource* findAndRefCachedResource(const GrContentKey&); /** * Creates a new text rendering context that is optimal for the @@ -198,45 +198,53 @@ public: * Creates a new entry, based on the specified key and texture and returns it. The caller owns a * ref on the returned texture which must be balanced by a call to unref. * + * TODO: Move resizing logic out of GrContext and have the caller set the content key on the + * returned texture rather than take it as a param. + * * @param params The texture params used to draw a texture may help determine * the cache entry used. (e.g. different versions may exist * for different wrap modes on GPUs with limited NPOT * texture support). NULL implies clamp wrap modes. * @param desc Description of the texture properties. - * @param cacheID Cache-specific properties (e.g., texture gen ID) + * @param key Key to associate with the texture. * @param srcData Pointer to the pixel values. * @param rowBytes The number of bytes between rows of the texture. Zero * implies tightly packed rows. For compressed pixel configs, this * field is ignored. - * @param cacheKey (optional) If non-NULL, we'll write the cache key we used to cacheKey. + * @param outKey (optional) If non-NULL, we'll write the cache key we used to cacheKey. this + * may differ from key on GPUs that don't support tiling NPOT textures. */ GrTexture* createTexture(const GrTextureParams* params, const GrSurfaceDesc& desc, - const GrCacheID& cacheID, + const GrContentKey& key, const void* srcData, size_t rowBytes, - GrResourceKey* cacheKey = NULL); + GrContentKey* outKey = NULL); /** * Search for an entry based on key and dimensions. If found, ref it and return it. The return * value will be NULL if not found. The caller must balance with a call to unref. * + * TODO: Remove this function and do lookups generically. + * * @param desc Description of the texture properties. - * @param cacheID Cache-specific properties (e.g., texture gen ID) + * @param key key to use for texture look up. * @param params The texture params used to draw a texture may help determine * the cache entry used. (e.g. different versions may exist * for different wrap modes on GPUs with limited NPOT * texture support). NULL implies clamp wrap modes. */ GrTexture* findAndRefTexture(const GrSurfaceDesc& desc, - const GrCacheID& cacheID, + const GrContentKey& key, const GrTextureParams* params); /** * Determines whether a texture is in the cache. If the texture is found it * will not be locked or returned. This call does not affect the priority of * the texture for deletion. + * + * TODO: Remove this function and do cache checks generically. */ bool isTextureInCache(const GrSurfaceDesc& desc, - const GrCacheID& cacheID, + const GrContentKey& key, const GrTextureParams* params) const; /** @@ -871,8 +879,9 @@ private: const SkPath&, const GrStrokeInfo&); - GrTexture* createResizedTexture(const GrSurfaceDesc& desc, - const GrCacheID& cacheID, + // TODO: Move this out of GrContext. + GrTexture* createResizedTexture(const GrSurfaceDesc&, + const GrContentKey& origKey, const void* srcData, size_t rowBytes, bool filter); diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h index 750ec6a440..d6abc4d12c 100644 --- a/include/gpu/GrGpuResource.h +++ b/include/gpu/GrGpuResource.h @@ -259,7 +259,7 @@ private: virtual size_t onGpuMemorySize() const = 0; // See comments in CacheAccess. - bool setContentKey(const GrResourceKey& contentKey); + bool setContentKey(const GrContentKey& contentKey); void notifyIsPurgable() const; void removeScratchKey(); void makeBudgeted(); @@ -275,27 +275,18 @@ private: static const size_t kInvalidGpuMemorySize = ~static_cast(0); - enum Flags { - /** - * If set then fContentKey is valid and the resource is cached based on its content. - */ - kContentKeySet_Flag = 0x1, - }; - - GrScratchKey fScratchKey; - // TODO(bsalomon): Remove GrResourceKey and use different simpler type for content keys. - GrResourceKey fContentKey; + GrScratchKey fScratchKey; + GrContentKey fContentKey; // This is not ref'ed but abandon() or release() will be called before the GrGpu object // is destroyed. Those calls set will this to NULL. - GrGpu* fGpu; - mutable size_t fGpuMemorySize; + GrGpu* fGpu; + mutable size_t fGpuMemorySize; - uint32_t fFlags; - LifeCycle fLifeCycle; - const uint32_t fUniqueID; + LifeCycle fLifeCycle; + const uint32_t fUniqueID; - SkAutoTUnref fData; + SkAutoTUnref fData; typedef GrIORef INHERITED; friend class GrIORef; // to access notifyIsPurgable. diff --git a/include/gpu/GrResourceKey.h b/include/gpu/GrResourceKey.h index 9922c8f5d0..9cf955be98 100644 --- a/include/gpu/GrResourceKey.h +++ b/include/gpu/GrResourceKey.h @@ -13,149 +13,212 @@ #include "SkTemplates.h" #include "GrBinHashKey.h" -/** - * A key used for scratch resources. The key consists of a resource type (subclass) identifier, a - * hash, a data length, and type-specific data. A Builder object is used to initialize the - * key contents. The contents must be initialized before the key can be used. - */ -class GrScratchKey { -public: - /** Uniquely identifies the type of resource that is cached as scratch. */ - typedef uint32_t ResourceType; - /** Generate a unique ResourceType. */ - static ResourceType GenerateResourceType(); +uint32_t GrResourceKeyHash(const uint32_t* data, size_t size); - GrScratchKey() { this->reset(); } - GrScratchKey(const GrScratchKey& that) { *this = that; } +class GrResourceKey { +public: + uint32_t hash() const { + this->validate(); + return fKey[kHash_MetaDataIdx]; + } + + size_t size() const { + this->validate(); + return this->internalSize(); + } + + const uint32_t* data() const { + this->validate(); + return &fKey[kMetaDataCnt]; + } + +protected: + static const uint32_t kInvalidDomain = 0; + + GrResourceKey() { this->reset(); } /** Reset to an invalid key. */ void reset() { + GR_STATIC_ASSERT((uint16_t)kInvalidDomain == kInvalidDomain); fKey.reset(kMetaDataCnt); fKey[kHash_MetaDataIdx] = 0; - fKey[kTypeAndSize_MetaDataIdx] = kInvalidResourceType; + fKey[kDomainAndSize_MetaDataIdx] = kInvalidDomain; } - bool isValid() const { return kInvalidResourceType != this->resourceType(); } + bool operator==(const GrResourceKey& that) const { + return 0 == memcmp(fKey.get(), that.fKey.get(), this->size()); + } - ResourceType resourceType() const { return fKey[kTypeAndSize_MetaDataIdx] & 0xffff; } - - uint32_t hash() const { return fKey[kHash_MetaDataIdx]; } - - size_t size() const { return SkToInt(fKey[kTypeAndSize_MetaDataIdx] >> 16); } - - const uint32_t* data() const { return &fKey[kMetaDataCnt]; } - - GrScratchKey& operator=(const GrScratchKey& that) { + GrResourceKey& operator=(const GrResourceKey& that) { size_t bytes = that.size(); + SkASSERT(SkIsAlign4(bytes)); fKey.reset(SkToInt(bytes / sizeof(uint32_t))); memcpy(fKey.get(), that.fKey.get(), bytes); return *this; } - bool operator==(const GrScratchKey& that) const { - return 0 == memcmp(fKey.get(), that.fKey.get(), this->size()); - } - bool operator!=(const GrScratchKey& that) const { return !(*this == that); } + bool isValid() const { return kInvalidDomain != this->domain(); } - /** Used to initialize scratch key. */ + uint32_t domain() const { return fKey[kDomainAndSize_MetaDataIdx] & 0xffff; } + + /** Used to initialize a key. */ class Builder { public: - Builder(GrScratchKey* key, ResourceType type, int data32Count) : fKey(key) { + Builder(GrResourceKey* key, uint32_t domain, int data32Count) : fKey(key) { SkASSERT(data32Count >= 0); - SkASSERT(type != kInvalidResourceType); + SkASSERT(domain != kInvalidDomain); key->fKey.reset(kMetaDataCnt + data32Count); - SkASSERT(type <= SK_MaxU16); int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t); - SkASSERT(size <= SK_MaxU16); - key->fKey[kTypeAndSize_MetaDataIdx] = type | (size << 16); + SkASSERT(SkToU16(size) == size); + SkASSERT(SkToU16(domain) == domain); + key->fKey[kDomainAndSize_MetaDataIdx] = domain | (size << 16); } ~Builder() { this->finish(); } - void finish(); + void finish() { + if (NULL == fKey) { + return; + } + GR_STATIC_ASSERT(0 == kHash_MetaDataIdx); + uint32_t* hash = &fKey->fKey[kHash_MetaDataIdx]; + *hash = GrResourceKeyHash(hash + 1, fKey->internalSize() - sizeof(uint32_t)); + fKey->validate(); + fKey = NULL; + } uint32_t& operator[](int dataIdx) { SkASSERT(fKey); - SkDEBUGCODE(size_t dataCount = fKey->size() / sizeof(uint32_t) - kMetaDataCnt;) + SkDEBUGCODE(size_t dataCount = fKey->internalSize() / sizeof(uint32_t) - kMetaDataCnt;) SkASSERT(SkToU32(dataIdx) < dataCount); return fKey->fKey[kMetaDataCnt + dataIdx]; } private: - GrScratchKey* fKey; + GrResourceKey* fKey; }; private: + size_t internalSize() const { + return fKey[kDomainAndSize_MetaDataIdx] >> 16; + } + + void validate() const { + SkASSERT(fKey[kHash_MetaDataIdx] == + GrResourceKeyHash(&fKey[kHash_MetaDataIdx] + 1, + this->internalSize() - sizeof(uint32_t))); + } + enum MetaDataIdx { kHash_MetaDataIdx, - // The resource type and size are packed into a single uint32_t. - kTypeAndSize_MetaDataIdx, + // The key domain and size are packed into a single uint32_t. + kDomainAndSize_MetaDataIdx, - kLastMetaDataIdx = kTypeAndSize_MetaDataIdx + kLastMetaDataIdx = kDomainAndSize_MetaDataIdx }; - static const uint32_t kInvalidResourceType = 0; static const uint32_t kMetaDataCnt = kLastMetaDataIdx + 1; friend class TestResource; // For unit test to access kMetaDataCnt. - // Stencil and textures each require 2 uint32_t values. - SkAutoSTArray fKey; + // bmp textures require 4 uint32_t values. + SkAutoSTArray fKey; }; -class GrResourceKey { -public: - /** Flags set by the GrGpuResource subclass. */ - typedef uint8_t ResourceFlags; - - /** Creates a key for resource */ - GrResourceKey(const GrCacheID& id, ResourceFlags flags) { - this->init(id.getDomain(), id.getKey(), flags); - }; - - GrResourceKey(const GrResourceKey& src) { fKey = src.fKey; } - - GrResourceKey() { fKey.reset(); } - - void reset(const GrCacheID& id, ResourceFlags flags) { - this->init(id.getDomain(), id.getKey(), flags); - } - - uint32_t getHash() const { return fKey.getHash(); } - - ResourceFlags getResourceFlags() const { - return *reinterpret_cast(fKey.getData() + - kResourceFlagsOffset); - } - - bool operator==(const GrResourceKey& other) const { return fKey == other.fKey; } - - // A key indicating that the resource is not usable as a scratch resource. - static GrResourceKey& NullScratchKey(); - +/** + * A key used for scratch resources. The key consists of a resource type (subclass) identifier, a + * hash, a data length, and type-specific data. A Builder object is used to initialize the + * key contents. The contents must be initialized before the key can be used. + */ +class GrScratchKey : public GrResourceKey { private: - enum { - kCacheIDKeyOffset = 0, - kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key), - kResourceFlagsOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain), - kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags), - kKeySize = SkAlign4(kPadOffset), - kPadSize = kKeySize - kPadOffset - }; + typedef GrResourceKey INHERITED; - void init(const GrCacheID::Domain domain, const GrCacheID::Key& key, ResourceFlags flags) { - union { - uint8_t fKey8[kKeySize]; - uint32_t fKey32[kKeySize / 4]; - } keyData; +public: + /** Uniquely identifies the type of resource that is cached as scratch. */ + typedef uint32_t ResourceType; - uint8_t* k = keyData.fKey8; - memcpy(k + kCacheIDKeyOffset, key.fData8, sizeof(GrCacheID::Key)); - memcpy(k + kCacheIDDomainOffset, &domain, sizeof(GrCacheID::Domain)); - memcpy(k + kResourceFlagsOffset, &flags, sizeof(ResourceFlags)); - memset(k + kPadOffset, 0, kPadSize); - fKey.setKeyData(keyData.fKey32); + /** Generate a unique ResourceType. */ + static ResourceType GenerateResourceType(); + + /** Creates an invalid scratch key. It must be initialized using a Builder object before use. */ + GrScratchKey() {} + + GrScratchKey(const GrScratchKey& that) { *this = that; } + + /** reset() returns the key to the invalid state. */ + using INHERITED::reset; + + using INHERITED::isValid; + + ResourceType resourceType() const { return this->domain(); } + + GrScratchKey& operator=(const GrScratchKey& that) { + this->INHERITED::operator=(that); + return *this; } - GrBinHashKey fKey; + + bool operator==(const GrScratchKey& that) const { + return this->INHERITED::operator==(that); + } + bool operator!=(const GrScratchKey& that) const { return !(*this == that); } + + class Builder : public INHERITED::Builder { + public: + Builder(GrScratchKey* key, ResourceType type, int data32Count) + : INHERITED::Builder(key, type, data32Count) {} + }; +}; + +/** + * A key used to cache resources based on their content. The key consists of a domain type (use + * case for the cache), a hash, a data length, and domain-specific data. A Builder object is used to + * initialize the key contents. The contents must be initialized before the key can be used. + */ +class GrContentKey : public GrResourceKey { +private: + typedef GrResourceKey INHERITED; + +public: + typedef uint32_t Domain; + /** Generate a unique Domain of content keys. */ + static Domain GenerateDomain(); + + /** Creates an invalid content key. It must be initialized using a Builder object before use. */ + GrContentKey() {} + + GrContentKey(const GrContentKey& that) { *this = that; } + + /** reset() returns the key to the invalid state. */ + using INHERITED::reset; + + using INHERITED::isValid; + + GrContentKey& operator=(const GrContentKey& that) { + this->INHERITED::operator=(that); + return *this; + } + + bool operator==(const GrContentKey& that) const { + return this->INHERITED::operator==(that); + } + bool operator!=(const GrContentKey& that) const { return !(*this == that); } + + class Builder : public INHERITED::Builder { + public: + Builder(GrContentKey* key, Domain domain, int data32Count) + : INHERITED::Builder(key, domain, data32Count) {} + + /** Used to build a key that wraps another key and adds additional data. */ + Builder(GrContentKey* key, const GrContentKey& innerKey, Domain domain, + int extraData32Cnt) + : INHERITED::Builder(key, domain, (SkToInt(innerKey.size()) >> 2) + extraData32Cnt) { + int innerKeyCnt = SkToInt(innerKey.size()) >> 2; + // add the inner key to the end of the key so that op[] can be indexed normally. + for (int i = 0; i < innerKeyCnt; ++i) { + this->operator[](extraData32Cnt + i) = innerKey.data()[i]; + } + } + }; }; #endif diff --git a/include/gpu/GrTexture.h b/include/gpu/GrTexture.h index ecc1bb07b3..ccf958098a 100644 --- a/include/gpu/GrTexture.h +++ b/include/gpu/GrTexture.h @@ -13,7 +13,6 @@ #include "SkPoint.h" #include "SkRefCnt.h" -class GrResourceKey; class GrTextureParams; class GrTexturePriv; diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h index c4e374fdf2..f4fb3ab43f 100644 --- a/include/gpu/GrTypes.h +++ b/include/gpu/GrTypes.h @@ -472,58 +472,6 @@ struct GrSurfaceDesc { // Legacy alias typedef GrSurfaceDesc GrTextureDesc; -/** - * GrCacheID is used create and find cached GrResources (e.g. GrTextures). The ID has two parts: - * the domain and the key. Domains simply allow multiple clients to use 0-based indices as their - * cache key without colliding. The key uniquely identifies a GrResource within the domain. - * Users of the cache must obtain a domain via GenerateDomain(). - */ -struct GrCacheID { -public: - typedef uint8_t Domain; - - struct Key { - union { - uint8_t fData8[16]; - uint32_t fData32[4]; - uint64_t fData64[2]; - }; - }; - - /** - * A default cache ID is invalid; a set method must be called before the object is used. - */ - GrCacheID() { fDomain = kInvalid_Domain; } - - /** - * Initialize the cache ID to a domain and key. - */ - GrCacheID(Domain domain, const Key& key) { - SkASSERT(kInvalid_Domain != domain); - this->reset(domain, key); - } - - void reset(Domain domain, const Key& key) { - fDomain = domain; - memcpy(&fKey, &key, sizeof(Key)); - } - - /** Has this been initialized to a valid domain */ - bool isValid() const { return kInvalid_Domain != fDomain; } - - const Key& getKey() const { SkASSERT(this->isValid()); return fKey; } - Domain getDomain() const { SkASSERT(this->isValid()); return fDomain; } - - /** Creates a new unique ID domain. */ - static Domain GenerateDomain(); - -private: - Key fKey; - Domain fDomain; - - static const Domain kInvalid_Domain = 0; -}; - /** * Clips are composed from these objects. */ diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h index 06239e6568..1dc1a0e142 100644 --- a/include/gpu/SkGr.h +++ b/include/gpu/SkGr.h @@ -70,7 +70,7 @@ static inline GrColor SkColor2GrColorJustAlpha(SkColor c) { // The cache listens for these messages to purge junk resources proactively. struct GrResourceInvalidatedMessage { - GrResourceKey key; + GrContentKey fKey; }; bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*); diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 7c534d69e0..3487ae40b4 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -753,31 +753,29 @@ bool GrRectBlurEffect::CreateBlurProfileTexture(GrContext *context, float sigma, GrTextureParams params; GrSurfaceDesc texDesc; - unsigned int profile_size = SkScalarCeilToInt(6*sigma); + unsigned int profileSize = SkScalarCeilToInt(6*sigma); - texDesc.fWidth = profile_size; + texDesc.fWidth = profileSize; texDesc.fHeight = 1; texDesc.fConfig = kAlpha_8_GrPixelConfig; - static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomain(); - GrCacheID::Key key; - memset(&key, 0, sizeof(key)); - key.fData32[0] = profile_size; - key.fData32[1] = 1; - GrCacheID blurProfileKey(gBlurProfileDomain, key); + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey key; + GrContentKey::Builder builder(&key, kDomain, 1); + builder[0] = profileSize; + builder.finish(); uint8_t *profile = NULL; SkAutoTDeleteArray ada(NULL); - *blurProfileTexture = context->findAndRefTexture(texDesc, blurProfileKey, ¶ms); + *blurProfileTexture = context->findAndRefTexture(texDesc, key, ¶ms); if (NULL == *blurProfileTexture) { SkBlurMask::ComputeBlurProfile(sigma, &profile); ada.reset(profile); - *blurProfileTexture = context->createTexture(¶ms, texDesc, blurProfileKey, - profile, 0); + *blurProfileTexture = context->createTexture(¶ms, texDesc, key, profile, 0); if (NULL == *blurProfileTexture) { return false; @@ -920,12 +918,12 @@ GrFragmentProcessor* GrRRectBlurEffect::Create(GrContext* context, float sigma, return NULL; } - static const GrCacheID::Domain gRRectBlurDomain = GrCacheID::GenerateDomain(); - GrCacheID::Key key; - memset(&key, 0, sizeof(key)); - key.fData32[0] = blurRadius; - key.fData32[1] = cornerRadius; - GrCacheID blurRRectNinePatchID(gRRectBlurDomain, key); + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey key; + GrContentKey::Builder builder(&key, kDomain, 2); + builder[0] = blurRadius; + builder[1] = cornerRadius; + builder.finish(); GrTextureParams params; params.setFilterMode(GrTextureParams::kBilerp_FilterMode); @@ -937,7 +935,7 @@ GrFragmentProcessor* GrRRectBlurEffect::Create(GrContext* context, float sigma, texDesc.fHeight = texSide; texDesc.fConfig = kAlpha_8_GrPixelConfig; - GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, blurRRectNinePatchID, ¶ms); + GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, key, ¶ms); if (NULL == blurNinePatchTexture) { SkMask mask; @@ -964,7 +962,7 @@ GrFragmentProcessor* GrRRectBlurEffect::Create(GrContext* context, float sigma, SkMask blurred_mask; SkBlurMask::BoxBlur(&blurred_mask, mask, sigma, kNormal_SkBlurStyle, kHigh_SkBlurQuality, NULL, true ); - blurNinePatchTexture = context->createTexture(¶ms, texDesc, blurRRectNinePatchID, blurred_mask.fImage, 0); + blurNinePatchTexture = context->createTexture(¶ms, texDesc, key, blurred_mask.fImage, 0); SkMask::FreeImage(blurred_mask.fImage); } diff --git a/src/effects/SkColorCubeFilter.cpp b/src/effects/SkColorCubeFilter.cpp index 78f8ba3ab7..bfe28396ff 100644 --- a/src/effects/SkColorCubeFilter.cpp +++ b/src/effects/SkColorCubeFilter.cpp @@ -342,26 +342,24 @@ void GrColorCubeEffect::GLProcessor::GenKey(const GrProcessor& proc, } GrFragmentProcessor* SkColorCubeFilter::asFragmentProcessor(GrContext* context) const { - static const GrCacheID::Domain gCubeDomain = GrCacheID::GenerateDomain(); - - GrCacheID::Key key; - key.fData32[0] = fUniqueID; - key.fData32[1] = fCache.cubeDimension(); - key.fData64[1] = 0; - GrCacheID cacheID(gCubeDomain, key); + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey key; + GrContentKey::Builder builder(&key, kDomain, 2); + builder[0] = fUniqueID; + builder[1] = fCache.cubeDimension(); + builder.finish(); GrSurfaceDesc desc; desc.fWidth = fCache.cubeDimension(); desc.fHeight = fCache.cubeDimension() * fCache.cubeDimension(); desc.fConfig = kRGBA_8888_GrPixelConfig; - GrResourceKey rkey = GrTexturePriv::ComputeKey(context->getGpu(), NULL, desc, cacheID); - GrSurface* surface = static_cast(context->findAndRefCachedResource(rkey)); + GrSurface* surface = static_cast(context->findAndRefCachedResource(key)); SkAutoTUnref textureCube; if (surface) { textureCube.reset(surface->asTexture()); } else { - textureCube.reset(context->createTexture(NULL, desc, cacheID, fCubeData->data(), 0)); + textureCube.reset(context->createTexture(NULL, desc, key, fCubeData->data(), 0)); } return textureCube ? GrColorCubeEffect::Create(textureCube) : NULL; diff --git a/src/gpu/GrCacheID.cpp b/src/gpu/GrCacheID.cpp deleted file mode 100644 index 8d0be0da5a..0000000000 --- a/src/gpu/GrCacheID.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 "GrTypes.h" -#include "SkThread.h" // for sk_atomic_inc - -// Well, the dummy_ "fix" caused a warning on windows, so hiding all of it -// until we can find a universal fix. -#if 0 -// This used to be a global scope, but we got a warning about unused variable -// so we moved it into here. We just want it to compile, so we can test the -// static asserts. -static inline void dummy_function_to_avoid_unused_var_warning() { - GrCacheID::Key kAssertKey; - GR_STATIC_ASSERT(sizeof(kAssertKey.fData8) == sizeof(kAssertKey.fData32)); - GR_STATIC_ASSERT(sizeof(kAssertKey.fData8) == sizeof(kAssertKey.fData64)); - GR_STATIC_ASSERT(sizeof(kAssertKey.fData8) == sizeof(kAssertKey)); -} -#endif - -GrCacheID::Domain GrCacheID::GenerateDomain() { - static int32_t gNextDomain = kInvalid_Domain + 1; - - int32_t domain = sk_atomic_inc(&gNextDomain); - if (domain >= 1 << (8 * sizeof(Domain))) { - SkFAIL("Too many Cache Domains"); - } - - return static_cast(domain); -} diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index b798ef0478..ea3ea281fe 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -223,26 +223,6 @@ GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget, //////////////////////////////////////////////////////////////////////////////// -GrTexture* GrContext::findAndRefTexture(const GrSurfaceDesc& desc, - const GrCacheID& cacheID, - const GrTextureParams* params) { - GrResourceKey resourceKey = GrTexturePriv::ComputeKey(fGpu, params, desc, cacheID); - - GrGpuResource* resource = this->findAndRefCachedResource(resourceKey); - if (resource) { - SkASSERT(static_cast(resource)->asTexture()); - return static_cast(resource)->asTexture(); - } - return NULL; -} - -bool GrContext::isTextureInCache(const GrSurfaceDesc& desc, - const GrCacheID& cacheID, - const GrTextureParams* params) const { - GrResourceKey resourceKey = GrTexturePriv::ComputeKey(fGpu, params, desc, cacheID); - return fResourceCache2->hasContentKey(resourceKey); -} - static void stretch_image(void* dst, int dstW, int dstH, @@ -268,20 +248,54 @@ static void stretch_image(void* dst, } } +enum ResizeFlags { + /** + * The kStretchToPOT bit is set when the texture is NPOT and is being repeated or mipped but the + * hardware doesn't support that feature. + */ + kStretchToPOT_ResizeFlag = 0x1, + /** + * The kBilerp bit can only be set when the kStretchToPOT flag is set and indicates whether the + * stretched texture should be bilerped. + */ + kBilerp_ResizeFlag = 0x2, +}; + +static uint32_t get_texture_flags(const GrGpu* gpu, + const GrTextureParams* params, + const GrSurfaceDesc& desc) { + uint32_t flags = 0; + bool tiled = params && params->isTiled(); + if (tiled && !gpu->caps()->npotTextureTileSupport()) { + if (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight)) { + flags |= kStretchToPOT_ResizeFlag; + switch(params->filterMode()) { + case GrTextureParams::kNone_FilterMode: + break; + case GrTextureParams::kBilerp_FilterMode: + case GrTextureParams::kMipMap_FilterMode: + flags |= kBilerp_ResizeFlag; + break; + } + } + } + return flags; +} // The desired texture is NPOT and tiled but that isn't supported by // the current hardware. Resize the texture to be a POT GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc, - const GrCacheID& cacheID, + const GrContentKey& origKey, const void* srcData, size_t rowBytes, bool filter) { - SkAutoTUnref clampedTexture(this->findAndRefTexture(desc, cacheID, NULL)); + SkAutoTUnref clampedTexture(this->findAndRefTexture(desc, origKey, NULL)); if (NULL == clampedTexture) { - clampedTexture.reset(this->createTexture(NULL, desc, cacheID, srcData, rowBytes)); + clampedTexture.reset(this->createTexture(NULL, desc, origKey, srcData, rowBytes)); if (NULL == clampedTexture) { return NULL; } + clampedTexture->cacheAccess().setContentKey(origKey); } GrSurfaceDesc rtDesc = desc; @@ -318,6 +332,9 @@ GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc, verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(SkPoint)); verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint)); fDrawBuffer->drawNonIndexed(&pipelineBuilder, gp, kTriangleFan_GrPrimitiveType, 0, 4); + } else { + texture->unref(); + texture = NULL; } } else { // TODO: Our CPU stretch doesn't filter. But we create separate @@ -347,30 +364,39 @@ GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc, return texture; } +static GrContentKey::Domain ResizeDomain() { + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + return kDomain; +} + GrTexture* GrContext::createTexture(const GrTextureParams* params, const GrSurfaceDesc& desc, - const GrCacheID& cacheID, + const GrContentKey& origKey, const void* srcData, size_t rowBytes, - GrResourceKey* cacheKey) { - GrResourceKey resourceKey = GrTexturePriv::ComputeKey(fGpu, params, desc, cacheID); - + GrContentKey* outKey) { GrTexture* texture; - if (GrTexturePriv::NeedsResizing(resourceKey)) { - // We do not know how to resize compressed textures. - SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); + uint32_t flags = get_texture_flags(fGpu, params, desc); + SkTCopyOnFirstWrite key(origKey); + if (flags) { + // We don't have a code path to resize compressed textures. + if (GrPixelConfigIsCompressed(desc.fConfig)) { + return NULL; + } + texture = this->createResizedTexture(desc, origKey, srcData, rowBytes, + SkToBool(flags & kBilerp_ResizeFlag)); + + GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1); + builder[0] = flags; - texture = this->createResizedTexture(desc, cacheID, - srcData, rowBytes, - GrTexturePriv::NeedsBilerp(resourceKey)); } else { texture = fGpu->createTexture(desc, true, srcData, rowBytes); } if (texture) { - if (texture->cacheAccess().setContentKey(resourceKey)) { - if (cacheKey) { - *cacheKey = resourceKey; + if (texture->cacheAccess().setContentKey(*key)) { + if (outKey) { + *outKey = *key; } } else { texture->unref(); @@ -381,6 +407,37 @@ GrTexture* GrContext::createTexture(const GrTextureParams* params, return texture; } +GrTexture* GrContext::findAndRefTexture(const GrSurfaceDesc& desc, + const GrContentKey& origKey, + const GrTextureParams* params) { + uint32_t flags = get_texture_flags(fGpu, params, desc); + SkTCopyOnFirstWrite key(origKey); + if (flags) { + GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1); + builder[0] = flags; + } + + GrGpuResource* resource = this->findAndRefCachedResource(*key); + if (resource) { + SkASSERT(static_cast(resource)->asTexture()); + return static_cast(resource)->asTexture(); + } + return NULL; +} + +bool GrContext::isTextureInCache(const GrSurfaceDesc& desc, + const GrContentKey& origKey, + const GrTextureParams* params) const { + uint32_t flags = get_texture_flags(fGpu, params, desc); + SkTCopyOnFirstWrite key(origKey); + if (flags) { + GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1); + builder[0] = flags; + } + + return fResourceCache2->hasContentKey(*key); +} + GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexMatch match, bool calledDuringFlush) { // kNoStencil has no meaning if kRT isn't set. @@ -1703,12 +1760,12 @@ const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture, } } -void GrContext::addResourceToCache(const GrResourceKey& resourceKey, GrGpuResource* resource) { - resource->cacheAccess().setContentKey(resourceKey); +void GrContext::addResourceToCache(const GrContentKey& key, GrGpuResource* resource) { + resource->cacheAccess().setContentKey(key); } -GrGpuResource* GrContext::findAndRefCachedResource(const GrResourceKey& resourceKey) { - return fResourceCache2->findAndRefContentResource(resourceKey); +GrGpuResource* GrContext::findAndRefCachedResource(const GrContentKey& key) { + return fResourceCache2->findAndRefContentResource(key); } void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp index 2f267a4197..3e9964f1a0 100644 --- a/src/gpu/GrGpuResource.cpp +++ b/src/gpu/GrGpuResource.cpp @@ -20,7 +20,6 @@ static inline GrResourceCache2* get_resource_cache2(GrGpu* gpu) { GrGpuResource::GrGpuResource(GrGpu* gpu, LifeCycle lifeCycle) : fGpu(gpu) , fGpuMemorySize(kInvalidGpuMemorySize) - , fFlags(0) , fLifeCycle(lifeCycle) , fUniqueID(CreateUniqueID()) { } @@ -83,7 +82,7 @@ void GrGpuResource::didChangeGpuMemorySize() const { get_resource_cache2(fGpu)->resourceAccess().didChangeGpuMemorySize(this, oldSize); } -bool GrGpuResource::setContentKey(const GrResourceKey& contentKey) { +bool GrGpuResource::setContentKey(const GrContentKey& key) { // Currently this can only be called once and can't be called when the resource is scratch. SkASSERT(this->internalHasRef()); @@ -92,15 +91,14 @@ bool GrGpuResource::setContentKey(const GrResourceKey& contentKey) { return false; } - if ((fFlags & kContentKeySet_Flag) || this->wasDestroyed()) { + if (fContentKey.isValid() || this->wasDestroyed()) { return false; } - fContentKey = contentKey; - fFlags |= kContentKeySet_Flag; + fContentKey = key; if (!get_resource_cache2(fGpu)->resourceAccess().didSetContentKey(this)) { - fFlags &= ~kContentKeySet_Flag; + fContentKey.reset(); return false; } return true; diff --git a/src/gpu/GrGpuResourceCacheAccess.h b/src/gpu/GrGpuResourceCacheAccess.h index d7c5028b20..33fe1ad93a 100644 --- a/src/gpu/GrGpuResourceCacheAccess.h +++ b/src/gpu/GrGpuResourceCacheAccess.h @@ -24,7 +24,7 @@ public: * resource that currently is using the content key, allow resources' content keys to change, * and allow removal of a content key to convert a resource back to scratch. */ - bool setContentKey(const GrResourceKey& contentKey) { + bool setContentKey(const GrContentKey& contentKey) { return fResource->setContentKey(contentKey); } @@ -33,7 +33,7 @@ public: * not have a content key. */ bool isScratch() const { - return NULL == this->getContentKey() && fResource->fScratchKey.isValid(); + return !this->getContentKey().isValid() && fResource->fScratchKey.isValid(); } /** @@ -52,12 +52,7 @@ public: /** * If the resource is currently cached by a content key, the key is returned, otherwise NULL. */ - const GrResourceKey* getContentKey() const { - if (fResource->fFlags & GrGpuResource::kContentKeySet_Flag) { - return &fResource->fContentKey; - } - return NULL; - } + const GrContentKey& getContentKey() const { return fResource->fContentKey; } /** * Is the resource object wrapping an externally allocated GPU resource? diff --git a/src/gpu/GrPath.cpp b/src/gpu/GrPath.cpp index eb956fbf65..a069b0ad1e 100644 --- a/src/gpu/GrPath.cpp +++ b/src/gpu/GrPath.cpp @@ -13,15 +13,11 @@ template static uint64_t get_top_n_float_bits(float f) { return floatBits >> (32 - NumBits); } -GrResourceKey GrPath::ComputeKey(const SkPath& path, const SkStrokeRec& stroke) { - static const GrCacheID::Domain gPathDomain = GrCacheID::GenerateDomain(); - - GrCacheID::Key key; - uint64_t* keyData = key.fData64; - keyData[0] = path.getGenerationID(); - keyData[1] = ComputeStrokeKey(stroke); - - return GrResourceKey(GrCacheID(gPathDomain, key), 0); +void GrPath::ComputeKey(const SkPath& path, const SkStrokeRec& stroke, GrContentKey* key) { + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey::Builder builder(key, kDomain, 3); + *reinterpret_cast(&builder[0]) = ComputeStrokeKey(stroke); + builder[2] = path.getGenerationID(); } uint64_t GrPath::ComputeStrokeKey(const SkStrokeRec& stroke) { diff --git a/src/gpu/GrPath.h b/src/gpu/GrPath.h index eaa3b40fdb..56e26b3374 100644 --- a/src/gpu/GrPath.h +++ b/src/gpu/GrPath.h @@ -27,7 +27,7 @@ public: fBounds(skPath.getBounds()) { } - static GrResourceKey ComputeKey(const SkPath& path, const SkStrokeRec& stroke); + static void ComputeKey(const SkPath& path, const SkStrokeRec& stroke, GrContentKey* key); static uint64_t ComputeStrokeKey(const SkStrokeRec&); bool isEqualTo(const SkPath& path, const SkStrokeRec& stroke) { diff --git a/src/gpu/GrResourceCache2.cpp b/src/gpu/GrResourceCache2.cpp index ba9d4d1016..a63bda8cc7 100644 --- a/src/gpu/GrResourceCache2.cpp +++ b/src/gpu/GrResourceCache2.cpp @@ -19,7 +19,7 @@ DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); ////////////////////////////////////////////////////////////////////////////// GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() { - static int32_t gType = kInvalidResourceType + 1; + static int32_t gType = INHERITED::kInvalidDomain + 1; int32_t type = sk_atomic_inc(&gType); if (type > SK_MaxU16) { @@ -29,15 +29,18 @@ GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() { return static_cast(type); } +GrContentKey::Domain GrContentKey::GenerateDomain() { + static int32_t gDomain = INHERITED::kInvalidDomain + 1; -void GrScratchKey::Builder::finish() { - if (NULL == fKey) { - return; + int32_t domain = sk_atomic_inc(&gDomain); + if (kInvalidDomain == gDomain) { + SkFAIL("Too many Content Key Domains"); } - GR_STATIC_ASSERT(0 == kHash_MetaDataIdx); - fKey->fKey[kHash_MetaDataIdx] = - SkChecksum::Compute(&fKey->fKey[kHash_MetaDataIdx + 1], fKey->size() - sizeof(uint32_t)); - fKey = NULL; + + return static_cast(domain); +} +uint32_t GrResourceKeyHash(const uint32_t* data, size_t size) { + return SkChecksum::Compute(data, size); } ////////////////////////////////////////////////////////////////////////////// @@ -129,8 +132,8 @@ void GrResourceCache2::removeResource(GrGpuResource* resource) { if (resource->cacheAccess().getScratchKey().isValid()) { fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource); } - if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) { - fContentHash.remove(*contentKey); + if (resource->cacheAccess().getContentKey().isValid()) { + fContentHash.remove(resource->cacheAccess().getContentKey()); } this->validate(); } @@ -222,9 +225,9 @@ bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) { SkASSERT(!fPurging); SkASSERT(resource); SkASSERT(this->isInCache(resource)); - SkASSERT(resource->cacheAccess().getContentKey()); + SkASSERT(resource->cacheAccess().getContentKey().isValid()); - GrGpuResource* res = fContentHash.find(*resource->cacheAccess().getContentKey()); + GrGpuResource* res = fContentHash.find(resource->cacheAccess().getContentKey()); if (NULL != res) { return false; } @@ -258,8 +261,8 @@ void GrResourceCache2::notifyPurgable(GrGpuResource* resource) { bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes; // Also purge if the resource has neither a valid scratch key nor a content key. - bool noKey = !resource->cacheAccess().isScratch() && - (NULL == resource->cacheAccess().getContentKey()); + bool noKey = !resource->cacheAccess().getScratchKey().isValid() && + !resource->cacheAccess().getContentKey().isValid(); // Only cached resources should ever have a key. SkASSERT(noKey || resource->cacheAccess().isBudgeted()); @@ -406,20 +409,20 @@ void GrResourceCache2::validate() const { } if (resource->cacheAccess().isScratch()) { - SkASSERT(NULL == resource->cacheAccess().getContentKey()); + SkASSERT(!resource->cacheAccess().getContentKey().isValid()); ++scratch; SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey())); SkASSERT(!resource->cacheAccess().isWrapped()); } else if (resource->cacheAccess().getScratchKey().isValid()) { - SkASSERT(NULL != resource->cacheAccess().getContentKey()); + SkASSERT(resource->cacheAccess().getContentKey().isValid()); ++couldBeScratch; SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey())); SkASSERT(!resource->cacheAccess().isWrapped()); } - - if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) { + const GrContentKey& contentKey = resource->cacheAccess().getContentKey(); + if (contentKey.isValid()) { ++content; - SkASSERT(fContentHash.find(*contentKey) == resource); + SkASSERT(fContentHash.find(contentKey) == resource); SkASSERT(!resource->cacheAccess().isWrapped()); } diff --git a/src/gpu/GrResourceCache2.h b/src/gpu/GrResourceCache2.h index 5733cff664..5aee1add86 100644 --- a/src/gpu/GrResourceCache2.h +++ b/src/gpu/GrResourceCache2.h @@ -110,7 +110,7 @@ public: /** * Find a resource that matches a content key. */ - GrGpuResource* findAndRefContentResource(const GrResourceKey& contentKey) { + GrGpuResource* findAndRefContentResource(const GrContentKey& contentKey) { GrGpuResource* resource = fContentHash.find(contentKey); if (resource) { resource->ref(); @@ -122,7 +122,7 @@ public: /** * Query whether a content key exists in the cache. */ - bool hasContentKey(const GrResourceKey& contentKey) const { + bool hasContentKey(const GrContentKey& contentKey) const { return SkToBool(fContentHash.find(contentKey)); } @@ -193,13 +193,13 @@ private: typedef SkTMultiMap ScratchMap; struct ContentHashTraits { - static const GrResourceKey& GetKey(const GrGpuResource& r) { - return *r.cacheAccess().getContentKey(); + static const GrContentKey& GetKey(const GrGpuResource& r) { + return r.cacheAccess().getContentKey(); } - static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); } + static uint32_t Hash(const GrContentKey& key) { return key.hash(); } }; - typedef SkTDynamicHash ContentHash; + typedef SkTDynamicHash ContentHash; typedef SkTInternalLList ResourceList; diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp index 1a3856c801..1b6a2f7c7e 100644 --- a/src/gpu/GrStencilAndCoverPathRenderer.cpp +++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp @@ -72,11 +72,12 @@ GrStencilAndCoverPathRenderer::onGetStencilSupport(const GrDrawTarget*, static GrPath* get_gr_path(GrGpu* gpu, const SkPath& skPath, const SkStrokeRec& stroke) { GrContext* ctx = gpu->getContext(); - GrResourceKey resourceKey = GrPath::ComputeKey(skPath, stroke); - SkAutoTUnref path(static_cast(ctx->findAndRefCachedResource(resourceKey))); + GrContentKey key; + GrPath::ComputeKey(skPath, stroke, &key); + SkAutoTUnref path(static_cast(ctx->findAndRefCachedResource(key))); if (NULL == path || !path->isEqualTo(skPath, stroke)) { path.reset(gpu->pathRendering()->createPath(skPath, stroke)); - ctx->addResourceToCache(resourceKey, path); + ctx->addResourceToCache(key, path); } return path.detach(); } diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp index c29dca6d0a..2f2f1f8ebd 100644 --- a/src/gpu/GrStencilAndCoverTextContext.cpp +++ b/src/gpu/GrStencilAndCoverTextContext.cpp @@ -205,20 +205,25 @@ static GrPathRange* get_gr_glyphs(GrContext* ctx, const SkTypeface* typeface, const SkDescriptor* desc, const SkStrokeRec& stroke) { - static const GrCacheID::Domain gGlyphsDomain = GrCacheID::GenerateDomain(); - - GrCacheID::Key key; - uint64_t* keyData = key.fData64; - keyData[0] = desc ? desc->getChecksum() : 0; - keyData[0] = (keyData[0] << 32) | (typeface ? typeface->uniqueID() : 0); - keyData[1] = GrPath::ComputeStrokeKey(stroke); - GrResourceKey resourceKey = GrResourceKey(GrCacheID(gGlyphsDomain, key), 0); + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey key; + GrContentKey::Builder builder(&key, kDomain, 4); + struct GlyphKey { + uint32_t fChecksum; + uint32_t fTypeface; + uint64_t fStroke; + }; + GlyphKey* glyphKey = reinterpret_cast(&builder[0]); + glyphKey->fChecksum = desc ? desc->getChecksum() : 0; + glyphKey->fTypeface = typeface ? typeface->uniqueID() : 0; + glyphKey->fStroke = GrPath::ComputeStrokeKey(stroke); + builder.finish(); SkAutoTUnref glyphs( - static_cast(ctx->findAndRefCachedResource(resourceKey))); + static_cast(ctx->findAndRefCachedResource(key))); if (NULL == glyphs || (NULL != desc && !glyphs->isEqualTo(*desc))) { glyphs.reset(ctx->getGpu()->pathRendering()->createGlyphs(typeface, desc, stroke)); - ctx->addResourceToCache(resourceKey, glyphs); + ctx->addResourceToCache(key, glyphs); } return glyphs.detach(); diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp index 378e9900f7..30dbbb659a 100644 --- a/src/gpu/GrTexture.cpp +++ b/src/gpu/GrTexture.cpp @@ -66,42 +66,7 @@ void GrTexture::validateDesc() const { ////////////////////////////////////////////////////////////////////////////// -// These flags need to fit in a GrResourceKey::ResourceFlags so they can be folded into the texture -// key -enum TextureFlags { - /** - * The kStretchToPOT bit is set when the texture is NPOT and is being repeated but the - * hardware doesn't support that feature. - */ - kStretchToPOT_TextureFlag = 0x1, - /** - * The kBilerp bit can only be set when the kStretchToPOT flag is set and indicates whether the - * stretched texture should be bilerped. - */ - kBilerp_TextureFlag = 0x2, -}; - namespace { -GrResourceKey::ResourceFlags get_texture_flags(const GrGpu* gpu, - const GrTextureParams* params, - const GrSurfaceDesc& desc) { - GrResourceKey::ResourceFlags flags = 0; - bool tiled = params && params->isTiled(); - if (tiled && !gpu->caps()->npotTextureTileSupport()) { - if (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight)) { - flags |= kStretchToPOT_TextureFlag; - switch(params->filterMode()) { - case GrTextureParams::kNone_FilterMode: - break; - case GrTextureParams::kBilerp_FilterMode: - case GrTextureParams::kMipMap_FilterMode: - flags |= kBilerp_TextureFlag; - break; - } - } - } - return flags; -} // FIXME: This should be refactored with the code in gl/GrGLGpu.cpp. GrSurfaceOrigin resolve_origin(const GrSurfaceDesc& desc) { @@ -132,14 +97,6 @@ GrTexture::GrTexture(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc) fShiftFixedY = 31 - SkCLZ(fDesc.fHeight); } -GrResourceKey GrTexturePriv::ComputeKey(const GrGpu* gpu, - const GrTextureParams* params, - const GrSurfaceDesc& desc, - const GrCacheID& cacheID) { - GrResourceKey::ResourceFlags flags = get_texture_flags(gpu, params, desc); - return GrResourceKey(cacheID, flags); -} - void GrTexturePriv::ComputeScratchKey(const GrSurfaceDesc& desc, GrScratchKey* key) { static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType(); @@ -158,11 +115,3 @@ void GrTexturePriv::ComputeScratchKey(const GrSurfaceDesc& desc, GrScratchKey* k builder[0] = desc.fWidth | (desc.fHeight << 16); builder[1] = desc.fConfig | (desc.fSampleCnt << 6) | (flags << 14) | (origin << 24); } - -bool GrTexturePriv::NeedsResizing(const GrResourceKey& key) { - return SkToBool(key.getResourceFlags() & kStretchToPOT_TextureFlag); -} - -bool GrTexturePriv::NeedsBilerp(const GrResourceKey& key) { - return SkToBool(key.getResourceFlags() & kBilerp_TextureFlag); -} diff --git a/src/gpu/GrTexturePriv.h b/src/gpu/GrTexturePriv.h index c093a9bbc6..8add4e1c49 100644 --- a/src/gpu/GrTexturePriv.h +++ b/src/gpu/GrTexturePriv.h @@ -39,14 +39,7 @@ public: return GrTexture::kNotAllocated_MipMapsStatus != fTexture->fMipMapsStatus; } - static GrResourceKey ComputeKey(const GrGpu* gpu, - const GrTextureParams* params, - const GrSurfaceDesc& desc, - const GrCacheID& cacheID); static void ComputeScratchKey(const GrSurfaceDesc&, GrScratchKey*); - static bool NeedsResizing(const GrResourceKey& key); - static bool NeedsBilerp(const GrResourceKey& key); - // TODO: Move this logic and the shift values out of here and to the callers. SkFixed normalizeFixedX(SkFixed x) const { diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index a3972806f7..9083860db8 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -86,25 +86,20 @@ static void build_index8_data(void* buffer, const SkBitmap& bitmap) { //////////////////////////////////////////////////////////////////////////////// -static void generate_bitmap_cache_id(const SkBitmap& bitmap, GrCacheID* id) { +static void generate_bitmap_key(const SkBitmap& bitmap, GrContentKey* key) { // Our id includes the offset, width, and height so that bitmaps created by extractSubset() // are unique. uint32_t genID = bitmap.getGenerationID(); SkIPoint origin = bitmap.pixelRefOrigin(); - int16_t width = SkToS16(bitmap.width()); - int16_t height = SkToS16(bitmap.height()); + uint32_t width = SkToU16(bitmap.width()); + uint32_t height = SkToU16(bitmap.height()); - GrCacheID::Key key; - memcpy(key.fData8 + 0, &genID, 4); - memcpy(key.fData8 + 4, &origin.fX, 4); - memcpy(key.fData8 + 8, &origin.fY, 4); - memcpy(key.fData8 + 12, &width, 2); - memcpy(key.fData8 + 14, &height, 2); - static const size_t kKeyDataSize = 16; - memset(key.fData8 + kKeyDataSize, 0, sizeof(key) - kKeyDataSize); - GR_STATIC_ASSERT(sizeof(key) >= kKeyDataSize); - static const GrCacheID::Domain gBitmapTextureDomain = GrCacheID::GenerateDomain(); - id->reset(gBitmapTextureDomain, key); + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey::Builder builder(key, kDomain, 4); + builder[0] = genID; + builder[1] = origin.fX; + builder[2] = origin.fY; + builder[3] = width | (height << 16); } static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrSurfaceDesc* desc) { @@ -120,9 +115,9 @@ namespace { // When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key. class GrResourceInvalidator : public SkPixelRef::GenIDChangeListener { public: - explicit GrResourceInvalidator(GrResourceKey key) : fKey(key) {} + explicit GrResourceInvalidator(const GrContentKey& key) : fKey(key) {} private: - GrResourceKey fKey; + GrContentKey fKey; void onChange() SK_OVERRIDE { const GrResourceInvalidatedMessage message = { fKey }; @@ -132,7 +127,7 @@ private: } // namespace -static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) { +static void add_genID_listener(const GrContentKey& key, SkPixelRef* pixelRef) { SkASSERT(pixelRef); pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key))); } @@ -147,11 +142,10 @@ static GrTexture* sk_gr_allocate_texture(GrContext* ctx, GrTexture* result; if (cache) { // This texture is likely to be used again so leave it in the cache - GrCacheID cacheID; - generate_bitmap_cache_id(bm, &cacheID); + GrContentKey key; + generate_bitmap_key(bm, &key); - GrResourceKey key; - result = ctx->createTexture(params, desc, cacheID, pixels, rowBytes, &key); + result = ctx->createTexture(params, desc, key, pixels, rowBytes, &key); if (result) { add_genID_listener(key, bm.pixelRef()); } @@ -399,12 +393,12 @@ bool GrIsBitmapInCache(const GrContext* ctx, return true; } - GrCacheID cacheID; - generate_bitmap_cache_id(bitmap, &cacheID); + GrContentKey key; + generate_bitmap_key(bitmap, &key); GrSurfaceDesc desc; generate_bitmap_texture_desc(bitmap, &desc); - return ctx->isTextureInCache(desc, cacheID, params); + return ctx->isTextureInCache(desc, key, params); } GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, @@ -420,13 +414,13 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, if (cache) { // If the bitmap isn't changing try to find a cached copy first. - GrCacheID cacheID; - generate_bitmap_cache_id(bitmap, &cacheID); + GrContentKey key; + generate_bitmap_key(bitmap, &key); GrSurfaceDesc desc; generate_bitmap_texture_desc(bitmap, &desc); - result = ctx->findAndRefTexture(desc, cacheID, params); + result = ctx->findAndRefTexture(desc, key, params); } if (NULL == result) { result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap); diff --git a/src/gpu/effects/GrTextureStripAtlas.cpp b/src/gpu/effects/GrTextureStripAtlas.cpp index 134c99f452..2305586844 100644 --- a/src/gpu/effects/GrTextureStripAtlas.cpp +++ b/src/gpu/effects/GrTextureStripAtlas.cpp @@ -196,15 +196,15 @@ void GrTextureStripAtlas::lockTexture() { texDesc.fHeight = fDesc.fHeight; texDesc.fConfig = fDesc.fConfig; - static const GrCacheID::Domain gTextureStripAtlasDomain = GrCacheID::GenerateDomain(); - GrCacheID::Key key; - *key.fData32 = fCacheKey; - memset(key.fData32 + 1, 0, sizeof(key) - sizeof(uint32_t)); - GrCacheID cacheID(gTextureStripAtlasDomain, key); + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey key; + GrContentKey::Builder builder(&key, kDomain, 1); + builder[0] = static_cast(fCacheKey); + builder.finish(); - fTexture = fDesc.fContext->findAndRefTexture(texDesc, cacheID, ¶ms); + fTexture = fDesc.fContext->findAndRefTexture(texDesc, key, ¶ms); if (NULL == fTexture) { - fTexture = fDesc.fContext->createTexture(¶ms, texDesc, cacheID, NULL, 0); + fTexture = fDesc.fContext->createTexture(¶ms, texDesc, key, NULL, 0); // This is a new texture, so all of our cache info is now invalid this->initLRU(); fKeyTable.rewind(); diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index c43d757230..c3752c48bb 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -98,9 +98,7 @@ GrFragmentProcessor* BigKeyProcessor::TestCreate(SkRandom*, static const int kRenderTargetHeight = 1; static const int kRenderTargetWidth = 1; -static GrRenderTarget* random_render_target(GrContext* context, - const GrCacheID& cacheId, - SkRandom* random) { +static GrRenderTarget* random_render_target(GrContext* context, SkRandom* random) { // setup render target GrTextureParams params; GrSurfaceDesc texDesc; @@ -110,10 +108,15 @@ static GrRenderTarget* random_render_target(GrContext* context, texDesc.fConfig = kRGBA_8888_GrPixelConfig; texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin; + GrContentKey key; + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + GrContentKey::Builder builder(&key, kDomain, 1); + builder[0] = texDesc.fOrigin; + builder.finish(); - SkAutoTUnref texture(context->findAndRefTexture(texDesc, cacheId, ¶ms)); + SkAutoTUnref texture(context->findAndRefTexture(texDesc, key, ¶ms)); if (!texture) { - texture.reset(context->createTexture(¶ms, texDesc, cacheId, 0, 0)); + texture.reset(context->createTexture(¶ms, texDesc, key, 0, 0)); if (!texture) { return NULL; } @@ -237,14 +240,6 @@ bool GrDrawTarget::programUnitTest(int maxStages) { // dummy scissor state GrScissorState scissor; - // Setup texture cache id key - const GrCacheID::Domain glProgramsDomain = GrCacheID::GenerateDomain(); - GrCacheID::Key key; - memset(&key, 0, sizeof(key)); - key.fData32[0] = kRenderTargetWidth; - key.fData32[1] = kRenderTargetHeight; - GrCacheID glProgramsCacheID(glProgramsDomain, key); - // setup clip SkRect screen = SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), SkIntToScalar(kRenderTargetHeight)); @@ -261,7 +256,7 @@ bool GrDrawTarget::programUnitTest(int maxStages) { static const int NUM_TESTS = 512; for (int t = 0; t < NUM_TESTS;) { // setup random render target(can fail) - SkAutoTUnref rt(random_render_target(fContext, glProgramsCacheID, &random)); + SkAutoTUnref rt(random_render_target(fContext, &random)); if (!rt.get()) { SkDebugf("Could not allocate render target"); return false; diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index 31ae9b40e6..6b7d68c75f 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -120,8 +120,8 @@ public: static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) { static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType(); GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt); - for (size_t i = 0; i < kScratchKeyFieldCnt; ++i) { - builder[i] = i + static_cast(property); + for (int i = 0; i < kScratchKeyFieldCnt; ++i) { + builder[i] = static_cast(i + property); } } @@ -130,7 +130,7 @@ public: } private: - static const size_t kScratchKeyFieldCnt = 6; + static const int kScratchKeyFieldCnt = 6; TestResource(GrGpu* gpu, SimulatedProperty property, ScratchConstructor) : INHERITED(gpu, kCached_LifeCycle) @@ -209,6 +209,13 @@ static void test_no_key(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes()); } +// Each integer passed as a template param creates a new domain. +template static void make_content_key(GrContentKey* key, int data) { + static GrContentKey::Domain d = GrContentKey::GenerateDomain(); + GrContentKey::Builder builder(key, d, 1); + builder[0] = data; +} + static void test_budgeting(skiatest::Reporter* reporter) { SkAutoTUnref context(GrContext::CreateMockContext()); REPORTER_ASSERT(reporter, SkToBool(context)); @@ -221,9 +228,8 @@ static void test_budgeting(skiatest::Reporter* reporter) { SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes()); - GrCacheID::Key keyData; - memset(&keyData, 0, sizeof(keyData)); - GrResourceKey contentKey(GrCacheID(GrCacheID::GenerateDomain(), keyData), 0); + GrContentKey contentKey; + make_content_key<0>(&contentKey, 0); // Create a scratch, a content, and a wrapped resource TestResource* scratch = @@ -241,8 +247,8 @@ static void test_budgeting(skiatest::Reporter* reporter) { unbudgeted->setSize(13); // Make sure we can't add a content key to the wrapped resource - keyData.fData8[0] = 1; - GrResourceKey contentKey2(GrCacheID(GrCacheID::GenerateDomain(), keyData), 0); + GrContentKey contentKey2; + make_content_key<0>(&contentKey2, 1); REPORTER_ASSERT(reporter, !wrapped->cacheAccess().setContentKey(contentKey2)); REPORTER_ASSERT(reporter, NULL == cache2->findAndRefContentResource(contentKey2)); @@ -315,9 +321,8 @@ static void test_unbudgeted(skiatest::Reporter* reporter) { SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes()); - GrCacheID::Key keyData; - memset(&keyData, 0, sizeof(keyData)); - GrResourceKey contentKey(GrCacheID(GrCacheID::GenerateDomain(), keyData), 0); + GrContentKey contentKey; + make_content_key<0>(&contentKey, 0); TestResource* scratch; TestResource* content; @@ -576,10 +581,8 @@ static void test_duplicate_content_key(skiatest::Reporter* reporter) { cache2->purgeAllUnlocked(); SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); - GrCacheID::Domain domain = GrCacheID::GenerateDomain(); - GrCacheID::Key keyData; - memset(&keyData, 0, sizeof(keyData)); - GrResourceKey key(GrCacheID(domain, keyData), 0); + GrContentKey key; + make_content_key<0>(&key, 0); // Create two resources that we will attempt to register with the same content key. TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu())); @@ -627,16 +630,10 @@ static void test_purge_invalidated(skiatest::Reporter* reporter) { return; } - GrCacheID::Domain domain = GrCacheID::GenerateDomain(); - GrCacheID::Key keyData; - memset(&keyData, 0, sizeof(keyData)); - - keyData.fData64[0] = 1; - GrResourceKey key1(GrCacheID(domain, keyData), 0); - keyData.fData64[0] = 2; - GrResourceKey key2(GrCacheID(domain, keyData), 0); - keyData.fData64[0] = 3; - GrResourceKey key3(GrCacheID(domain, keyData), 0); + GrContentKey key1, key2, key3; + make_content_key<0>(&key1, 1); + make_content_key<0>(&key2, 2); + make_content_key<0>(&key3, 3); context->setResourceCacheLimits(5, 30000); GrResourceCache2* cache2 = context->getResourceCache2(); @@ -694,15 +691,9 @@ static void test_cache_chained_purge(skiatest::Reporter* reporter) { return; } - GrCacheID::Domain domain = GrCacheID::GenerateDomain(); - GrCacheID::Key keyData; - memset(&keyData, 0, sizeof(keyData)); - - keyData.fData64[0] = 1; - GrResourceKey key1(GrCacheID(domain, keyData), 0); - - keyData.fData64[0] = 2; - GrResourceKey key2(GrCacheID(domain, keyData), 0); + GrContentKey key1, key2; + make_content_key<0>(&key1, 1); + make_content_key<0>(&key2, 2); { context->setResourceCacheLimits(3, 30000); @@ -745,17 +736,9 @@ static void test_resource_size_changed(skiatest::Reporter* reporter) { return; } - GrCacheID::Domain domain = GrCacheID::GenerateDomain(); - - GrCacheID::Key key1Data; - key1Data.fData64[0] = 0; - key1Data.fData64[1] = 0; - GrResourceKey key1(GrCacheID(domain, key1Data), 0); - - GrCacheID::Key key2Data; - key2Data.fData64[0] = 1; - key2Data.fData64[1] = 0; - GrResourceKey key2(GrCacheID(domain, key2Data), 0); + GrContentKey key1, key2; + make_content_key<0>(&key1, 1); + make_content_key<0>(&key2, 2); // Test changing resources sizes (both increase & decrease). { @@ -832,25 +815,21 @@ static void test_large_resource_count(skiatest::Reporter* reporter) { cache2->purgeAllUnlocked(); SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); - GrCacheID::Domain domain0 = GrCacheID::GenerateDomain(); - GrCacheID::Domain domain1 = GrCacheID::GenerateDomain(); - - GrCacheID::Key keyData; - memset(&keyData, 0, sizeof(keyData)); for (int i = 0; i < kResourceCnt; ++i) { - TestResource* resource; - keyData.fData32[0] = i; + GrContentKey key1, key2; + make_content_key<1>(&key1, i); + make_content_key<2>(&key2, i); + + TestResource* resource; - GrResourceKey key0(GrCacheID(domain0, keyData), 0); resource = SkNEW_ARGS(TestResource, (context->getGpu())); - resource->cacheAccess().setContentKey(key0); + resource->cacheAccess().setContentKey(key1); resource->setSize(1); resource->unref(); - GrResourceKey key1(GrCacheID(domain1, keyData), 0); resource = SkNEW_ARGS(TestResource, (context->getGpu())); - resource->cacheAccess().setContentKey(key1); + resource->cacheAccess().setContentKey(key2); resource->setSize(1); resource->unref(); } @@ -861,11 +840,12 @@ static void test_large_resource_count(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, cache2->getResourceBytes() == 2 * kResourceCnt); REPORTER_ASSERT(reporter, cache2->getResourceCount() == 2 * kResourceCnt); for (int i = 0; i < kResourceCnt; ++i) { - keyData.fData32[0] = i; - GrResourceKey key0(GrCacheID(domain0, keyData), 0); - REPORTER_ASSERT(reporter, cache2->hasContentKey(key0)); - GrResourceKey key1(GrCacheID(domain0, keyData), 0); + GrContentKey key1, key2; + make_content_key<1>(&key1, i); + make_content_key<2>(&key2, i); + REPORTER_ASSERT(reporter, cache2->hasContentKey(key1)); + REPORTER_ASSERT(reporter, cache2->hasContentKey(key2)); } cache2->purgeAllUnlocked(); @@ -876,11 +856,12 @@ static void test_large_resource_count(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, cache2->getResourceCount() == 0); for (int i = 0; i < kResourceCnt; ++i) { - keyData.fData32[0] = i; - GrResourceKey key0(GrCacheID(domain0, keyData), 0); - REPORTER_ASSERT(reporter, !cache2->hasContentKey(key0)); - GrResourceKey key1(GrCacheID(domain0, keyData), 0); + GrContentKey key1, key2; + make_content_key<1>(&key1, i); + make_content_key<2>(&key2, i); + REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1)); + REPORTER_ASSERT(reporter, !cache2->hasContentKey(key2)); } }