Add specialized content key class for resources.

Review URL: https://codereview.chromium.org/858123002
This commit is contained in:
bsalomon 2015-01-23 04:24:04 -08:00 committed by Commit bot
parent f98f2bb0e7
commit 24db3b1c35
26 changed files with 457 additions and 520 deletions

View File

@ -28,15 +28,12 @@ public:
this->registerWithCache(); this->registerWithCache();
} }
static GrResourceKey ComputeKey(int i) { static void ComputeKey(int i, GrContentKey* key) {
GrCacheID::Key key; static GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
memset(&key, 0, sizeof(key)); GrContentKey::Builder builder(key, kDomain, 1);
key.fData32[0] = i; builder[0] = i;
static int gDomain = GrCacheID::GenerateDomain();
return GrResourceKey(GrCacheID(gDomain, key), 0);
} }
private: private:
size_t onGpuMemorySize() const SK_OVERRIDE { return 100; } size_t onGpuMemorySize() const SK_OVERRIDE { return 100; }
@ -45,7 +42,8 @@ private:
static void populate_cache(GrGpu* gpu, int resourceCount) { static void populate_cache(GrGpu* gpu, int resourceCount) {
for (int i = 0; i < resourceCount; ++i) { for (int i = 0; i < resourceCount; ++i) {
GrResourceKey key = BenchResource::ComputeKey(i); GrContentKey key;
BenchResource::ComputeKey(i, &key);
GrGpuResource* resource = SkNEW_ARGS(BenchResource, (gpu)); GrGpuResource* resource = SkNEW_ARGS(BenchResource, (gpu));
resource->cacheAccess().setContentKey(key); resource->cacheAccess().setContentKey(key);
resource->unref(); resource->unref();
@ -127,7 +125,8 @@ protected:
SkASSERT(CACHE_SIZE_COUNT == cache2->getResourceCount()); SkASSERT(CACHE_SIZE_COUNT == cache2->getResourceCount());
for (int i = 0; i < loops; ++i) { for (int i = 0; i < loops; ++i) {
for (int k = 0; k < CACHE_SIZE_COUNT; ++k) { for (int k = 0; k < CACHE_SIZE_COUNT; ++k) {
GrResourceKey key = BenchResource::ComputeKey(k); GrContentKey key;
BenchResource::ComputeKey(k, &key);
SkAutoTUnref<GrGpuResource> resource(cache2->findAndRefContentResource(key)); SkAutoTUnref<GrGpuResource> resource(cache2->findAndRefContentResource(key));
SkASSERT(resource); SkASSERT(resource);
} }

View File

@ -62,7 +62,6 @@
'<(skia_src_path)/gpu/GrBlend.h', '<(skia_src_path)/gpu/GrBlend.h',
'<(skia_src_path)/gpu/GrBufferAllocPool.cpp', '<(skia_src_path)/gpu/GrBufferAllocPool.cpp',
'<(skia_src_path)/gpu/GrBufferAllocPool.h', '<(skia_src_path)/gpu/GrBufferAllocPool.h',
'<(skia_src_path)/gpu/GrCacheID.cpp',
'<(skia_src_path)/gpu/GrClipData.cpp', '<(skia_src_path)/gpu/GrClipData.cpp',
'<(skia_src_path)/gpu/GrClipMaskCache.h', '<(skia_src_path)/gpu/GrClipMaskCache.h',
'<(skia_src_path)/gpu/GrClipMaskCache.cpp', '<(skia_src_path)/gpu/GrClipMaskCache.cpp',

View File

@ -172,14 +172,14 @@ public:
/** /**
* Stores a custom resource in the cache, based on the specified key. * 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 * 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 * conjunction with addResourceToCache(). The return value will be NULL if not found. The
* caller must balance with a call to unref(). * 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 * 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 * 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. * 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 * @param params The texture params used to draw a texture may help determine
* the cache entry used. (e.g. different versions may exist * the cache entry used. (e.g. different versions may exist
* for different wrap modes on GPUs with limited NPOT * for different wrap modes on GPUs with limited NPOT
* texture support). NULL implies clamp wrap modes. * texture support). NULL implies clamp wrap modes.
* @param desc Description of the texture properties. * @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 srcData Pointer to the pixel values.
* @param rowBytes The number of bytes between rows of the texture. Zero * @param rowBytes The number of bytes between rows of the texture. Zero
* implies tightly packed rows. For compressed pixel configs, this * implies tightly packed rows. For compressed pixel configs, this
* field is ignored. * 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, GrTexture* createTexture(const GrTextureParams* params,
const GrSurfaceDesc& desc, const GrSurfaceDesc& desc,
const GrCacheID& cacheID, const GrContentKey& key,
const void* srcData, const void* srcData,
size_t rowBytes, 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 * 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. * 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 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 * @param params The texture params used to draw a texture may help determine
* the cache entry used. (e.g. different versions may exist * the cache entry used. (e.g. different versions may exist
* for different wrap modes on GPUs with limited NPOT * for different wrap modes on GPUs with limited NPOT
* texture support). NULL implies clamp wrap modes. * texture support). NULL implies clamp wrap modes.
*/ */
GrTexture* findAndRefTexture(const GrSurfaceDesc& desc, GrTexture* findAndRefTexture(const GrSurfaceDesc& desc,
const GrCacheID& cacheID, const GrContentKey& key,
const GrTextureParams* params); const GrTextureParams* params);
/** /**
* Determines whether a texture is in the cache. If the texture is found it * 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 * will not be locked or returned. This call does not affect the priority of
* the texture for deletion. * the texture for deletion.
*
* TODO: Remove this function and do cache checks generically.
*/ */
bool isTextureInCache(const GrSurfaceDesc& desc, bool isTextureInCache(const GrSurfaceDesc& desc,
const GrCacheID& cacheID, const GrContentKey& key,
const GrTextureParams* params) const; const GrTextureParams* params) const;
/** /**
@ -871,8 +879,9 @@ private:
const SkPath&, const SkPath&,
const GrStrokeInfo&); const GrStrokeInfo&);
GrTexture* createResizedTexture(const GrSurfaceDesc& desc, // TODO: Move this out of GrContext.
const GrCacheID& cacheID, GrTexture* createResizedTexture(const GrSurfaceDesc&,
const GrContentKey& origKey,
const void* srcData, const void* srcData,
size_t rowBytes, size_t rowBytes,
bool filter); bool filter);

View File

@ -259,7 +259,7 @@ private:
virtual size_t onGpuMemorySize() const = 0; virtual size_t onGpuMemorySize() const = 0;
// See comments in CacheAccess. // See comments in CacheAccess.
bool setContentKey(const GrResourceKey& contentKey); bool setContentKey(const GrContentKey& contentKey);
void notifyIsPurgable() const; void notifyIsPurgable() const;
void removeScratchKey(); void removeScratchKey();
void makeBudgeted(); void makeBudgeted();
@ -275,27 +275,18 @@ private:
static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0); static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
enum Flags { GrScratchKey fScratchKey;
/** GrContentKey fContentKey;
* 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;
// This is not ref'ed but abandon() or release() will be called before the GrGpu object // 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. // is destroyed. Those calls set will this to NULL.
GrGpu* fGpu; GrGpu* fGpu;
mutable size_t fGpuMemorySize; mutable size_t fGpuMemorySize;
uint32_t fFlags; LifeCycle fLifeCycle;
LifeCycle fLifeCycle; const uint32_t fUniqueID;
const uint32_t fUniqueID;
SkAutoTUnref<const SkData> fData; SkAutoTUnref<const SkData> fData;
typedef GrIORef<GrGpuResource> INHERITED; typedef GrIORef<GrGpuResource> INHERITED;
friend class GrIORef<GrGpuResource>; // to access notifyIsPurgable. friend class GrIORef<GrGpuResource>; // to access notifyIsPurgable.

View File

@ -13,149 +13,212 @@
#include "SkTemplates.h" #include "SkTemplates.h"
#include "GrBinHashKey.h" #include "GrBinHashKey.h"
/** uint32_t GrResourceKeyHash(const uint32_t* data, size_t size);
* 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();
GrScratchKey() { this->reset(); } class GrResourceKey {
GrScratchKey(const GrScratchKey& that) { *this = that; } 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. */ /** Reset to an invalid key. */
void reset() { void reset() {
GR_STATIC_ASSERT((uint16_t)kInvalidDomain == kInvalidDomain);
fKey.reset(kMetaDataCnt); fKey.reset(kMetaDataCnt);
fKey[kHash_MetaDataIdx] = 0; 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; } GrResourceKey& operator=(const GrResourceKey& that) {
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) {
size_t bytes = that.size(); size_t bytes = that.size();
SkASSERT(SkIsAlign4(bytes));
fKey.reset(SkToInt(bytes / sizeof(uint32_t))); fKey.reset(SkToInt(bytes / sizeof(uint32_t)));
memcpy(fKey.get(), that.fKey.get(), bytes); memcpy(fKey.get(), that.fKey.get(), bytes);
return *this; return *this;
} }
bool operator==(const GrScratchKey& that) const { bool isValid() const { return kInvalidDomain != this->domain(); }
return 0 == memcmp(fKey.get(), that.fKey.get(), this->size());
}
bool operator!=(const GrScratchKey& that) const { return !(*this == that); }
/** Used to initialize scratch key. */ uint32_t domain() const { return fKey[kDomainAndSize_MetaDataIdx] & 0xffff; }
/** Used to initialize a key. */
class Builder { class Builder {
public: public:
Builder(GrScratchKey* key, ResourceType type, int data32Count) : fKey(key) { Builder(GrResourceKey* key, uint32_t domain, int data32Count) : fKey(key) {
SkASSERT(data32Count >= 0); SkASSERT(data32Count >= 0);
SkASSERT(type != kInvalidResourceType); SkASSERT(domain != kInvalidDomain);
key->fKey.reset(kMetaDataCnt + data32Count); key->fKey.reset(kMetaDataCnt + data32Count);
SkASSERT(type <= SK_MaxU16);
int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t); int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t);
SkASSERT(size <= SK_MaxU16); SkASSERT(SkToU16(size) == size);
key->fKey[kTypeAndSize_MetaDataIdx] = type | (size << 16); SkASSERT(SkToU16(domain) == domain);
key->fKey[kDomainAndSize_MetaDataIdx] = domain | (size << 16);
} }
~Builder() { this->finish(); } ~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) { uint32_t& operator[](int dataIdx) {
SkASSERT(fKey); 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); SkASSERT(SkToU32(dataIdx) < dataCount);
return fKey->fKey[kMetaDataCnt + dataIdx]; return fKey->fKey[kMetaDataCnt + dataIdx];
} }
private: private:
GrScratchKey* fKey; GrResourceKey* fKey;
}; };
private: 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 { enum MetaDataIdx {
kHash_MetaDataIdx, kHash_MetaDataIdx,
// The resource type and size are packed into a single uint32_t. // The key domain and size are packed into a single uint32_t.
kTypeAndSize_MetaDataIdx, kDomainAndSize_MetaDataIdx,
kLastMetaDataIdx = kTypeAndSize_MetaDataIdx kLastMetaDataIdx = kDomainAndSize_MetaDataIdx
}; };
static const uint32_t kInvalidResourceType = 0;
static const uint32_t kMetaDataCnt = kLastMetaDataIdx + 1; static const uint32_t kMetaDataCnt = kLastMetaDataIdx + 1;
friend class TestResource; // For unit test to access kMetaDataCnt. friend class TestResource; // For unit test to access kMetaDataCnt.
// Stencil and textures each require 2 uint32_t values. // bmp textures require 4 uint32_t values.
SkAutoSTArray<kMetaDataCnt + 2, uint32_t> fKey; SkAutoSTArray<kMetaDataCnt + 4, uint32_t> fKey;
}; };
class GrResourceKey { /**
public: * A key used for scratch resources. The key consists of a resource type (subclass) identifier, a
/** Flags set by the GrGpuResource subclass. */ * hash, a data length, and type-specific data. A Builder object is used to initialize the
typedef uint8_t ResourceFlags; * key contents. The contents must be initialized before the key can be used.
*/
/** Creates a key for resource */ class GrScratchKey : public GrResourceKey {
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<const ResourceFlags*>(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();
private: private:
enum { typedef GrResourceKey INHERITED;
kCacheIDKeyOffset = 0,
kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key),
kResourceFlagsOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain),
kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags),
kKeySize = SkAlign4(kPadOffset),
kPadSize = kKeySize - kPadOffset
};
void init(const GrCacheID::Domain domain, const GrCacheID::Key& key, ResourceFlags flags) { public:
union { /** Uniquely identifies the type of resource that is cached as scratch. */
uint8_t fKey8[kKeySize]; typedef uint32_t ResourceType;
uint32_t fKey32[kKeySize / 4];
} keyData;
uint8_t* k = keyData.fKey8; /** Generate a unique ResourceType. */
memcpy(k + kCacheIDKeyOffset, key.fData8, sizeof(GrCacheID::Key)); static ResourceType GenerateResourceType();
memcpy(k + kCacheIDDomainOffset, &domain, sizeof(GrCacheID::Domain));
memcpy(k + kResourceFlagsOffset, &flags, sizeof(ResourceFlags)); /** Creates an invalid scratch key. It must be initialized using a Builder object before use. */
memset(k + kPadOffset, 0, kPadSize); GrScratchKey() {}
fKey.setKeyData(keyData.fKey32);
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<kKeySize> 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 #endif

View File

@ -13,7 +13,6 @@
#include "SkPoint.h" #include "SkPoint.h"
#include "SkRefCnt.h" #include "SkRefCnt.h"
class GrResourceKey;
class GrTextureParams; class GrTextureParams;
class GrTexturePriv; class GrTexturePriv;

View File

@ -472,58 +472,6 @@ struct GrSurfaceDesc {
// Legacy alias // Legacy alias
typedef GrSurfaceDesc GrTextureDesc; 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. * Clips are composed from these objects.
*/ */

View File

@ -70,7 +70,7 @@ static inline GrColor SkColor2GrColorJustAlpha(SkColor c) {
// The cache listens for these messages to purge junk resources proactively. // The cache listens for these messages to purge junk resources proactively.
struct GrResourceInvalidatedMessage { struct GrResourceInvalidatedMessage {
GrResourceKey key; GrContentKey fKey;
}; };
bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*); bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*);

View File

@ -753,31 +753,29 @@ bool GrRectBlurEffect::CreateBlurProfileTexture(GrContext *context, float sigma,
GrTextureParams params; GrTextureParams params;
GrSurfaceDesc texDesc; 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.fHeight = 1;
texDesc.fConfig = kAlpha_8_GrPixelConfig; texDesc.fConfig = kAlpha_8_GrPixelConfig;
static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomain(); static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
GrCacheID::Key key; GrContentKey key;
memset(&key, 0, sizeof(key)); GrContentKey::Builder builder(&key, kDomain, 1);
key.fData32[0] = profile_size; builder[0] = profileSize;
key.fData32[1] = 1; builder.finish();
GrCacheID blurProfileKey(gBlurProfileDomain, key);
uint8_t *profile = NULL; uint8_t *profile = NULL;
SkAutoTDeleteArray<uint8_t> ada(NULL); SkAutoTDeleteArray<uint8_t> ada(NULL);
*blurProfileTexture = context->findAndRefTexture(texDesc, blurProfileKey, &params); *blurProfileTexture = context->findAndRefTexture(texDesc, key, &params);
if (NULL == *blurProfileTexture) { if (NULL == *blurProfileTexture) {
SkBlurMask::ComputeBlurProfile(sigma, &profile); SkBlurMask::ComputeBlurProfile(sigma, &profile);
ada.reset(profile); ada.reset(profile);
*blurProfileTexture = context->createTexture(&params, texDesc, blurProfileKey, *blurProfileTexture = context->createTexture(&params, texDesc, key, profile, 0);
profile, 0);
if (NULL == *blurProfileTexture) { if (NULL == *blurProfileTexture) {
return false; return false;
@ -920,12 +918,12 @@ GrFragmentProcessor* GrRRectBlurEffect::Create(GrContext* context, float sigma,
return NULL; return NULL;
} }
static const GrCacheID::Domain gRRectBlurDomain = GrCacheID::GenerateDomain(); static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
GrCacheID::Key key; GrContentKey key;
memset(&key, 0, sizeof(key)); GrContentKey::Builder builder(&key, kDomain, 2);
key.fData32[0] = blurRadius; builder[0] = blurRadius;
key.fData32[1] = cornerRadius; builder[1] = cornerRadius;
GrCacheID blurRRectNinePatchID(gRRectBlurDomain, key); builder.finish();
GrTextureParams params; GrTextureParams params;
params.setFilterMode(GrTextureParams::kBilerp_FilterMode); params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
@ -937,7 +935,7 @@ GrFragmentProcessor* GrRRectBlurEffect::Create(GrContext* context, float sigma,
texDesc.fHeight = texSide; texDesc.fHeight = texSide;
texDesc.fConfig = kAlpha_8_GrPixelConfig; texDesc.fConfig = kAlpha_8_GrPixelConfig;
GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, blurRRectNinePatchID, &params); GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, key, &params);
if (NULL == blurNinePatchTexture) { if (NULL == blurNinePatchTexture) {
SkMask mask; SkMask mask;
@ -964,7 +962,7 @@ GrFragmentProcessor* GrRRectBlurEffect::Create(GrContext* context, float sigma,
SkMask blurred_mask; SkMask blurred_mask;
SkBlurMask::BoxBlur(&blurred_mask, mask, sigma, kNormal_SkBlurStyle, kHigh_SkBlurQuality, NULL, true ); SkBlurMask::BoxBlur(&blurred_mask, mask, sigma, kNormal_SkBlurStyle, kHigh_SkBlurQuality, NULL, true );
blurNinePatchTexture = context->createTexture(&params, texDesc, blurRRectNinePatchID, blurred_mask.fImage, 0); blurNinePatchTexture = context->createTexture(&params, texDesc, key, blurred_mask.fImage, 0);
SkMask::FreeImage(blurred_mask.fImage); SkMask::FreeImage(blurred_mask.fImage);
} }

View File

@ -342,26 +342,24 @@ void GrColorCubeEffect::GLProcessor::GenKey(const GrProcessor& proc,
} }
GrFragmentProcessor* SkColorCubeFilter::asFragmentProcessor(GrContext* context) const { GrFragmentProcessor* SkColorCubeFilter::asFragmentProcessor(GrContext* context) const {
static const GrCacheID::Domain gCubeDomain = GrCacheID::GenerateDomain(); static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
GrContentKey key;
GrCacheID::Key key; GrContentKey::Builder builder(&key, kDomain, 2);
key.fData32[0] = fUniqueID; builder[0] = fUniqueID;
key.fData32[1] = fCache.cubeDimension(); builder[1] = fCache.cubeDimension();
key.fData64[1] = 0; builder.finish();
GrCacheID cacheID(gCubeDomain, key);
GrSurfaceDesc desc; GrSurfaceDesc desc;
desc.fWidth = fCache.cubeDimension(); desc.fWidth = fCache.cubeDimension();
desc.fHeight = fCache.cubeDimension() * fCache.cubeDimension(); desc.fHeight = fCache.cubeDimension() * fCache.cubeDimension();
desc.fConfig = kRGBA_8888_GrPixelConfig; desc.fConfig = kRGBA_8888_GrPixelConfig;
GrResourceKey rkey = GrTexturePriv::ComputeKey(context->getGpu(), NULL, desc, cacheID); GrSurface* surface = static_cast<GrSurface*>(context->findAndRefCachedResource(key));
GrSurface* surface = static_cast<GrSurface*>(context->findAndRefCachedResource(rkey));
SkAutoTUnref<GrTexture> textureCube; SkAutoTUnref<GrTexture> textureCube;
if (surface) { if (surface) {
textureCube.reset(surface->asTexture()); textureCube.reset(surface->asTexture());
} else { } 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; return textureCube ? GrColorCubeEffect::Create(textureCube) : NULL;

View File

@ -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>(domain);
}

View File

@ -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<GrSurface*>(resource)->asTexture());
return static_cast<GrSurface*>(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, static void stretch_image(void* dst,
int dstW, int dstW,
int dstH, 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 desired texture is NPOT and tiled but that isn't supported by
// the current hardware. Resize the texture to be a POT // the current hardware. Resize the texture to be a POT
GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc, GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc,
const GrCacheID& cacheID, const GrContentKey& origKey,
const void* srcData, const void* srcData,
size_t rowBytes, size_t rowBytes,
bool filter) { bool filter) {
SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, cacheID, NULL)); SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, origKey, NULL));
if (NULL == clampedTexture) { if (NULL == clampedTexture) {
clampedTexture.reset(this->createTexture(NULL, desc, cacheID, srcData, rowBytes)); clampedTexture.reset(this->createTexture(NULL, desc, origKey, srcData, rowBytes));
if (NULL == clampedTexture) { if (NULL == clampedTexture) {
return NULL; return NULL;
} }
clampedTexture->cacheAccess().setContentKey(origKey);
} }
GrSurfaceDesc rtDesc = desc; 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[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(SkPoint));
verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint)); verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint));
fDrawBuffer->drawNonIndexed(&pipelineBuilder, gp, kTriangleFan_GrPrimitiveType, 0, 4); fDrawBuffer->drawNonIndexed(&pipelineBuilder, gp, kTriangleFan_GrPrimitiveType, 0, 4);
} else {
texture->unref();
texture = NULL;
} }
} else { } else {
// TODO: Our CPU stretch doesn't filter. But we create separate // TODO: Our CPU stretch doesn't filter. But we create separate
@ -347,30 +364,39 @@ GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc,
return texture; return texture;
} }
static GrContentKey::Domain ResizeDomain() {
static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
return kDomain;
}
GrTexture* GrContext::createTexture(const GrTextureParams* params, GrTexture* GrContext::createTexture(const GrTextureParams* params,
const GrSurfaceDesc& desc, const GrSurfaceDesc& desc,
const GrCacheID& cacheID, const GrContentKey& origKey,
const void* srcData, const void* srcData,
size_t rowBytes, size_t rowBytes,
GrResourceKey* cacheKey) { GrContentKey* outKey) {
GrResourceKey resourceKey = GrTexturePriv::ComputeKey(fGpu, params, desc, cacheID);
GrTexture* texture; GrTexture* texture;
if (GrTexturePriv::NeedsResizing(resourceKey)) { uint32_t flags = get_texture_flags(fGpu, params, desc);
// We do not know how to resize compressed textures. SkTCopyOnFirstWrite<GrContentKey> key(origKey);
SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); 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 { } else {
texture = fGpu->createTexture(desc, true, srcData, rowBytes); texture = fGpu->createTexture(desc, true, srcData, rowBytes);
} }
if (texture) { if (texture) {
if (texture->cacheAccess().setContentKey(resourceKey)) { if (texture->cacheAccess().setContentKey(*key)) {
if (cacheKey) { if (outKey) {
*cacheKey = resourceKey; *outKey = *key;
} }
} else { } else {
texture->unref(); texture->unref();
@ -381,6 +407,37 @@ GrTexture* GrContext::createTexture(const GrTextureParams* params,
return texture; return texture;
} }
GrTexture* GrContext::findAndRefTexture(const GrSurfaceDesc& desc,
const GrContentKey& origKey,
const GrTextureParams* params) {
uint32_t flags = get_texture_flags(fGpu, params, desc);
SkTCopyOnFirstWrite<GrContentKey> 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<GrSurface*>(resource)->asTexture());
return static_cast<GrSurface*>(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<GrContentKey> 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, GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexMatch match,
bool calledDuringFlush) { bool calledDuringFlush) {
// kNoStencil has no meaning if kRT isn't set. // 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) { void GrContext::addResourceToCache(const GrContentKey& key, GrGpuResource* resource) {
resource->cacheAccess().setContentKey(resourceKey); resource->cacheAccess().setContentKey(key);
} }
GrGpuResource* GrContext::findAndRefCachedResource(const GrResourceKey& resourceKey) { GrGpuResource* GrContext::findAndRefCachedResource(const GrContentKey& key) {
return fResourceCache2->findAndRefContentResource(resourceKey); return fResourceCache2->findAndRefContentResource(key);
} }
void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {

View File

@ -20,7 +20,6 @@ static inline GrResourceCache2* get_resource_cache2(GrGpu* gpu) {
GrGpuResource::GrGpuResource(GrGpu* gpu, LifeCycle lifeCycle) GrGpuResource::GrGpuResource(GrGpu* gpu, LifeCycle lifeCycle)
: fGpu(gpu) : fGpu(gpu)
, fGpuMemorySize(kInvalidGpuMemorySize) , fGpuMemorySize(kInvalidGpuMemorySize)
, fFlags(0)
, fLifeCycle(lifeCycle) , fLifeCycle(lifeCycle)
, fUniqueID(CreateUniqueID()) { , fUniqueID(CreateUniqueID()) {
} }
@ -83,7 +82,7 @@ void GrGpuResource::didChangeGpuMemorySize() const {
get_resource_cache2(fGpu)->resourceAccess().didChangeGpuMemorySize(this, oldSize); 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. // Currently this can only be called once and can't be called when the resource is scratch.
SkASSERT(this->internalHasRef()); SkASSERT(this->internalHasRef());
@ -92,15 +91,14 @@ bool GrGpuResource::setContentKey(const GrResourceKey& contentKey) {
return false; return false;
} }
if ((fFlags & kContentKeySet_Flag) || this->wasDestroyed()) { if (fContentKey.isValid() || this->wasDestroyed()) {
return false; return false;
} }
fContentKey = contentKey; fContentKey = key;
fFlags |= kContentKeySet_Flag;
if (!get_resource_cache2(fGpu)->resourceAccess().didSetContentKey(this)) { if (!get_resource_cache2(fGpu)->resourceAccess().didSetContentKey(this)) {
fFlags &= ~kContentKeySet_Flag; fContentKey.reset();
return false; return false;
} }
return true; return true;

View File

@ -24,7 +24,7 @@ public:
* resource that currently is using the content key, allow resources' content keys to change, * 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. * 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); return fResource->setContentKey(contentKey);
} }
@ -33,7 +33,7 @@ public:
* not have a content key. * not have a content key.
*/ */
bool isScratch() const { 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. * If the resource is currently cached by a content key, the key is returned, otherwise NULL.
*/ */
const GrResourceKey* getContentKey() const { const GrContentKey& getContentKey() const { return fResource->fContentKey; }
if (fResource->fFlags & GrGpuResource::kContentKeySet_Flag) {
return &fResource->fContentKey;
}
return NULL;
}
/** /**
* Is the resource object wrapping an externally allocated GPU resource? * Is the resource object wrapping an externally allocated GPU resource?

View File

@ -13,15 +13,11 @@ template<int NumBits> static uint64_t get_top_n_float_bits(float f) {
return floatBits >> (32 - NumBits); return floatBits >> (32 - NumBits);
} }
GrResourceKey GrPath::ComputeKey(const SkPath& path, const SkStrokeRec& stroke) { void GrPath::ComputeKey(const SkPath& path, const SkStrokeRec& stroke, GrContentKey* key) {
static const GrCacheID::Domain gPathDomain = GrCacheID::GenerateDomain(); static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
GrContentKey::Builder builder(key, kDomain, 3);
GrCacheID::Key key; *reinterpret_cast<uint64_t*>(&builder[0]) = ComputeStrokeKey(stroke);
uint64_t* keyData = key.fData64; builder[2] = path.getGenerationID();
keyData[0] = path.getGenerationID();
keyData[1] = ComputeStrokeKey(stroke);
return GrResourceKey(GrCacheID(gPathDomain, key), 0);
} }
uint64_t GrPath::ComputeStrokeKey(const SkStrokeRec& stroke) { uint64_t GrPath::ComputeStrokeKey(const SkStrokeRec& stroke) {

View File

@ -27,7 +27,7 @@ public:
fBounds(skPath.getBounds()) { 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&); static uint64_t ComputeStrokeKey(const SkStrokeRec&);
bool isEqualTo(const SkPath& path, const SkStrokeRec& stroke) { bool isEqualTo(const SkPath& path, const SkStrokeRec& stroke) {

View File

@ -19,7 +19,7 @@ DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() { GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() {
static int32_t gType = kInvalidResourceType + 1; static int32_t gType = INHERITED::kInvalidDomain + 1;
int32_t type = sk_atomic_inc(&gType); int32_t type = sk_atomic_inc(&gType);
if (type > SK_MaxU16) { if (type > SK_MaxU16) {
@ -29,15 +29,18 @@ GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() {
return static_cast<ResourceType>(type); return static_cast<ResourceType>(type);
} }
GrContentKey::Domain GrContentKey::GenerateDomain() {
static int32_t gDomain = INHERITED::kInvalidDomain + 1;
void GrScratchKey::Builder::finish() { int32_t domain = sk_atomic_inc(&gDomain);
if (NULL == fKey) { if (kInvalidDomain == gDomain) {
return; SkFAIL("Too many Content Key Domains");
} }
GR_STATIC_ASSERT(0 == kHash_MetaDataIdx);
fKey->fKey[kHash_MetaDataIdx] = return static_cast<Domain>(domain);
SkChecksum::Compute(&fKey->fKey[kHash_MetaDataIdx + 1], fKey->size() - sizeof(uint32_t)); }
fKey = NULL; 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()) { if (resource->cacheAccess().getScratchKey().isValid()) {
fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource); fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
} }
if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) { if (resource->cacheAccess().getContentKey().isValid()) {
fContentHash.remove(*contentKey); fContentHash.remove(resource->cacheAccess().getContentKey());
} }
this->validate(); this->validate();
} }
@ -222,9 +225,9 @@ bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
SkASSERT(!fPurging); SkASSERT(!fPurging);
SkASSERT(resource); SkASSERT(resource);
SkASSERT(this->isInCache(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) { if (NULL != res) {
return false; return false;
} }
@ -258,8 +261,8 @@ void GrResourceCache2::notifyPurgable(GrGpuResource* resource) {
bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes; bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
// Also purge if the resource has neither a valid scratch key nor a content key. // Also purge if the resource has neither a valid scratch key nor a content key.
bool noKey = !resource->cacheAccess().isScratch() && bool noKey = !resource->cacheAccess().getScratchKey().isValid() &&
(NULL == resource->cacheAccess().getContentKey()); !resource->cacheAccess().getContentKey().isValid();
// Only cached resources should ever have a key. // Only cached resources should ever have a key.
SkASSERT(noKey || resource->cacheAccess().isBudgeted()); SkASSERT(noKey || resource->cacheAccess().isBudgeted());
@ -406,20 +409,20 @@ void GrResourceCache2::validate() const {
} }
if (resource->cacheAccess().isScratch()) { if (resource->cacheAccess().isScratch()) {
SkASSERT(NULL == resource->cacheAccess().getContentKey()); SkASSERT(!resource->cacheAccess().getContentKey().isValid());
++scratch; ++scratch;
SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey())); SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
SkASSERT(!resource->cacheAccess().isWrapped()); SkASSERT(!resource->cacheAccess().isWrapped());
} else if (resource->cacheAccess().getScratchKey().isValid()) { } else if (resource->cacheAccess().getScratchKey().isValid()) {
SkASSERT(NULL != resource->cacheAccess().getContentKey()); SkASSERT(resource->cacheAccess().getContentKey().isValid());
++couldBeScratch; ++couldBeScratch;
SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey())); SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
SkASSERT(!resource->cacheAccess().isWrapped()); SkASSERT(!resource->cacheAccess().isWrapped());
} }
const GrContentKey& contentKey = resource->cacheAccess().getContentKey();
if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) { if (contentKey.isValid()) {
++content; ++content;
SkASSERT(fContentHash.find(*contentKey) == resource); SkASSERT(fContentHash.find(contentKey) == resource);
SkASSERT(!resource->cacheAccess().isWrapped()); SkASSERT(!resource->cacheAccess().isWrapped());
} }

View File

@ -110,7 +110,7 @@ public:
/** /**
* Find a resource that matches a content key. * Find a resource that matches a content key.
*/ */
GrGpuResource* findAndRefContentResource(const GrResourceKey& contentKey) { GrGpuResource* findAndRefContentResource(const GrContentKey& contentKey) {
GrGpuResource* resource = fContentHash.find(contentKey); GrGpuResource* resource = fContentHash.find(contentKey);
if (resource) { if (resource) {
resource->ref(); resource->ref();
@ -122,7 +122,7 @@ public:
/** /**
* Query whether a content key exists in the cache. * 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)); return SkToBool(fContentHash.find(contentKey));
} }
@ -193,13 +193,13 @@ private:
typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMap; typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMap;
struct ContentHashTraits { struct ContentHashTraits {
static const GrResourceKey& GetKey(const GrGpuResource& r) { static const GrContentKey& GetKey(const GrGpuResource& r) {
return *r.cacheAccess().getContentKey(); 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<GrGpuResource, GrResourceKey, ContentHashTraits> ContentHash; typedef SkTDynamicHash<GrGpuResource, GrContentKey, ContentHashTraits> ContentHash;
typedef SkTInternalLList<GrGpuResource> ResourceList; typedef SkTInternalLList<GrGpuResource> ResourceList;

View File

@ -72,11 +72,12 @@ GrStencilAndCoverPathRenderer::onGetStencilSupport(const GrDrawTarget*,
static GrPath* get_gr_path(GrGpu* gpu, const SkPath& skPath, const SkStrokeRec& stroke) { static GrPath* get_gr_path(GrGpu* gpu, const SkPath& skPath, const SkStrokeRec& stroke) {
GrContext* ctx = gpu->getContext(); GrContext* ctx = gpu->getContext();
GrResourceKey resourceKey = GrPath::ComputeKey(skPath, stroke); GrContentKey key;
SkAutoTUnref<GrPath> path(static_cast<GrPath*>(ctx->findAndRefCachedResource(resourceKey))); GrPath::ComputeKey(skPath, stroke, &key);
SkAutoTUnref<GrPath> path(static_cast<GrPath*>(ctx->findAndRefCachedResource(key)));
if (NULL == path || !path->isEqualTo(skPath, stroke)) { if (NULL == path || !path->isEqualTo(skPath, stroke)) {
path.reset(gpu->pathRendering()->createPath(skPath, stroke)); path.reset(gpu->pathRendering()->createPath(skPath, stroke));
ctx->addResourceToCache(resourceKey, path); ctx->addResourceToCache(key, path);
} }
return path.detach(); return path.detach();
} }

View File

@ -205,20 +205,25 @@ static GrPathRange* get_gr_glyphs(GrContext* ctx,
const SkTypeface* typeface, const SkTypeface* typeface,
const SkDescriptor* desc, const SkDescriptor* desc,
const SkStrokeRec& stroke) { const SkStrokeRec& stroke) {
static const GrCacheID::Domain gGlyphsDomain = GrCacheID::GenerateDomain(); static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
GrContentKey key;
GrCacheID::Key key; GrContentKey::Builder builder(&key, kDomain, 4);
uint64_t* keyData = key.fData64; struct GlyphKey {
keyData[0] = desc ? desc->getChecksum() : 0; uint32_t fChecksum;
keyData[0] = (keyData[0] << 32) | (typeface ? typeface->uniqueID() : 0); uint32_t fTypeface;
keyData[1] = GrPath::ComputeStrokeKey(stroke); uint64_t fStroke;
GrResourceKey resourceKey = GrResourceKey(GrCacheID(gGlyphsDomain, key), 0); };
GlyphKey* glyphKey = reinterpret_cast<GlyphKey*>(&builder[0]);
glyphKey->fChecksum = desc ? desc->getChecksum() : 0;
glyphKey->fTypeface = typeface ? typeface->uniqueID() : 0;
glyphKey->fStroke = GrPath::ComputeStrokeKey(stroke);
builder.finish();
SkAutoTUnref<GrPathRange> glyphs( SkAutoTUnref<GrPathRange> glyphs(
static_cast<GrPathRange*>(ctx->findAndRefCachedResource(resourceKey))); static_cast<GrPathRange*>(ctx->findAndRefCachedResource(key)));
if (NULL == glyphs || (NULL != desc && !glyphs->isEqualTo(*desc))) { if (NULL == glyphs || (NULL != desc && !glyphs->isEqualTo(*desc))) {
glyphs.reset(ctx->getGpu()->pathRendering()->createGlyphs(typeface, desc, stroke)); glyphs.reset(ctx->getGpu()->pathRendering()->createGlyphs(typeface, desc, stroke));
ctx->addResourceToCache(resourceKey, glyphs); ctx->addResourceToCache(key, glyphs);
} }
return glyphs.detach(); return glyphs.detach();

View File

@ -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 { 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. // FIXME: This should be refactored with the code in gl/GrGLGpu.cpp.
GrSurfaceOrigin resolve_origin(const GrSurfaceDesc& desc) { GrSurfaceOrigin resolve_origin(const GrSurfaceDesc& desc) {
@ -132,14 +97,6 @@ GrTexture::GrTexture(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc)
fShiftFixedY = 31 - SkCLZ(fDesc.fHeight); 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) { void GrTexturePriv::ComputeScratchKey(const GrSurfaceDesc& desc, GrScratchKey* key) {
static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType(); 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[0] = desc.fWidth | (desc.fHeight << 16);
builder[1] = desc.fConfig | (desc.fSampleCnt << 6) | (flags << 14) | (origin << 24); 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);
}

View File

@ -39,14 +39,7 @@ public:
return GrTexture::kNotAllocated_MipMapsStatus != fTexture->fMipMapsStatus; 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 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. // TODO: Move this logic and the shift values out of here and to the callers.
SkFixed normalizeFixedX(SkFixed x) const { SkFixed normalizeFixedX(SkFixed x) const {

View File

@ -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() // Our id includes the offset, width, and height so that bitmaps created by extractSubset()
// are unique. // are unique.
uint32_t genID = bitmap.getGenerationID(); uint32_t genID = bitmap.getGenerationID();
SkIPoint origin = bitmap.pixelRefOrigin(); SkIPoint origin = bitmap.pixelRefOrigin();
int16_t width = SkToS16(bitmap.width()); uint32_t width = SkToU16(bitmap.width());
int16_t height = SkToS16(bitmap.height()); uint32_t height = SkToU16(bitmap.height());
GrCacheID::Key key; static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
memcpy(key.fData8 + 0, &genID, 4); GrContentKey::Builder builder(key, kDomain, 4);
memcpy(key.fData8 + 4, &origin.fX, 4); builder[0] = genID;
memcpy(key.fData8 + 8, &origin.fY, 4); builder[1] = origin.fX;
memcpy(key.fData8 + 12, &width, 2); builder[2] = origin.fY;
memcpy(key.fData8 + 14, &height, 2); builder[3] = width | (height << 16);
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 void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrSurfaceDesc* desc) { 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. // When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
class GrResourceInvalidator : public SkPixelRef::GenIDChangeListener { class GrResourceInvalidator : public SkPixelRef::GenIDChangeListener {
public: public:
explicit GrResourceInvalidator(GrResourceKey key) : fKey(key) {} explicit GrResourceInvalidator(const GrContentKey& key) : fKey(key) {}
private: private:
GrResourceKey fKey; GrContentKey fKey;
void onChange() SK_OVERRIDE { void onChange() SK_OVERRIDE {
const GrResourceInvalidatedMessage message = { fKey }; const GrResourceInvalidatedMessage message = { fKey };
@ -132,7 +127,7 @@ private:
} // namespace } // namespace
static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) { static void add_genID_listener(const GrContentKey& key, SkPixelRef* pixelRef) {
SkASSERT(pixelRef); SkASSERT(pixelRef);
pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key))); pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key)));
} }
@ -147,11 +142,10 @@ static GrTexture* sk_gr_allocate_texture(GrContext* ctx,
GrTexture* result; GrTexture* result;
if (cache) { if (cache) {
// This texture is likely to be used again so leave it in the cache // This texture is likely to be used again so leave it in the cache
GrCacheID cacheID; GrContentKey key;
generate_bitmap_cache_id(bm, &cacheID); generate_bitmap_key(bm, &key);
GrResourceKey key; result = ctx->createTexture(params, desc, key, pixels, rowBytes, &key);
result = ctx->createTexture(params, desc, cacheID, pixels, rowBytes, &key);
if (result) { if (result) {
add_genID_listener(key, bm.pixelRef()); add_genID_listener(key, bm.pixelRef());
} }
@ -399,12 +393,12 @@ bool GrIsBitmapInCache(const GrContext* ctx,
return true; return true;
} }
GrCacheID cacheID; GrContentKey key;
generate_bitmap_cache_id(bitmap, &cacheID); generate_bitmap_key(bitmap, &key);
GrSurfaceDesc desc; GrSurfaceDesc desc;
generate_bitmap_texture_desc(bitmap, &desc); generate_bitmap_texture_desc(bitmap, &desc);
return ctx->isTextureInCache(desc, cacheID, params); return ctx->isTextureInCache(desc, key, params);
} }
GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
@ -420,13 +414,13 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
if (cache) { if (cache) {
// If the bitmap isn't changing try to find a cached copy first. // If the bitmap isn't changing try to find a cached copy first.
GrCacheID cacheID; GrContentKey key;
generate_bitmap_cache_id(bitmap, &cacheID); generate_bitmap_key(bitmap, &key);
GrSurfaceDesc desc; GrSurfaceDesc desc;
generate_bitmap_texture_desc(bitmap, &desc); generate_bitmap_texture_desc(bitmap, &desc);
result = ctx->findAndRefTexture(desc, cacheID, params); result = ctx->findAndRefTexture(desc, key, params);
} }
if (NULL == result) { if (NULL == result) {
result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap); result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap);

View File

@ -196,15 +196,15 @@ void GrTextureStripAtlas::lockTexture() {
texDesc.fHeight = fDesc.fHeight; texDesc.fHeight = fDesc.fHeight;
texDesc.fConfig = fDesc.fConfig; texDesc.fConfig = fDesc.fConfig;
static const GrCacheID::Domain gTextureStripAtlasDomain = GrCacheID::GenerateDomain(); static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
GrCacheID::Key key; GrContentKey key;
*key.fData32 = fCacheKey; GrContentKey::Builder builder(&key, kDomain, 1);
memset(key.fData32 + 1, 0, sizeof(key) - sizeof(uint32_t)); builder[0] = static_cast<uint32_t>(fCacheKey);
GrCacheID cacheID(gTextureStripAtlasDomain, key); builder.finish();
fTexture = fDesc.fContext->findAndRefTexture(texDesc, cacheID, &params); fTexture = fDesc.fContext->findAndRefTexture(texDesc, key, &params);
if (NULL == fTexture) { if (NULL == fTexture) {
fTexture = fDesc.fContext->createTexture(&params, texDesc, cacheID, NULL, 0); fTexture = fDesc.fContext->createTexture(&params, texDesc, key, NULL, 0);
// This is a new texture, so all of our cache info is now invalid // This is a new texture, so all of our cache info is now invalid
this->initLRU(); this->initLRU();
fKeyTable.rewind(); fKeyTable.rewind();

View File

@ -98,9 +98,7 @@ GrFragmentProcessor* BigKeyProcessor::TestCreate(SkRandom*,
static const int kRenderTargetHeight = 1; static const int kRenderTargetHeight = 1;
static const int kRenderTargetWidth = 1; static const int kRenderTargetWidth = 1;
static GrRenderTarget* random_render_target(GrContext* context, static GrRenderTarget* random_render_target(GrContext* context, SkRandom* random) {
const GrCacheID& cacheId,
SkRandom* random) {
// setup render target // setup render target
GrTextureParams params; GrTextureParams params;
GrSurfaceDesc texDesc; GrSurfaceDesc texDesc;
@ -110,10 +108,15 @@ static GrRenderTarget* random_render_target(GrContext* context,
texDesc.fConfig = kRGBA_8888_GrPixelConfig; texDesc.fConfig = kRGBA_8888_GrPixelConfig;
texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin : texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin :
kBottomLeft_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<GrTexture> texture(context->findAndRefTexture(texDesc, cacheId, &params)); SkAutoTUnref<GrTexture> texture(context->findAndRefTexture(texDesc, key, &params));
if (!texture) { if (!texture) {
texture.reset(context->createTexture(&params, texDesc, cacheId, 0, 0)); texture.reset(context->createTexture(&params, texDesc, key, 0, 0));
if (!texture) { if (!texture) {
return NULL; return NULL;
} }
@ -237,14 +240,6 @@ bool GrDrawTarget::programUnitTest(int maxStages) {
// dummy scissor state // dummy scissor state
GrScissorState scissor; 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 // setup clip
SkRect screen = SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), SkRect screen = SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth),
SkIntToScalar(kRenderTargetHeight)); SkIntToScalar(kRenderTargetHeight));
@ -261,7 +256,7 @@ bool GrDrawTarget::programUnitTest(int maxStages) {
static const int NUM_TESTS = 512; static const int NUM_TESTS = 512;
for (int t = 0; t < NUM_TESTS;) { for (int t = 0; t < NUM_TESTS;) {
// setup random render target(can fail) // setup random render target(can fail)
SkAutoTUnref<GrRenderTarget> rt(random_render_target(fContext, glProgramsCacheID, &random)); SkAutoTUnref<GrRenderTarget> rt(random_render_target(fContext, &random));
if (!rt.get()) { if (!rt.get()) {
SkDebugf("Could not allocate render target"); SkDebugf("Could not allocate render target");
return false; return false;

View File

@ -120,8 +120,8 @@ public:
static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) { static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) {
static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType(); static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType();
GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt); GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt);
for (size_t i = 0; i < kScratchKeyFieldCnt; ++i) { for (int i = 0; i < kScratchKeyFieldCnt; ++i) {
builder[i] = i + static_cast<int>(property); builder[i] = static_cast<uint32_t>(i + property);
} }
} }
@ -130,7 +130,7 @@ public:
} }
private: private:
static const size_t kScratchKeyFieldCnt = 6; static const int kScratchKeyFieldCnt = 6;
TestResource(GrGpu* gpu, SimulatedProperty property, ScratchConstructor) TestResource(GrGpu* gpu, SimulatedProperty property, ScratchConstructor)
: INHERITED(gpu, kCached_LifeCycle) : INHERITED(gpu, kCached_LifeCycle)
@ -209,6 +209,13 @@ static void test_no_key(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes()); REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
} }
// Each integer passed as a template param creates a new domain.
template <int> 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) { static void test_budgeting(skiatest::Reporter* reporter) {
SkAutoTUnref<GrContext> context(GrContext::CreateMockContext()); SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
REPORTER_ASSERT(reporter, SkToBool(context)); 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->getResourceCount() && 0 == cache2->getResourceBytes());
SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes()); SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes());
GrCacheID::Key keyData; GrContentKey contentKey;
memset(&keyData, 0, sizeof(keyData)); make_content_key<0>(&contentKey, 0);
GrResourceKey contentKey(GrCacheID(GrCacheID::GenerateDomain(), keyData), 0);
// Create a scratch, a content, and a wrapped resource // Create a scratch, a content, and a wrapped resource
TestResource* scratch = TestResource* scratch =
@ -241,8 +247,8 @@ static void test_budgeting(skiatest::Reporter* reporter) {
unbudgeted->setSize(13); unbudgeted->setSize(13);
// Make sure we can't add a content key to the wrapped resource // Make sure we can't add a content key to the wrapped resource
keyData.fData8[0] = 1; GrContentKey contentKey2;
GrResourceKey contentKey2(GrCacheID(GrCacheID::GenerateDomain(), keyData), 0); make_content_key<0>(&contentKey2, 1);
REPORTER_ASSERT(reporter, !wrapped->cacheAccess().setContentKey(contentKey2)); REPORTER_ASSERT(reporter, !wrapped->cacheAccess().setContentKey(contentKey2));
REPORTER_ASSERT(reporter, NULL == cache2->findAndRefContentResource(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->getResourceCount() && 0 == cache2->getResourceBytes());
SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes()); SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes());
GrCacheID::Key keyData; GrContentKey contentKey;
memset(&keyData, 0, sizeof(keyData)); make_content_key<0>(&contentKey, 0);
GrResourceKey contentKey(GrCacheID(GrCacheID::GenerateDomain(), keyData), 0);
TestResource* scratch; TestResource* scratch;
TestResource* content; TestResource* content;
@ -576,10 +581,8 @@ static void test_duplicate_content_key(skiatest::Reporter* reporter) {
cache2->purgeAllUnlocked(); cache2->purgeAllUnlocked();
SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
GrCacheID::Domain domain = GrCacheID::GenerateDomain(); GrContentKey key;
GrCacheID::Key keyData; make_content_key<0>(&key, 0);
memset(&keyData, 0, sizeof(keyData));
GrResourceKey key(GrCacheID(domain, keyData), 0);
// Create two resources that we will attempt to register with the same content key. // Create two resources that we will attempt to register with the same content key.
TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu())); TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
@ -627,16 +630,10 @@ static void test_purge_invalidated(skiatest::Reporter* reporter) {
return; return;
} }
GrCacheID::Domain domain = GrCacheID::GenerateDomain(); GrContentKey key1, key2, key3;
GrCacheID::Key keyData; make_content_key<0>(&key1, 1);
memset(&keyData, 0, sizeof(keyData)); make_content_key<0>(&key2, 2);
make_content_key<0>(&key3, 3);
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);
context->setResourceCacheLimits(5, 30000); context->setResourceCacheLimits(5, 30000);
GrResourceCache2* cache2 = context->getResourceCache2(); GrResourceCache2* cache2 = context->getResourceCache2();
@ -694,15 +691,9 @@ static void test_cache_chained_purge(skiatest::Reporter* reporter) {
return; return;
} }
GrCacheID::Domain domain = GrCacheID::GenerateDomain(); GrContentKey key1, key2;
GrCacheID::Key keyData; make_content_key<0>(&key1, 1);
memset(&keyData, 0, sizeof(keyData)); make_content_key<0>(&key2, 2);
keyData.fData64[0] = 1;
GrResourceKey key1(GrCacheID(domain, keyData), 0);
keyData.fData64[0] = 2;
GrResourceKey key2(GrCacheID(domain, keyData), 0);
{ {
context->setResourceCacheLimits(3, 30000); context->setResourceCacheLimits(3, 30000);
@ -745,17 +736,9 @@ static void test_resource_size_changed(skiatest::Reporter* reporter) {
return; return;
} }
GrCacheID::Domain domain = GrCacheID::GenerateDomain(); GrContentKey key1, key2;
make_content_key<0>(&key1, 1);
GrCacheID::Key key1Data; make_content_key<0>(&key2, 2);
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);
// Test changing resources sizes (both increase & decrease). // Test changing resources sizes (both increase & decrease).
{ {
@ -832,25 +815,21 @@ static void test_large_resource_count(skiatest::Reporter* reporter) {
cache2->purgeAllUnlocked(); cache2->purgeAllUnlocked();
SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); 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) { for (int i = 0; i < kResourceCnt; ++i) {
TestResource* resource; GrContentKey key1, key2;
keyData.fData32[0] = i; 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 = SkNEW_ARGS(TestResource, (context->getGpu()));
resource->cacheAccess().setContentKey(key0); resource->cacheAccess().setContentKey(key1);
resource->setSize(1); resource->setSize(1);
resource->unref(); resource->unref();
GrResourceKey key1(GrCacheID(domain1, keyData), 0);
resource = SkNEW_ARGS(TestResource, (context->getGpu())); resource = SkNEW_ARGS(TestResource, (context->getGpu()));
resource->cacheAccess().setContentKey(key1); resource->cacheAccess().setContentKey(key2);
resource->setSize(1); resource->setSize(1);
resource->unref(); 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->getResourceBytes() == 2 * kResourceCnt);
REPORTER_ASSERT(reporter, cache2->getResourceCount() == 2 * kResourceCnt); REPORTER_ASSERT(reporter, cache2->getResourceCount() == 2 * kResourceCnt);
for (int i = 0; i < kResourceCnt; ++i) { for (int i = 0; i < kResourceCnt; ++i) {
keyData.fData32[0] = i; GrContentKey key1, key2;
GrResourceKey key0(GrCacheID(domain0, keyData), 0); make_content_key<1>(&key1, i);
REPORTER_ASSERT(reporter, cache2->hasContentKey(key0)); make_content_key<2>(&key2, i);
GrResourceKey key1(GrCacheID(domain0, keyData), 0);
REPORTER_ASSERT(reporter, cache2->hasContentKey(key1)); REPORTER_ASSERT(reporter, cache2->hasContentKey(key1));
REPORTER_ASSERT(reporter, cache2->hasContentKey(key2));
} }
cache2->purgeAllUnlocked(); cache2->purgeAllUnlocked();
@ -876,11 +856,12 @@ static void test_large_resource_count(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, cache2->getResourceCount() == 0); REPORTER_ASSERT(reporter, cache2->getResourceCount() == 0);
for (int i = 0; i < kResourceCnt; ++i) { for (int i = 0; i < kResourceCnt; ++i) {
keyData.fData32[0] = i; GrContentKey key1, key2;
GrResourceKey key0(GrCacheID(domain0, keyData), 0); make_content_key<1>(&key1, i);
REPORTER_ASSERT(reporter, !cache2->hasContentKey(key0)); make_content_key<2>(&key2, i);
GrResourceKey key1(GrCacheID(domain0, keyData), 0);
REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1)); REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
REPORTER_ASSERT(reporter, !cache2->hasContentKey(key2));
} }
} }