Make textures register with GrResourceCache2 as scratch.

R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/510053003
This commit is contained in:
bsalomon 2014-08-28 09:54:34 -07:00 committed by Commit bot
parent 7e7136f47d
commit 744998e666
13 changed files with 249 additions and 161 deletions

View File

@ -9,6 +9,7 @@
'variables': {
'skgpu_sources': [
'<(skia_include_path)/gpu/GrBackendEffectFactory.h',
'<(skia_include_path)/gpu/GrBinHashKey.h',
'<(skia_include_path)/gpu/GrClipData.h',
'<(skia_include_path)/gpu/GrColor.h',
'<(skia_include_path)/gpu/GrConfig.h',
@ -25,6 +26,7 @@
'<(skia_include_path)/gpu/GrPathRendererChain.h',
'<(skia_include_path)/gpu/GrRect.h',
'<(skia_include_path)/gpu/GrRenderTarget.h',
'<(skia_include_path)/gpu/GrResourceKey.h',
'<(skia_include_path)/gpu/GrSurface.h',
'<(skia_include_path)/gpu/GrTBackendEffectFactory.h',
'<(skia_include_path)/gpu/GrTexture.h',
@ -50,7 +52,6 @@
'<(skia_src_path)/gpu/GrAllocPool.cpp',
'<(skia_src_path)/gpu/GrAtlas.cpp',
'<(skia_src_path)/gpu/GrAtlas.h',
'<(skia_src_path)/gpu/GrBinHashKey.h',
'<(skia_src_path)/gpu/GrBitmapTextContext.cpp',
'<(skia_src_path)/gpu/GrBitmapTextContext.h',
'<(skia_src_path)/gpu/GrBlend.cpp',
@ -87,6 +88,7 @@
'<(skia_src_path)/gpu/GrLayerCache.h',
'<(skia_src_path)/gpu/GrMemoryPool.cpp',
'<(skia_src_path)/gpu/GrMemoryPool.h',
'<(skia_src_path)/gpu/GrMurmur3HashKey.h',
'<(skia_src_path)/gpu/GrOrderedSet.h',
'<(skia_src_path)/gpu/GrOvalRenderer.cpp',
'<(skia_src_path)/gpu/GrOvalRenderer.h',

View File

@ -10,66 +10,8 @@
#ifndef GrBinHashKey_DEFINED
#define GrBinHashKey_DEFINED
#include "SkChecksum.h"
#include "GrTypes.h"
/**
* GrMurmur3HashKey is a hash key class that can take a data chunk of any predetermined
* length. It uses the Murmur3 hash function. It is intended to be used with
* SkTDynamicHash (where GrBinHashKey is for GrTHashTable).
*/
template<size_t KEY_SIZE_IN_BYTES>
class GrMurmur3HashKey {
public:
GrMurmur3HashKey() {
this->reset();
}
void reset() {
fHash = 0;
#ifdef SK_DEBUG
fIsValid = false;
#endif
}
void setKeyData(const uint32_t* data) {
SK_COMPILE_ASSERT(KEY_SIZE_IN_BYTES % 4 == 0, key_size_mismatch);
memcpy(fData, data, KEY_SIZE_IN_BYTES);
fHash = SkChecksum::Murmur3(fData, KEY_SIZE_IN_BYTES);
#ifdef SK_DEBUG
fIsValid = true;
#endif
}
bool operator==(const GrMurmur3HashKey& other) const {
if (fHash != other.fHash) {
return false;
}
return !memcmp(fData, other.fData, KEY_SIZE_IN_BYTES);
}
uint32_t getHash() const {
SkASSERT(fIsValid);
return fHash;
}
const uint8_t* getData() const {
SkASSERT(fIsValid);
return reinterpret_cast<const uint8_t*>(fData);
}
private:
uint32_t fHash;
uint32_t fData[KEY_SIZE_IN_BYTES / sizeof(uint32_t)]; // Buffer for key storage.
#ifdef SK_DEBUG
public:
bool fIsValid;
#endif
};
/**
* GrBinHashKey is a hash key class that can take a data chunk of any predetermined
* length. The hash function used is the One-at-a-Time Hash

View File

@ -10,6 +10,7 @@
#include "SkInstCnt.h"
#include "SkTInternalLList.h"
#include "GrResourceKey.h"
class GrResourceCacheEntry;
class GrResourceCache2;
@ -82,6 +83,12 @@ public:
void setCacheEntry(GrResourceCacheEntry* cacheEntry) { fCacheEntry = cacheEntry; }
GrResourceCacheEntry* getCacheEntry() { return fCacheEntry; }
/**
* If this resource can be used as a scratch resource this returns a valid
* scratch key. Otherwise it returns a key for which isNullScratch is true.
*/
const GrResourceKey& getScratchKey() const { return fScratchKey; }
/**
* Gets an id that is unique for this GrCacheable object. It is static in that it does
* not change when the content of the GrCacheable object changes. This will never return
@ -90,7 +97,6 @@ public:
uint32_t getUniqueID() const { return fUniqueID; }
protected:
// This must be called by every GrGpuObject. It should be called once the object is fully
// initialized (i.e. not in a base class constructor).
void registerWithCache();
@ -117,6 +123,12 @@ protected:
*/
void didChangeGpuMemorySize() const;
/**
* Optionally called by the GrGpuResource subclass if the resource can be used as scratch.
* By default resources are not usable as scratch. This should only be called once.
**/
void setScratchKey(const GrResourceKey& scratchKey);
private:
#ifdef SK_DEBUG
friend class GrGpu; // for assert in GrGpu to access getGpu
@ -146,6 +158,8 @@ private:
GrResourceCacheEntry* fCacheEntry; // NULL if not in cache
const uint32_t fUniqueID;
GrResourceKey fScratchKey;
typedef SkNoncopyable INHERITED;
};

113
include/gpu/GrResourceKey.h Normal file
View File

@ -0,0 +1,113 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrResourceKey_DEFINED
#define GrResourceKey_DEFINED
#include "GrTypes.h"
#include "GrBinHashKey.h"
class GrResourceKey {
public:
static GrCacheID::Domain ScratchDomain() {
static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain();
return gDomain;
}
/** Uniquely identifies the GrGpuResource subclass in the key to avoid collisions
across resource types. */
typedef uint8_t ResourceType;
/** Flags set by the GrGpuResource subclass. */
typedef uint8_t ResourceFlags;
/** Generate a unique ResourceType */
static ResourceType GenerateResourceType();
/** Creates a key for resource */
GrResourceKey(const GrCacheID& id, ResourceType type, ResourceFlags flags) {
this->init(id.getDomain(), id.getKey(), type, flags);
};
GrResourceKey(const GrResourceKey& src) { fKey = src.fKey; }
GrResourceKey() { fKey.reset(); }
void reset(const GrCacheID& id, ResourceType type, ResourceFlags flags) {
this->init(id.getDomain(), id.getKey(), type, flags);
}
uint32_t getHash() const { return fKey.getHash(); }
bool isScratch() const {
return ScratchDomain() ==
*reinterpret_cast<const GrCacheID::Domain*>(fKey.getData() +
kCacheIDDomainOffset);
}
ResourceType getResourceType() const {
return *reinterpret_cast<const ResourceType*>(fKey.getData() +
kResourceTypeOffset);
}
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() {
static const GrCacheID::Key kBogusKey = { { {0} } };
static GrCacheID kBogusID(ScratchDomain(), kBogusKey);
static GrResourceKey kNullScratchKey(kBogusID, NoneResourceType(), 0);
return kNullScratchKey;
}
bool isNullScratch() const {
return this->isScratch() && NoneResourceType() == this->getResourceType();
}
private:
enum {
kCacheIDKeyOffset = 0,
kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key),
kResourceTypeOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain),
kResourceFlagsOffset = kResourceTypeOffset + sizeof(ResourceType),
kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags),
kKeySize = SkAlign4(kPadOffset),
kPadSize = kKeySize - kPadOffset
};
static ResourceType NoneResourceType() {
static const ResourceType gNoneResourceType = GenerateResourceType();
return gNoneResourceType;
}
void init(const GrCacheID::Domain domain,
const GrCacheID::Key& key,
ResourceType type,
ResourceFlags flags) {
union {
uint8_t fKey8[kKeySize];
uint32_t fKey32[kKeySize / 4];
} keyData;
uint8_t* k = keyData.fKey8;
memcpy(k + kCacheIDKeyOffset, key.fData8, sizeof(GrCacheID::Key));
memcpy(k + kCacheIDDomainOffset, &domain, sizeof(GrCacheID::Domain));
memcpy(k + kResourceTypeOffset, &type, sizeof(ResourceType));
memcpy(k + kResourceFlagsOffset, &flags, sizeof(ResourceFlags));
memset(k + kPadOffset, 0, kPadSize);
fKey.setKeyData(keyData.fKey32);
}
GrBinHashKey<kKeySize> fKey;
};
#endif

View File

@ -163,10 +163,7 @@ public:
static bool NeedsBilerp(const GrResourceKey& key);
protected:
GrTextureImpl(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
: INHERITED(gpu, isWrapped, desc)
, fMipMapsStatus(kNotAllocated_MipMapsStatus) {
}
GrTextureImpl(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc);
private:
enum MipMapsStatus {

View File

@ -22,7 +22,8 @@ GrGpuResource::GrGpuResource(GrGpu* gpu, bool isWrapped)
: fGpu(gpu)
, fRefCnt(1)
, fCacheEntry(NULL)
, fUniqueID(CreateUniqueID()) {
, fUniqueID(CreateUniqueID())
, fScratchKey(GrResourceKey::NullScratchKey()) {
if (isWrapped) {
fFlags = kWrapped_FlagBit;
} else {
@ -72,6 +73,13 @@ GrContext* GrGpuResource::getContext() {
}
}
void GrGpuResource::setScratchKey(const GrResourceKey& scratchKey) {
SkASSERT(fScratchKey.isNullScratch());
SkASSERT(scratchKey.isScratch());
SkASSERT(!scratchKey.isNullScratch());
fScratchKey = scratchKey;
}
uint32_t GrGpuResource::CreateUniqueID() {
static int32_t gUniqueID = SK_InvalidUniqueID;
uint32_t id;

View File

@ -0,0 +1,73 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrMurmur3HashKey_DEFINED
#define GrMurmur3HashKey_DEFINED
#include "SkChecksum.h"
#include "GrTypes.h"
/**
* GrMurmur3HashKey is a hash key class that can take a data chunk of any predetermined
* length. It uses the Murmur3 hash function. It is intended to be used with
* SkTDynamicHash (where GrBinHashKey is for GrTHashTable).
*/
template<size_t KEY_SIZE_IN_BYTES>
class GrMurmur3HashKey {
public:
GrMurmur3HashKey() {
this->reset();
}
void reset() {
fHash = 0;
#ifdef SK_DEBUG
fIsValid = false;
#endif
}
void setKeyData(const uint32_t* data) {
SK_COMPILE_ASSERT(KEY_SIZE_IN_BYTES % 4 == 0, key_size_mismatch);
memcpy(fData, data, KEY_SIZE_IN_BYTES);
fHash = SkChecksum::Murmur3(fData, KEY_SIZE_IN_BYTES);
#ifdef SK_DEBUG
fIsValid = true;
#endif
}
bool operator==(const GrMurmur3HashKey& other) const {
if (fHash != other.fHash) {
return false;
}
return !memcmp(fData, other.fData, KEY_SIZE_IN_BYTES);
}
uint32_t getHash() const {
SkASSERT(fIsValid);
return fHash;
}
const uint8_t* getData() const {
SkASSERT(fIsValid);
return reinterpret_cast<const uint8_t*>(fData);
}
private:
uint32_t fHash;
uint32_t fData[KEY_SIZE_IN_BYTES / sizeof(uint32_t)]; // Buffer for key storage.
#ifdef SK_DEBUG
public:
bool fIsValid;
#endif
};
#endif

View File

@ -11,10 +11,8 @@
#ifndef GrResourceCache_DEFINED
#define GrResourceCache_DEFINED
#include "GrConfig.h"
#include "GrTypes.h"
#include "GrResourceKey.h"
#include "SkTMultiMap.h"
#include "GrBinHashKey.h"
#include "SkMessageBus.h"
#include "SkTInternalLList.h"
@ -22,92 +20,6 @@ class GrGpuResource;
class GrResourceCache;
class GrResourceCacheEntry;
class GrResourceKey {
public:
static GrCacheID::Domain ScratchDomain() {
static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain();
return gDomain;
}
/** Uniquely identifies the GrGpuResource subclass in the key to avoid collisions
across resource types. */
typedef uint8_t ResourceType;
/** Flags set by the GrGpuResource subclass. */
typedef uint8_t ResourceFlags;
/** Generate a unique ResourceType */
static ResourceType GenerateResourceType();
/** Creates a key for resource */
GrResourceKey(const GrCacheID& id, ResourceType type, ResourceFlags flags) {
this->init(id.getDomain(), id.getKey(), type, flags);
};
GrResourceKey(const GrResourceKey& src) {
fKey = src.fKey;
}
GrResourceKey() {
fKey.reset();
}
void reset(const GrCacheID& id, ResourceType type, ResourceFlags flags) {
this->init(id.getDomain(), id.getKey(), type, flags);
}
uint32_t getHash() const {
return fKey.getHash();
}
bool isScratch() const {
return ScratchDomain() ==
*reinterpret_cast<const GrCacheID::Domain*>(fKey.getData() +
kCacheIDDomainOffset);
}
ResourceType getResourceType() const {
return *reinterpret_cast<const ResourceType*>(fKey.getData() +
kResourceTypeOffset);
}
ResourceFlags getResourceFlags() const {
return *reinterpret_cast<const ResourceFlags*>(fKey.getData() +
kResourceFlagsOffset);
}
bool operator==(const GrResourceKey& other) const { return fKey == other.fKey; }
private:
enum {
kCacheIDKeyOffset = 0,
kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key),
kResourceTypeOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain),
kResourceFlagsOffset = kResourceTypeOffset + sizeof(ResourceType),
kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags),
kKeySize = SkAlign4(kPadOffset),
kPadSize = kKeySize - kPadOffset
};
void init(const GrCacheID::Domain domain,
const GrCacheID::Key& key,
ResourceType type,
ResourceFlags flags) {
union {
uint8_t fKey8[kKeySize];
uint32_t fKey32[kKeySize / 4];
} keyData;
uint8_t* k = keyData.fKey8;
memcpy(k + kCacheIDKeyOffset, key.fData8, sizeof(GrCacheID::Key));
memcpy(k + kCacheIDDomainOffset, &domain, sizeof(GrCacheID::Domain));
memcpy(k + kResourceTypeOffset, &type, sizeof(ResourceType));
memcpy(k + kResourceFlagsOffset, &flags, sizeof(ResourceFlags));
memset(k + kPadOffset, 0, kPadSize);
fKey.setKeyData(keyData.fKey32);
}
GrBinHashKey<kKeySize> fKey;
};
// The cache listens for these messages to purge junk resources proactively.
struct GrResourceInvalidatedMessage {

View File

@ -20,11 +20,17 @@ void GrResourceCache2::insertResource(GrGpuResource* resource) {
SkASSERT(!this->isInCache(resource));
fResources.addToHead(resource);
++fCount;
if (!resource->getScratchKey().isNullScratch()) {
fScratchMap.insert(resource->getScratchKey(), resource);
}
}
void GrResourceCache2::removeResource(GrGpuResource* resource) {
SkASSERT(this->isInCache(resource));
fResources.remove(resource);
fResources.remove(resource);
if (!resource->getScratchKey().isNullScratch()) {
fScratchMap.remove(resource->getScratchKey(), resource);
}
--fCount;
}
@ -35,6 +41,7 @@ void GrResourceCache2::abandonAll() {
// abandon should have already removed this from the list.
SkASSERT(head != fResources.head());
}
SkASSERT(!fScratchMap.count());
SkASSERT(!fCount);
}
@ -45,5 +52,6 @@ void GrResourceCache2::releaseAll() {
// release should have already removed this from the list.
SkASSERT(head != fResources.head());
}
SkASSERT(!fScratchMap.count());
SkASSERT(!fCount);
}

View File

@ -9,10 +9,10 @@
#ifndef GrResourceCache2_DEFINED
#define GrResourceCache2_DEFINED
#include "GrTypes.h"
#include "GrGpuResource.h"
#include "GrResourceKey.h"
#include "SkTInternalLList.h"
class GrGpuResource;
#include "SkTMultiMap.h"
/**
* Eventual replacement for GrResourceCache. Currently it simply holds a list
@ -39,8 +39,21 @@ private:
}
#endif
int fCount;
SkTInternalLList<GrGpuResource> fResources;
void removeScratch(const GrGpuResource* resource);
struct ScratchMapTraits {
static const GrResourceKey& GetKey(const GrGpuResource& r) {
return r.getScratchKey();
}
static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); }
};
typedef SkTMultiMap<GrGpuResource, GrResourceKey, ScratchMapTraits> ScratchMap;
int fCount;
SkTInternalLList<GrGpuResource> fResources;
// This map holds all resources that can be used as scratch resources.
ScratchMap fScratchMap;
};
#endif

View File

@ -207,6 +207,11 @@ GrSurfaceOrigin resolve_origin(const GrTextureDesc& desc) {
}
//////////////////////////////////////////////////////////////////////////////
GrTextureImpl::GrTextureImpl(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
: INHERITED(gpu, isWrapped, desc)
, fMipMapsStatus(kNotAllocated_MipMapsStatus) {
this->setScratchKey(ComputeScratchKey(desc));
}
GrResourceKey GrTextureImpl::ComputeKey(const GrGpu* gpu,
const GrTextureParams* params,

View File

@ -8,7 +8,7 @@
#ifndef GrTextureStripAtlas_DEFINED
#define GrTextureStripAtlas_DEFINED
#include "GrBinHashKey.h"
#include "GrMurmur3HashKey.h"
#include "SkBitmap.h"
#include "SkGr.h"
#include "SkTDArray.h"

View File

@ -8,6 +8,7 @@
// This is a GPU-backend specific test
#if SK_SUPPORT_GPU
#include "GrMurmur3HashKey.h"
#include "GrBinHashKey.h"
#include "Test.h"