Add specialized content key class for resources.
Review URL: https://codereview.chromium.org/858123002
This commit is contained in:
parent
f98f2bb0e7
commit
24db3b1c35
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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',
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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*);
|
||||||
|
@ -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, ¶ms);
|
*blurProfileTexture = context->findAndRefTexture(texDesc, key, ¶ms);
|
||||||
|
|
||||||
if (NULL == *blurProfileTexture) {
|
if (NULL == *blurProfileTexture) {
|
||||||
|
|
||||||
SkBlurMask::ComputeBlurProfile(sigma, &profile);
|
SkBlurMask::ComputeBlurProfile(sigma, &profile);
|
||||||
ada.reset(profile);
|
ada.reset(profile);
|
||||||
|
|
||||||
*blurProfileTexture = context->createTexture(¶ms, texDesc, blurProfileKey,
|
*blurProfileTexture = context->createTexture(¶ms, 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, ¶ms);
|
GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, key, ¶ms);
|
||||||
|
|
||||||
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(¶ms, texDesc, blurRRectNinePatchID, blurred_mask.fImage, 0);
|
blurNinePatchTexture = context->createTexture(¶ms, texDesc, key, blurred_mask.fImage, 0);
|
||||||
SkMask::FreeImage(blurred_mask.fImage);
|
SkMask::FreeImage(blurred_mask.fImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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?
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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, ¶ms);
|
fTexture = fDesc.fContext->findAndRefTexture(texDesc, key, ¶ms);
|
||||||
if (NULL == fTexture) {
|
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 is a new texture, so all of our cache info is now invalid
|
||||||
this->initLRU();
|
this->initLRU();
|
||||||
fKeyTable.rewind();
|
fKeyTable.rewind();
|
||||||
|
@ -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, ¶ms));
|
SkAutoTUnref<GrTexture> texture(context->findAndRefTexture(texDesc, key, ¶ms));
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
texture.reset(context->createTexture(¶ms, texDesc, cacheId, 0, 0));
|
texture.reset(context->createTexture(¶ms, 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;
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user