Make GrTextureCache into a generic GrResource cache. Also some GrContext texture interface cleanup.
http://codereview.appspot.com/4815055/ git-svn-id: http://skia.googlecode.com/svn/trunk@1965 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
f131694617
commit
50398bf7f1
@ -18,16 +18,18 @@
|
|||||||
#define GrContext_DEFINED
|
#define GrContext_DEFINED
|
||||||
|
|
||||||
#include "GrClip.h"
|
#include "GrClip.h"
|
||||||
#include "GrTextureCache.h"
|
|
||||||
#include "GrPaint.h"
|
#include "GrPaint.h"
|
||||||
#include "GrPathRenderer.h"
|
#include "GrPathRenderer.h"
|
||||||
|
|
||||||
class GrFontCache;
|
class GrFontCache;
|
||||||
class GrGpu;
|
class GrGpu;
|
||||||
struct GrGpuStats;
|
struct GrGpuStats;
|
||||||
class GrVertexBufferAllocPool;
|
|
||||||
class GrIndexBufferAllocPool;
|
class GrIndexBufferAllocPool;
|
||||||
class GrInOrderDrawBuffer;
|
class GrInOrderDrawBuffer;
|
||||||
|
class GrResourceEntry;
|
||||||
|
class GrResourceCache;
|
||||||
|
class GrVertexBufferAllocPool;
|
||||||
|
|
||||||
|
|
||||||
class GR_API GrContext : public GrRefCnt {
|
class GR_API GrContext : public GrRefCnt {
|
||||||
public:
|
public:
|
||||||
@ -82,54 +84,92 @@ public:
|
|||||||
// Textures
|
// Textures
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for an entry with the same Key. If found, "lock" it and return it.
|
* Token that refers to an entry in the texture cache. Returned by
|
||||||
* If not found, return null.
|
* functions that lock textures. Passed to unlockTexture.
|
||||||
*/
|
*/
|
||||||
GrTextureEntry* findAndLockTexture(GrTextureKey*,
|
class TextureCacheEntry {
|
||||||
const GrSamplerState&);
|
public:
|
||||||
|
TextureCacheEntry() : fEntry(NULL) {}
|
||||||
|
TextureCacheEntry(const TextureCacheEntry& e) : fEntry(e.fEntry) {}
|
||||||
|
TextureCacheEntry& operator= (const TextureCacheEntry& e) {
|
||||||
|
fEntry = e.fEntry;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
GrTexture* texture() const;
|
||||||
|
void reset() { fEntry = NULL; }
|
||||||
|
private:
|
||||||
|
explicit TextureCacheEntry(GrResourceEntry* entry) { fEntry = entry; }
|
||||||
|
void set(GrResourceEntry* entry) { fEntry = entry; }
|
||||||
|
GrResourceEntry* cacheEntry() { return fEntry; }
|
||||||
|
GrResourceEntry* fEntry;
|
||||||
|
friend class GrContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key generated by client. Should be a unique key on the texture data.
|
||||||
|
* Does not need to consider that width and height of the texture. Two
|
||||||
|
* textures with the same TextureKey but different bounds will not collide.
|
||||||
|
*/
|
||||||
|
typedef uint64_t TextureKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for an entry based on key and dimensions. If found, "lock" it and
|
||||||
|
* return it. The entry's texture() function will return NULL if not found.
|
||||||
|
* Must call be balanced with an unlockTexture() call.
|
||||||
|
*/
|
||||||
|
TextureCacheEntry findAndLockTexture(TextureKey key,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
const GrSamplerState&);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new entry, based on the specified key and texture, and return
|
* Create a new entry, based on the specified key and texture, and return
|
||||||
* its "locked" entry.
|
* its "locked" entry. Must call be balanced with an unlockTexture() call.
|
||||||
*
|
|
||||||
* Ownership of the texture is transferred to the Entry, which will unref()
|
|
||||||
* it when we are purged or deleted.
|
|
||||||
*/
|
*/
|
||||||
GrTextureEntry* createAndLockTexture(GrTextureKey* key,
|
TextureCacheEntry createAndLockTexture(TextureKey key,
|
||||||
const GrSamplerState&,
|
const GrSamplerState&,
|
||||||
const GrTextureDesc&,
|
const GrTextureDesc&,
|
||||||
void* srcData, size_t rowBytes);
|
void* srcData, size_t rowBytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum that determines how closely a returned scratch texture must match
|
||||||
|
* a provided GrTextureDesc.
|
||||||
|
*/
|
||||||
|
enum ScratchTexMatch {
|
||||||
|
/**
|
||||||
|
* Finds a texture that exactly matches the descriptor.
|
||||||
|
*/
|
||||||
|
kExact_ScratchTexMatch,
|
||||||
|
/**
|
||||||
|
* Finds a texture that approximately matches the descriptor. Will be
|
||||||
|
* at least as large in width and height as desc specifies. If desc
|
||||||
|
* specifies that texture is a render target then result will be a
|
||||||
|
* render target. If desc specifies a render target and doesn't set the
|
||||||
|
* no stencil flag then result will have a stencil. Format and aa level
|
||||||
|
* will always match.
|
||||||
|
*/
|
||||||
|
kApprox_ScratchTexMatch
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a texture matching the desc. It's contents are unknown. Subsequent
|
* Returns a texture matching the desc. It's contents are unknown. Subsequent
|
||||||
* requests with the same descriptor are not guaranteed to return the same
|
* requests with the same descriptor are not guaranteed to return the same
|
||||||
* texture. The same texture is guaranteed not be returned again until it is
|
* texture. The same texture is guaranteed not be returned again until it is
|
||||||
* unlocked.
|
* unlocked. Must call be balanced with an unlockTexture() call.
|
||||||
*
|
*
|
||||||
* Textures created by createAndLockTexture() hide the complications of
|
* Textures created by createAndLockTexture() hide the complications of
|
||||||
* tiling non-power-of-two textures on APIs that don't support this (e.g.
|
* tiling non-power-of-two textures on APIs that don't support this (e.g.
|
||||||
* unextended GLES2). Tiling a npot texture created by lockKeylessTexture on
|
* unextended GLES2). Tiling a npot texture created by lockScratchTexture on
|
||||||
* such an API will create gaps in the tiling pattern. This includes clamp
|
* such an API will create gaps in the tiling pattern. This includes clamp
|
||||||
* mode. (This may be addressed in a future update.)
|
* mode. (This may be addressed in a future update.)
|
||||||
*/
|
*/
|
||||||
GrTextureEntry* lockKeylessTexture(const GrTextureDesc& desc);
|
TextureCacheEntry lockScratchTexture(const GrTextureDesc& desc, ScratchTexMatch match);
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds a texture that approximately matches the descriptor. Will be
|
|
||||||
* at least as large in width and height as desc specifies. If desc
|
|
||||||
* specifies that texture is a render target then result will be a
|
|
||||||
* render target. If desc specifies a render target and doesn't set the
|
|
||||||
* no stencil flag then result will have a stencil. Format and aa level
|
|
||||||
* will always match.
|
|
||||||
*/
|
|
||||||
GrTextureEntry* findApproximateKeylessTexture(const GrTextureDesc& desc);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When done with an entry, call unlockTexture(entry) on it, which returns
|
* When done with an entry, call unlockTexture(entry) on it, which returns
|
||||||
* it to the cache, where it may be purged.
|
* it to the cache, where it may be purged.
|
||||||
*/
|
*/
|
||||||
void unlockTexture(GrTextureEntry* entry);
|
void unlockTexture(TextureCacheEntry entry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a texture that is outside the cache. Does not count against
|
* Creates a texture that is outside the cache. Does not count against
|
||||||
@ -195,9 +235,6 @@ public:
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Platform Surfaces
|
// Platform Surfaces
|
||||||
|
|
||||||
// GrContext provides an interface for wrapping externally created textures
|
|
||||||
// and rendertargets in their Gr-equivalents.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps an existing 3D API surface in a GrObject. desc.fFlags determines
|
* Wraps an existing 3D API surface in a GrObject. desc.fFlags determines
|
||||||
* the type of object returned. If kIsTexture is set the returned object
|
* the type of object returned. If kIsTexture is set the returned object
|
||||||
@ -213,6 +250,7 @@ public:
|
|||||||
* on failure.
|
* on failure.
|
||||||
*/
|
*/
|
||||||
GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc);
|
GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the current target object (e.g. FBO or IDirect3DSurface9*) and
|
* Reads the current target object (e.g. FBO or IDirect3DSurface9*) and
|
||||||
* viewport state from the underlying 3D API and wraps it in a
|
* viewport state from the underlying 3D API and wraps it in a
|
||||||
@ -559,9 +597,9 @@ private:
|
|||||||
};
|
};
|
||||||
DrawCategory fLastDrawCategory;
|
DrawCategory fLastDrawCategory;
|
||||||
|
|
||||||
GrGpu* fGpu;
|
GrGpu* fGpu;
|
||||||
GrTextureCache* fTextureCache;
|
GrResourceCache* fTextureCache;
|
||||||
GrFontCache* fFontCache;
|
GrFontCache* fFontCache;
|
||||||
|
|
||||||
GrPathRenderer* fCustomPathRenderer;
|
GrPathRenderer* fCustomPathRenderer;
|
||||||
GrDefaultPathRenderer fDefaultPathRenderer;
|
GrDefaultPathRenderer fDefaultPathRenderer;
|
||||||
@ -597,10 +635,6 @@ private:
|
|||||||
|
|
||||||
static void SetPaint(const GrPaint& paint, GrDrawTarget* target);
|
static void SetPaint(const GrPaint& paint, GrDrawTarget* target);
|
||||||
|
|
||||||
bool finalizeTextureKey(GrTextureKey*,
|
|
||||||
const GrSamplerState&,
|
|
||||||
bool keyless) const;
|
|
||||||
|
|
||||||
GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);
|
GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);
|
||||||
|
|
||||||
void drawClipIntoStencil();
|
void drawClipIntoStencil();
|
||||||
@ -680,24 +714,54 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlocks a texture entry when this goes out of scope. Entry may be NULL.
|
* Gets and locks a scratch texture from a descriptor using
|
||||||
|
* either exact or approximate criteria. Unlocks texture in
|
||||||
|
* the destructor.
|
||||||
*/
|
*/
|
||||||
class GrAutoUnlockTextureEntry : ::GrNoncopyable {
|
class GrAutoScratchTexture : ::GrNoncopyable {
|
||||||
public:
|
public:
|
||||||
GrAutoUnlockTextureEntry(GrContext* context, GrTextureEntry* entry)
|
GrAutoScratchTexture()
|
||||||
: fContext(context)
|
: fContext(NULL) {
|
||||||
, fEntry(entry) {
|
|
||||||
}
|
}
|
||||||
~GrAutoUnlockTextureEntry() {
|
|
||||||
if (fContext && fEntry) {
|
GrAutoScratchTexture(GrContext* context,
|
||||||
|
const GrTextureDesc& desc,
|
||||||
|
GrContext::ScratchTexMatch match =
|
||||||
|
GrContext::kApprox_ScratchTexMatch)
|
||||||
|
: fContext(NULL) {
|
||||||
|
this->set(context, desc, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
~GrAutoScratchTexture() {
|
||||||
|
if (NULL != fContext) {
|
||||||
fContext->unlockTexture(fEntry);
|
fContext->unlockTexture(fEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTexture* texture() { return fEntry->texture(); }
|
GrTexture* set(GrContext* context,
|
||||||
|
const GrTextureDesc& desc,
|
||||||
|
GrContext::ScratchTexMatch match =
|
||||||
|
GrContext::kApprox_ScratchTexMatch) {
|
||||||
|
if (NULL != fContext) {
|
||||||
|
fContext->unlockTexture(fEntry);
|
||||||
|
}
|
||||||
|
fContext = context;
|
||||||
|
if (NULL != fContext) {
|
||||||
|
fEntry = fContext->lockScratchTexture(desc, match);
|
||||||
|
GrTexture* ret = fEntry.texture();
|
||||||
|
if (NULL == ret) {
|
||||||
|
fContext = NULL;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GrTexture* texture() { return fEntry.texture(); }
|
||||||
private:
|
private:
|
||||||
GrContext* fContext;
|
GrContext* fContext;
|
||||||
GrTextureEntry* fEntry;
|
GrContext::TextureCacheEntry fEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "GrInOrderDrawBuffer.h"
|
#include "GrInOrderDrawBuffer.h"
|
||||||
#include "GrPathRenderer.h"
|
#include "GrPathRenderer.h"
|
||||||
#include "GrPathUtils.h"
|
#include "GrPathUtils.h"
|
||||||
#include "GrTextureCache.h"
|
#include "GrResourceCache.h"
|
||||||
#include "GrTextStrike.h"
|
#include "GrTextStrike.h"
|
||||||
#include "SkTrace.h"
|
#include "SkTrace.h"
|
||||||
|
|
||||||
@ -135,41 +135,66 @@ int GrContext::PaintStageVertexLayoutBits(
|
|||||||
enum {
|
enum {
|
||||||
kNPOTBit = 0x1,
|
kNPOTBit = 0x1,
|
||||||
kFilterBit = 0x2,
|
kFilterBit = 0x2,
|
||||||
kKeylessBit = 0x4,
|
kScratchBit = 0x4,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool GrContext::finalizeTextureKey(GrTextureKey* key,
|
GrTexture* GrContext::TextureCacheEntry::texture() const {
|
||||||
const GrSamplerState& sampler,
|
if (NULL == fEntry) {
|
||||||
bool keyless) const {
|
return NULL;
|
||||||
uint32_t bits = 0;
|
} else {
|
||||||
uint16_t width = key->width();
|
return (GrTexture*) fEntry->resource();
|
||||||
uint16_t height = key->height();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!fGpu->npotTextureTileSupport()) {
|
namespace {
|
||||||
|
// returns true if this is a "special" texture because of gpu NPOT limitations
|
||||||
|
bool gen_texture_key_values(const GrGpu* gpu,
|
||||||
|
const GrSamplerState& sampler,
|
||||||
|
GrContext::TextureKey clientKey,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
bool scratch,
|
||||||
|
uint32_t v[4]) {
|
||||||
|
GR_STATIC_ASSERT(sizeof(GrContext::TextureKey) == sizeof(uint64_t));
|
||||||
|
// we assume we only need 16 bits of width and height
|
||||||
|
// assert that texture creation will fail anyway if this assumption
|
||||||
|
// would cause key collisions.
|
||||||
|
GrAssert(gpu->maxTextureSize() <= SK_MaxU16);
|
||||||
|
v[0] = clientKey & 0xffffffffUL;
|
||||||
|
v[1] = (clientKey >> 32) & 0xffffffffUL;
|
||||||
|
v[2] = width | (height << 16);
|
||||||
|
|
||||||
|
v[3] = 0;
|
||||||
|
if (!gpu->npotTextureTileSupport()) {
|
||||||
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
|
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
|
||||||
|
|
||||||
bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
|
bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
|
||||||
(sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
|
(sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
|
||||||
|
|
||||||
if (tiled && !isPow2) {
|
if (tiled && !isPow2) {
|
||||||
bits |= kNPOTBit;
|
v[3] |= kNPOTBit;
|
||||||
if (GrSamplerState::kNearest_Filter != sampler.getFilter()) {
|
if (GrSamplerState::kNearest_Filter != sampler.getFilter()) {
|
||||||
bits |= kFilterBit;
|
v[3] |= kFilterBit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyless) {
|
if (scratch) {
|
||||||
bits |= kKeylessBit;
|
v[3] |= kScratchBit;
|
||||||
}
|
}
|
||||||
key->finalize(bits);
|
|
||||||
return 0 != bits;
|
return v[3] & kNPOTBit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
|
GrContext::TextureCacheEntry GrContext::findAndLockTexture(TextureKey key,
|
||||||
const GrSamplerState& sampler) {
|
int width,
|
||||||
finalizeTextureKey(key, sampler, false);
|
int height,
|
||||||
return fTextureCache->findAndLock(*key);
|
const GrSamplerState& sampler) {
|
||||||
|
uint32_t v[4];
|
||||||
|
gen_texture_key_values(fGpu, sampler, key, width, height, false, v);
|
||||||
|
GrResourceKey resourceKey(v);
|
||||||
|
return TextureCacheEntry(fTextureCache->findAndLock(resourceKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stretchImage(void* dst,
|
static void stretchImage(void* dst,
|
||||||
@ -199,32 +224,34 @@ static void stretchImage(void* dst,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
|
GrContext::TextureCacheEntry GrContext::createAndLockTexture(TextureKey key,
|
||||||
const GrSamplerState& sampler,
|
const GrSamplerState& sampler,
|
||||||
const GrTextureDesc& desc,
|
const GrTextureDesc& desc,
|
||||||
void* srcData, size_t rowBytes) {
|
void* srcData, size_t rowBytes) {
|
||||||
SK_TRACE_EVENT0("GrContext::createAndLockTexture");
|
SK_TRACE_EVENT0("GrContext::createAndLockTexture");
|
||||||
GrAssert(key->width() == desc.fWidth);
|
|
||||||
GrAssert(key->height() == desc.fHeight);
|
|
||||||
|
|
||||||
#if GR_DUMP_TEXTURE_UPLOAD
|
#if GR_DUMP_TEXTURE_UPLOAD
|
||||||
GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
|
GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GrTextureEntry* entry = NULL;
|
TextureCacheEntry entry;
|
||||||
bool special = finalizeTextureKey(key, sampler, false);
|
uint32_t v[4];
|
||||||
if (special) {
|
bool special = gen_texture_key_values(fGpu, sampler, key,
|
||||||
GrTextureEntry* clampEntry;
|
desc.fWidth, desc.fHeight, false, v);
|
||||||
GrTextureKey clampKey(*key);
|
GrResourceKey resourceKey(v);
|
||||||
clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter());
|
|
||||||
|
|
||||||
if (NULL == clampEntry) {
|
if (special) {
|
||||||
clampEntry = createAndLockTexture(&clampKey,
|
TextureCacheEntry clampEntry =
|
||||||
|
findAndLockTexture(key, desc.fWidth, desc.fHeight,
|
||||||
|
GrSamplerState::ClampNoFilter());
|
||||||
|
|
||||||
|
if (NULL == clampEntry.texture()) {
|
||||||
|
clampEntry = createAndLockTexture(key,
|
||||||
GrSamplerState::ClampNoFilter(),
|
GrSamplerState::ClampNoFilter(),
|
||||||
desc, srcData, rowBytes);
|
desc, srcData, rowBytes);
|
||||||
GrAssert(NULL != clampEntry);
|
GrAssert(NULL != clampEntry.texture());
|
||||||
if (NULL == clampEntry) {
|
if (NULL == clampEntry.texture()) {
|
||||||
return NULL;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GrTextureDesc rtDesc = desc;
|
GrTextureDesc rtDesc = desc;
|
||||||
@ -241,7 +268,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
|
|||||||
if (NULL != texture) {
|
if (NULL != texture) {
|
||||||
GrDrawTarget::AutoStateRestore asr(fGpu);
|
GrDrawTarget::AutoStateRestore asr(fGpu);
|
||||||
fGpu->setRenderTarget(texture->asRenderTarget());
|
fGpu->setRenderTarget(texture->asRenderTarget());
|
||||||
fGpu->setTexture(0, clampEntry->texture());
|
fGpu->setTexture(0, clampEntry.texture());
|
||||||
fGpu->disableStencil();
|
fGpu->disableStencil();
|
||||||
fGpu->setViewMatrix(GrMatrix::I());
|
fGpu->setViewMatrix(GrMatrix::I());
|
||||||
fGpu->setAlpha(0xff);
|
fGpu->setAlpha(0xff);
|
||||||
@ -276,7 +303,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
|
|||||||
verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
|
verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
|
||||||
fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
|
fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
|
||||||
0, 4);
|
0, 4);
|
||||||
entry = fTextureCache->createAndLock(*key, texture);
|
entry.set(fTextureCache->createAndLock(resourceKey, texture));
|
||||||
}
|
}
|
||||||
texture->releaseRenderTarget();
|
texture->releaseRenderTarget();
|
||||||
} else {
|
} else {
|
||||||
@ -302,69 +329,64 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
|
|||||||
stretchedPixels.get(),
|
stretchedPixels.get(),
|
||||||
stretchedRowBytes);
|
stretchedRowBytes);
|
||||||
GrAssert(NULL != texture);
|
GrAssert(NULL != texture);
|
||||||
entry = fTextureCache->createAndLock(*key, texture);
|
entry.set(fTextureCache->createAndLock(resourceKey, texture));
|
||||||
}
|
}
|
||||||
fTextureCache->unlock(clampEntry);
|
fTextureCache->unlock(clampEntry.cacheEntry());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
|
GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
|
||||||
if (NULL != texture) {
|
if (NULL != texture) {
|
||||||
entry = fTextureCache->createAndLock(*key, texture);
|
entry.set(fTextureCache->createAndLock(resourceKey, texture));
|
||||||
} else {
|
|
||||||
entry = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureEntry* GrContext::lockKeylessTexture(const GrTextureDesc& desc) {
|
namespace {
|
||||||
uint32_t p0 = desc.fFormat;
|
inline void gen_scratch_tex_key_values(const GrGpu* gpu,
|
||||||
uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
|
const GrTextureDesc& desc,
|
||||||
GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight);
|
uint32_t v[4]) {
|
||||||
this->finalizeTextureKey(&key, GrSamplerState::ClampNoFilter(), true);
|
// Instead of a client-provided key of the texture contents
|
||||||
|
// we create a key of from the descriptor.
|
||||||
GrTextureEntry* entry = fTextureCache->findAndLock(key);
|
GrContext::TextureKey descKey = desc.fAALevel |
|
||||||
if (NULL == entry) {
|
(desc.fFlags << 8) |
|
||||||
GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
|
((uint64_t) desc.fFormat << 32);
|
||||||
if (NULL != texture) {
|
// this code path isn't friendly to tiling with NPOT restricitons
|
||||||
entry = fTextureCache->createAndLock(key, texture);
|
// We just pass ClampNoFilter()
|
||||||
}
|
gen_texture_key_values(gpu, GrSamplerState::ClampNoFilter(), descKey,
|
||||||
}
|
desc.fWidth, desc.fHeight, true, v);
|
||||||
// If the caller gives us the same desc/sampler twice we don't want
|
}
|
||||||
// to return the same texture the second time (unless it was previously
|
|
||||||
// released). So we detach the entry from the cache and reattach at release.
|
|
||||||
if (NULL != entry) {
|
|
||||||
fTextureCache->detach(entry);
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureEntry* GrContext::findApproximateKeylessTexture(
|
GrContext::TextureCacheEntry GrContext::lockScratchTexture(
|
||||||
const GrTextureDesc& inDesc) {
|
const GrTextureDesc& inDesc,
|
||||||
|
ScratchTexMatch match) {
|
||||||
|
|
||||||
GrTextureDesc desc = inDesc;
|
GrTextureDesc desc = inDesc;
|
||||||
// bin by pow2 with a reasonable min
|
if (kExact_ScratchTexMatch != match) {
|
||||||
static const int MIN_SIZE = 256;
|
// bin by pow2 with a reasonable min
|
||||||
desc.fWidth = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
|
static const int MIN_SIZE = 256;
|
||||||
desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
|
desc.fWidth = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
|
||||||
|
desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t p0 = desc.fFormat;
|
uint32_t p0 = desc.fFormat;
|
||||||
uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
|
uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
|
||||||
|
|
||||||
GrTextureEntry* entry;
|
GrResourceEntry* entry;
|
||||||
bool keepTrying = true;
|
|
||||||
int origWidth = desc.fWidth;
|
int origWidth = desc.fWidth;
|
||||||
int origHeight = desc.fHeight;
|
int origHeight = desc.fHeight;
|
||||||
bool doubledW = false;
|
bool doubledW = false;
|
||||||
bool doubledH = false;
|
bool doubledH = false;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight);
|
uint32_t v[4];
|
||||||
this->finalizeTextureKey(&key, GrSamplerState::ClampNoFilter(), true);
|
gen_scratch_tex_key_values(fGpu, desc, v);
|
||||||
|
GrResourceKey key(v);
|
||||||
entry = fTextureCache->findAndLock(key);
|
entry = fTextureCache->findAndLock(key);
|
||||||
|
|
||||||
// if we miss, relax the fit of the flags...
|
// if we miss, relax the fit of the flags...
|
||||||
// then try doubling width... then height.
|
// then try doubling width... then height.
|
||||||
if (NULL != entry) {
|
if (NULL != entry || kExact_ScratchTexMatch == match) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
|
if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
|
||||||
@ -392,9 +414,9 @@ GrTextureEntry* GrContext::findApproximateKeylessTexture(
|
|||||||
desc.fHeight = origHeight;
|
desc.fHeight = origHeight;
|
||||||
GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
|
GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
|
||||||
if (NULL != texture) {
|
if (NULL != texture) {
|
||||||
GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight);
|
uint32_t v[4];
|
||||||
this->finalizeTextureKey(&key, GrSamplerState::ClampNoFilter(),
|
gen_scratch_tex_key_values(fGpu, desc, v);
|
||||||
true);
|
GrResourceKey key(v);
|
||||||
entry = fTextureCache->createAndLock(key, texture);
|
entry = fTextureCache->createAndLock(key, texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,14 +427,17 @@ GrTextureEntry* GrContext::findApproximateKeylessTexture(
|
|||||||
if (NULL != entry) {
|
if (NULL != entry) {
|
||||||
fTextureCache->detach(entry);
|
fTextureCache->detach(entry);
|
||||||
}
|
}
|
||||||
return entry;
|
return TextureCacheEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrContext::unlockTexture(GrTextureEntry* entry) {
|
void GrContext::unlockTexture(TextureCacheEntry entry) {
|
||||||
if (kKeylessBit & entry->key().getPrivateBits()) {
|
// If this is a scratch texture we detached it from the cache
|
||||||
fTextureCache->reattachAndUnlock(entry);
|
// while it was locked (to avoid two callers simultaneously getting
|
||||||
|
// the same texture).
|
||||||
|
if (kScratchBit & entry.cacheEntry()->key().getValue32(3)) {
|
||||||
|
fTextureCache->reattachAndUnlock(entry.cacheEntry());
|
||||||
} else {
|
} else {
|
||||||
fTextureCache->unlock(entry);
|
fTextureCache->unlock(entry.cacheEntry());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,9 +554,6 @@ void GrContext::drawPaint(const GrPaint& paint) {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct GrContext::OffscreenRecord {
|
struct GrContext::OffscreenRecord {
|
||||||
OffscreenRecord() { fEntry0 = NULL; fEntry1 = NULL; }
|
|
||||||
~OffscreenRecord() { GrAssert(NULL == fEntry0 && NULL == fEntry1); }
|
|
||||||
|
|
||||||
enum Downsample {
|
enum Downsample {
|
||||||
k4x4TwoPass_Downsample,
|
k4x4TwoPass_Downsample,
|
||||||
k4x4SinglePass_Downsample,
|
k4x4SinglePass_Downsample,
|
||||||
@ -542,8 +564,8 @@ struct GrContext::OffscreenRecord {
|
|||||||
int fTileCountX;
|
int fTileCountX;
|
||||||
int fTileCountY;
|
int fTileCountY;
|
||||||
int fScale;
|
int fScale;
|
||||||
GrTextureEntry* fEntry0;
|
GrAutoScratchTexture fOffscreen0;
|
||||||
GrTextureEntry* fEntry1;
|
GrAutoScratchTexture fOffscreen1;
|
||||||
GrDrawTarget::SavedDrawState fSavedState;
|
GrDrawTarget::SavedDrawState fSavedState;
|
||||||
GrClip fClip;
|
GrClip fClip;
|
||||||
};
|
};
|
||||||
@ -585,8 +607,8 @@ bool GrContext::prepareForOffscreenAA(GrDrawTarget* target,
|
|||||||
|
|
||||||
GrAssert(GR_USE_OFFSCREEN_AA);
|
GrAssert(GR_USE_OFFSCREEN_AA);
|
||||||
|
|
||||||
GrAssert(NULL == record->fEntry0);
|
GrAssert(NULL == record->fOffscreen0.texture());
|
||||||
GrAssert(NULL == record->fEntry1);
|
GrAssert(NULL == record->fOffscreen1.texture());
|
||||||
GrAssert(!boundRect.isEmpty());
|
GrAssert(!boundRect.isEmpty());
|
||||||
|
|
||||||
int boundW = boundRect.width();
|
int boundW = boundRect.width();
|
||||||
@ -627,31 +649,28 @@ bool GrContext::prepareForOffscreenAA(GrDrawTarget* target,
|
|||||||
|
|
||||||
desc.fWidth *= record->fScale;
|
desc.fWidth *= record->fScale;
|
||||||
desc.fHeight *= record->fScale;
|
desc.fHeight *= record->fScale;
|
||||||
|
record->fOffscreen0.set(this, desc);
|
||||||
record->fEntry0 = this->findApproximateKeylessTexture(desc);
|
if (NULL == record->fOffscreen0.texture()) {
|
||||||
if (NULL == record->fEntry0) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// the approximate lookup might have given us some slop space, might as well
|
// the approximate lookup might have given us some slop space, might as well
|
||||||
// use it when computing the tiles size.
|
// use it when computing the tiles size.
|
||||||
// these are scale values, will adjust after considering
|
// these are scale values, will adjust after considering
|
||||||
// the possible second offscreen.
|
// the possible second offscreen.
|
||||||
record->fTileSizeX = record->fEntry0->texture()->width();
|
record->fTileSizeX = record->fOffscreen0.texture()->width();
|
||||||
record->fTileSizeY = record->fEntry0->texture()->height();
|
record->fTileSizeY = record->fOffscreen0.texture()->height();
|
||||||
|
|
||||||
if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
|
if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
|
||||||
desc.fWidth /= 2;
|
desc.fWidth /= 2;
|
||||||
desc.fHeight /= 2;
|
desc.fHeight /= 2;
|
||||||
record->fEntry1 = this->findApproximateKeylessTexture(desc);
|
record->fOffscreen1.set(this, desc);
|
||||||
if (NULL == record->fEntry1) {
|
if (NULL == record->fOffscreen1.texture()) {
|
||||||
this->unlockTexture(record->fEntry0);
|
|
||||||
record->fEntry0 = NULL;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
record->fTileSizeX = GrMin(record->fTileSizeX,
|
record->fTileSizeX = GrMin(record->fTileSizeX,
|
||||||
2 * record->fEntry0->texture()->width());
|
2 * record->fOffscreen0.texture()->width());
|
||||||
record->fTileSizeY = GrMin(record->fTileSizeY,
|
record->fTileSizeY = GrMin(record->fTileSizeY,
|
||||||
2 * record->fEntry0->texture()->height());
|
2 * record->fOffscreen0.texture()->height());
|
||||||
}
|
}
|
||||||
record->fTileSizeX /= record->fScale;
|
record->fTileSizeX /= record->fScale;
|
||||||
record->fTileSizeY /= record->fScale;
|
record->fTileSizeY /= record->fScale;
|
||||||
@ -670,7 +689,7 @@ void GrContext::setupOffscreenAAPass1(GrDrawTarget* target,
|
|||||||
int tileX, int tileY,
|
int tileX, int tileY,
|
||||||
OffscreenRecord* record) {
|
OffscreenRecord* record) {
|
||||||
|
|
||||||
GrRenderTarget* offRT0 = record->fEntry0->texture()->asRenderTarget();
|
GrRenderTarget* offRT0 = record->fOffscreen0.texture()->asRenderTarget();
|
||||||
GrAssert(NULL != offRT0);
|
GrAssert(NULL != offRT0);
|
||||||
|
|
||||||
GrPaint tempPaint;
|
GrPaint tempPaint;
|
||||||
@ -715,7 +734,7 @@ void GrContext::doOffscreenAAPass2(GrDrawTarget* target,
|
|||||||
int tileX, int tileY,
|
int tileX, int tileY,
|
||||||
OffscreenRecord* record) {
|
OffscreenRecord* record) {
|
||||||
SK_TRACE_EVENT0("GrContext::doOffscreenAAPass2");
|
SK_TRACE_EVENT0("GrContext::doOffscreenAAPass2");
|
||||||
GrAssert(NULL != record->fEntry0);
|
GrAssert(NULL != record->fOffscreen0.texture());
|
||||||
GrDrawTarget::AutoGeometryPush agp(target);
|
GrDrawTarget::AutoGeometryPush agp(target);
|
||||||
GrIRect tileRect;
|
GrIRect tileRect;
|
||||||
tileRect.fLeft = boundRect.fLeft + tileX * record->fTileSizeX;
|
tileRect.fLeft = boundRect.fLeft + tileX * record->fTileSizeX;
|
||||||
@ -738,7 +757,7 @@ void GrContext::doOffscreenAAPass2(GrDrawTarget* target,
|
|||||||
GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
|
GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
|
||||||
GrSamplerState::kClamp_WrapMode, filter);
|
GrSamplerState::kClamp_WrapMode, filter);
|
||||||
|
|
||||||
GrTexture* src = record->fEntry0->texture();
|
GrTexture* src = record->fOffscreen0.texture();
|
||||||
int scale;
|
int scale;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -746,9 +765,9 @@ void GrContext::doOffscreenAAPass2(GrDrawTarget* target,
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
|
if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
|
||||||
GrAssert(NULL != record->fEntry1);
|
GrAssert(NULL != record->fOffscreen1.texture());
|
||||||
scale = 2;
|
scale = 2;
|
||||||
GrRenderTarget* dst = record->fEntry1->texture()->asRenderTarget();
|
GrRenderTarget* dst = record->fOffscreen1.texture()->asRenderTarget();
|
||||||
|
|
||||||
// Do 2x2 downsample from first to second
|
// Do 2x2 downsample from first to second
|
||||||
target->setTexture(kOffscreenStage, src);
|
target->setTexture(kOffscreenStage, src);
|
||||||
@ -762,7 +781,7 @@ void GrContext::doOffscreenAAPass2(GrDrawTarget* target,
|
|||||||
scale * tileRect.height());
|
scale * tileRect.height());
|
||||||
target->drawSimpleRect(rect, NULL, 1 << kOffscreenStage);
|
target->drawSimpleRect(rect, NULL, 1 << kOffscreenStage);
|
||||||
|
|
||||||
src = record->fEntry1->texture();
|
src = record->fOffscreen1.texture();
|
||||||
} else if (OffscreenRecord::kFSAA_Downsample == record->fDownsample) {
|
} else if (OffscreenRecord::kFSAA_Downsample == record->fDownsample) {
|
||||||
scale = 1;
|
scale = 1;
|
||||||
GrIRect rect = SkIRect::MakeWH(tileRect.width(), tileRect.height());
|
GrIRect rect = SkIRect::MakeWH(tileRect.width(), tileRect.height());
|
||||||
@ -811,16 +830,10 @@ void GrContext::doOffscreenAAPass2(GrDrawTarget* target,
|
|||||||
void GrContext::cleanupOffscreenAA(GrDrawTarget* target,
|
void GrContext::cleanupOffscreenAA(GrDrawTarget* target,
|
||||||
GrPathRenderer* pr,
|
GrPathRenderer* pr,
|
||||||
OffscreenRecord* record) {
|
OffscreenRecord* record) {
|
||||||
this->unlockTexture(record->fEntry0);
|
|
||||||
record->fEntry0 = NULL;
|
|
||||||
if (pr) {
|
if (pr) {
|
||||||
// Counterpart of scale() in prepareForOffscreenAA()
|
// Counterpart of scale() in prepareForOffscreenAA()
|
||||||
//pr->scaleCurveTolerance(SkScalarInvert(SkIntToScalar(record->fScale)));
|
//pr->scaleCurveTolerance(SkScalarInvert(SkIntToScalar(record->fScale)));
|
||||||
}
|
}
|
||||||
if (NULL != record->fEntry1) {
|
|
||||||
this->unlockTexture(record->fEntry1);
|
|
||||||
record->fEntry1 = NULL;
|
|
||||||
}
|
|
||||||
target->restoreDrawState(record->fSavedState);
|
target->restoreDrawState(record->fSavedState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1471,9 +1484,8 @@ void GrContext::writePixels(int left, int top, int width, int height,
|
|||||||
const GrTextureDesc desc = {
|
const GrTextureDesc desc = {
|
||||||
kNone_GrTextureFlags, kNone_GrAALevel, width, height, config
|
kNone_GrTextureFlags, kNone_GrAALevel, width, height, config
|
||||||
};
|
};
|
||||||
GrAutoUnlockTextureEntry aute(this,
|
GrAutoScratchTexture ast(this, desc);
|
||||||
this->findApproximateKeylessTexture(desc));
|
GrTexture* texture = ast.texture();
|
||||||
GrTexture* texture = aute.texture();
|
|
||||||
if (NULL == texture) {
|
if (NULL == texture) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1630,8 +1642,8 @@ GrContext::GrContext(GrGpu* gpu) :
|
|||||||
fCustomPathRenderer = GrPathRenderer::CreatePathRenderer();
|
fCustomPathRenderer = GrPathRenderer::CreatePathRenderer();
|
||||||
fGpu->setClipPathRenderer(fCustomPathRenderer);
|
fGpu->setClipPathRenderer(fCustomPathRenderer);
|
||||||
|
|
||||||
fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
|
fTextureCache = new GrResourceCache(MAX_TEXTURE_CACHE_COUNT,
|
||||||
MAX_TEXTURE_CACHE_BYTES);
|
MAX_TEXTURE_CACHE_BYTES);
|
||||||
fFontCache = new GrFontCache(fGpu);
|
fFontCache = new GrFontCache(fGpu);
|
||||||
|
|
||||||
fLastDrawCategory = kUnbuffered_DrawCategory;
|
fLastDrawCategory = kUnbuffered_DrawCategory;
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
#include "GrGpu.h"
|
#include "GrGpu.h"
|
||||||
#include "GrTextStrike.h"
|
#include "GrTextStrike.h"
|
||||||
#include "GrTextureCache.h"
|
|
||||||
#include "GrClipIterator.h"
|
#include "GrClipIterator.h"
|
||||||
#include "GrIndexBuffer.h"
|
#include "GrIndexBuffer.h"
|
||||||
#include "GrVertexBuffer.h"
|
#include "GrVertexBuffer.h"
|
||||||
|
@ -15,33 +15,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "GrTextureCache.h"
|
#include "GrResourceCache.h"
|
||||||
#include "GrTexture.h"
|
#include "GrResource.h"
|
||||||
|
|
||||||
GrTextureEntry::GrTextureEntry(const GrTextureKey& key, GrTexture* texture)
|
GrResourceEntry::GrResourceEntry(const GrResourceKey& key, GrResource* resource)
|
||||||
: fKey(key), fTexture(texture) {
|
: fKey(key), fResource(resource) {
|
||||||
fLockCount = 0;
|
fLockCount = 0;
|
||||||
fPrev = fNext = NULL;
|
fPrev = fNext = NULL;
|
||||||
|
|
||||||
// we assume ownership of the texture, and will unref it when we die
|
// we assume ownership of the resource, and will unref it when we die
|
||||||
GrAssert(texture);
|
GrAssert(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureEntry::~GrTextureEntry() {
|
GrResourceEntry::~GrResourceEntry() {
|
||||||
fTexture->unref();
|
fResource->unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
void GrTextureEntry::validate() const {
|
void GrResourceEntry::validate() const {
|
||||||
GrAssert(fLockCount >= 0);
|
GrAssert(fLockCount >= 0);
|
||||||
GrAssert(fTexture);
|
GrAssert(fResource);
|
||||||
fTexture->validate();
|
fResource->validate();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GrTextureCache::GrTextureCache(int maxCount, size_t maxBytes) :
|
GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
|
||||||
fMaxCount(maxCount),
|
fMaxCount(maxCount),
|
||||||
fMaxBytes(maxBytes) {
|
fMaxBytes(maxBytes) {
|
||||||
fEntryCount = 0;
|
fEntryCount = 0;
|
||||||
@ -52,36 +52,36 @@ GrTextureCache::GrTextureCache(int maxCount, size_t maxBytes) :
|
|||||||
fHead = fTail = NULL;
|
fHead = fTail = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureCache::~GrTextureCache() {
|
GrResourceCache::~GrResourceCache() {
|
||||||
GrAutoTextureCacheValidate atcv(this);
|
GrAutoResourceCacheValidate atcv(this);
|
||||||
|
|
||||||
this->removeAll();
|
this->removeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::getLimits(int* maxTextures, size_t* maxTextureBytes) const{
|
void GrResourceCache::getLimits(int* maxResources, size_t* maxResourceBytes) const{
|
||||||
if (maxTextures) {
|
if (maxResources) {
|
||||||
*maxTextures = fMaxCount;
|
*maxResources = fMaxCount;
|
||||||
}
|
}
|
||||||
if (maxTextureBytes) {
|
if (maxResourceBytes) {
|
||||||
*maxTextureBytes = fMaxBytes;
|
*maxResourceBytes = fMaxBytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::setLimits(int maxTextures, size_t maxTextureBytes) {
|
void GrResourceCache::setLimits(int maxResources, size_t maxResourceBytes) {
|
||||||
bool smaller = (maxTextures < fMaxCount) || (maxTextureBytes < fMaxBytes);
|
bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes);
|
||||||
|
|
||||||
fMaxCount = maxTextures;
|
fMaxCount = maxResources;
|
||||||
fMaxBytes = maxTextureBytes;
|
fMaxBytes = maxResourceBytes;
|
||||||
|
|
||||||
if (smaller) {
|
if (smaller) {
|
||||||
this->purgeAsNeeded();
|
this->purgeAsNeeded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::internalDetach(GrTextureEntry* entry,
|
void GrResourceCache::internalDetach(GrResourceEntry* entry,
|
||||||
bool clientDetach) {
|
bool clientDetach) {
|
||||||
GrTextureEntry* prev = entry->fPrev;
|
GrResourceEntry* prev = entry->fPrev;
|
||||||
GrTextureEntry* next = entry->fNext;
|
GrResourceEntry* next = entry->fNext;
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
prev->fNext = next;
|
prev->fNext = next;
|
||||||
@ -97,14 +97,14 @@ void GrTextureCache::internalDetach(GrTextureEntry* entry,
|
|||||||
// update our stats
|
// update our stats
|
||||||
if (clientDetach) {
|
if (clientDetach) {
|
||||||
fClientDetachedCount += 1;
|
fClientDetachedCount += 1;
|
||||||
fClientDetachedBytes += entry->texture()->sizeInBytes();
|
fClientDetachedBytes += entry->resource()->sizeInBytes();
|
||||||
} else {
|
} else {
|
||||||
fEntryCount -= 1;
|
fEntryCount -= 1;
|
||||||
fEntryBytes -= entry->texture()->sizeInBytes();
|
fEntryBytes -= entry->resource()->sizeInBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::attachToHead(GrTextureEntry* entry,
|
void GrResourceCache::attachToHead(GrResourceEntry* entry,
|
||||||
bool clientReattach) {
|
bool clientReattach) {
|
||||||
entry->fPrev = NULL;
|
entry->fPrev = NULL;
|
||||||
entry->fNext = fHead;
|
entry->fNext = fHead;
|
||||||
@ -119,19 +119,19 @@ void GrTextureCache::attachToHead(GrTextureEntry* entry,
|
|||||||
// update our stats
|
// update our stats
|
||||||
if (clientReattach) {
|
if (clientReattach) {
|
||||||
fClientDetachedCount -= 1;
|
fClientDetachedCount -= 1;
|
||||||
fClientDetachedBytes -= entry->texture()->sizeInBytes();
|
fClientDetachedBytes -= entry->resource()->sizeInBytes();
|
||||||
} else {
|
} else {
|
||||||
fEntryCount += 1;
|
fEntryCount += 1;
|
||||||
fEntryBytes += entry->texture()->sizeInBytes();
|
fEntryBytes += entry->resource()->sizeInBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GrTextureCache::Key {
|
class GrResourceCache::Key {
|
||||||
typedef GrTextureEntry T;
|
typedef GrResourceEntry T;
|
||||||
|
|
||||||
const GrTextureKey& fKey;
|
const GrResourceKey& fKey;
|
||||||
public:
|
public:
|
||||||
Key(const GrTextureKey& key) : fKey(key) {}
|
Key(const GrResourceKey& key) : fKey(key) {}
|
||||||
|
|
||||||
uint32_t getHash() const { return fKey.hashIndex(); }
|
uint32_t getHash() const { return fKey.hashIndex(); }
|
||||||
|
|
||||||
@ -154,10 +154,10 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
GrTextureEntry* GrTextureCache::findAndLock(const GrTextureKey& key) {
|
GrResourceEntry* GrResourceCache::findAndLock(const GrResourceKey& key) {
|
||||||
GrAutoTextureCacheValidate atcv(this);
|
GrAutoResourceCacheValidate atcv(this);
|
||||||
|
|
||||||
GrTextureEntry* entry = fCache.find(key);
|
GrResourceEntry* entry = fCache.find(key);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
this->internalDetach(entry, false);
|
this->internalDetach(entry, false);
|
||||||
this->attachToHead(entry, false);
|
this->attachToHead(entry, false);
|
||||||
@ -167,18 +167,18 @@ GrTextureEntry* GrTextureCache::findAndLock(const GrTextureKey& key) {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureEntry* GrTextureCache::createAndLock(const GrTextureKey& key,
|
GrResourceEntry* GrResourceCache::createAndLock(const GrResourceKey& key,
|
||||||
GrTexture* texture) {
|
GrResource* resource) {
|
||||||
GrAutoTextureCacheValidate atcv(this);
|
GrAutoResourceCacheValidate atcv(this);
|
||||||
|
|
||||||
GrTextureEntry* entry = new GrTextureEntry(key, texture);
|
GrResourceEntry* entry = new GrResourceEntry(key, resource);
|
||||||
|
|
||||||
this->attachToHead(entry, false);
|
this->attachToHead(entry, false);
|
||||||
fCache.insert(key, entry);
|
fCache.insert(key, entry);
|
||||||
|
|
||||||
#if GR_DUMP_TEXTURE_UPLOAD
|
#if GR_DUMP_TEXTURE_UPLOAD
|
||||||
GrPrintf("--- add texture to cache %p, count=%d bytes= %d %d\n",
|
GrPrintf("--- add resource to cache %p, count=%d bytes= %d %d\n",
|
||||||
entry, fEntryCount, texture->sizeInBytes(), fEntryBytes);
|
entry, fEntryCount, resource->sizeInBytes(), fEntryBytes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// mark the entry as "busy" so it doesn't get purged
|
// mark the entry as "busy" so it doesn't get purged
|
||||||
@ -187,19 +187,19 @@ GrTextureEntry* GrTextureCache::createAndLock(const GrTextureKey& key,
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::detach(GrTextureEntry* entry) {
|
void GrResourceCache::detach(GrResourceEntry* entry) {
|
||||||
internalDetach(entry, true);
|
internalDetach(entry, true);
|
||||||
fCache.remove(entry->fKey, entry);
|
fCache.remove(entry->fKey, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::reattachAndUnlock(GrTextureEntry* entry) {
|
void GrResourceCache::reattachAndUnlock(GrResourceEntry* entry) {
|
||||||
attachToHead(entry, true);
|
attachToHead(entry, true);
|
||||||
fCache.insert(entry->key(), entry);
|
fCache.insert(entry->key(), entry);
|
||||||
unlock(entry);
|
unlock(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::unlock(GrTextureEntry* entry) {
|
void GrResourceCache::unlock(GrResourceEntry* entry) {
|
||||||
GrAutoTextureCacheValidate atcv(this);
|
GrAutoResourceCacheValidate atcv(this);
|
||||||
|
|
||||||
GrAssert(entry);
|
GrAssert(entry);
|
||||||
GrAssert(entry->isLocked());
|
GrAssert(entry->isLocked());
|
||||||
@ -209,16 +209,16 @@ void GrTextureCache::unlock(GrTextureEntry* entry) {
|
|||||||
this->purgeAsNeeded();
|
this->purgeAsNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::purgeAsNeeded() {
|
void GrResourceCache::purgeAsNeeded() {
|
||||||
GrAutoTextureCacheValidate atcv(this);
|
GrAutoResourceCacheValidate atcv(this);
|
||||||
|
|
||||||
GrTextureEntry* entry = fTail;
|
GrResourceEntry* entry = fTail;
|
||||||
while (entry) {
|
while (entry) {
|
||||||
if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) {
|
if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureEntry* prev = entry->fPrev;
|
GrResourceEntry* prev = entry->fPrev;
|
||||||
if (!entry->isLocked()) {
|
if (!entry->isLocked()) {
|
||||||
// remove from our cache
|
// remove from our cache
|
||||||
fCache.remove(entry->fKey, entry);
|
fCache.remove(entry->fKey, entry);
|
||||||
@ -227,9 +227,9 @@ void GrTextureCache::purgeAsNeeded() {
|
|||||||
this->internalDetach(entry, false);
|
this->internalDetach(entry, false);
|
||||||
|
|
||||||
#if GR_DUMP_TEXTURE_UPLOAD
|
#if GR_DUMP_TEXTURE_UPLOAD
|
||||||
GrPrintf("--- ~texture from cache %p [%d %d]\n", entry->texture(),
|
GrPrintf("--- ~resource from cache %p [%d %d]\n", entry->resource(),
|
||||||
entry->texture()->width(),
|
entry->resource()->width(),
|
||||||
entry->texture()->height());
|
entry->resource()->height());
|
||||||
#endif
|
#endif
|
||||||
delete entry;
|
delete entry;
|
||||||
}
|
}
|
||||||
@ -237,15 +237,15 @@ void GrTextureCache::purgeAsNeeded() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureCache::removeAll() {
|
void GrResourceCache::removeAll() {
|
||||||
GrAssert(!fClientDetachedCount);
|
GrAssert(!fClientDetachedCount);
|
||||||
GrAssert(!fClientDetachedBytes);
|
GrAssert(!fClientDetachedBytes);
|
||||||
|
|
||||||
GrTextureEntry* entry = fHead;
|
GrResourceEntry* entry = fHead;
|
||||||
while (entry) {
|
while (entry) {
|
||||||
GrAssert(!entry->isLocked());
|
GrAssert(!entry->isLocked());
|
||||||
|
|
||||||
GrTextureEntry* next = entry->fNext;
|
GrResourceEntry* next = entry->fNext;
|
||||||
delete entry;
|
delete entry;
|
||||||
entry = next;
|
entry = next;
|
||||||
}
|
}
|
||||||
@ -259,8 +259,8 @@ void GrTextureCache::removeAll() {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
static int countMatches(const GrTextureEntry* head, const GrTextureEntry* target) {
|
static int countMatches(const GrResourceEntry* head, const GrResourceEntry* target) {
|
||||||
const GrTextureEntry* entry = head;
|
const GrResourceEntry* entry = head;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while (entry) {
|
while (entry) {
|
||||||
if (target == entry) {
|
if (target == entry) {
|
||||||
@ -277,7 +277,7 @@ static bool both_zero_or_nonzero(int count, size_t bytes) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void GrTextureCache::validate() const {
|
void GrResourceCache::validate() const {
|
||||||
GrAssert(!fHead == !fTail);
|
GrAssert(!fHead == !fTail);
|
||||||
GrAssert(both_zero_or_nonzero(fEntryCount, fEntryBytes));
|
GrAssert(both_zero_or_nonzero(fEntryCount, fEntryBytes));
|
||||||
GrAssert(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes));
|
GrAssert(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes));
|
||||||
@ -287,14 +287,14 @@ void GrTextureCache::validate() const {
|
|||||||
|
|
||||||
fCache.validate();
|
fCache.validate();
|
||||||
|
|
||||||
GrTextureEntry* entry = fHead;
|
GrResourceEntry* entry = fHead;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
size_t bytes = 0;
|
size_t bytes = 0;
|
||||||
while (entry) {
|
while (entry) {
|
||||||
entry->validate();
|
entry->validate();
|
||||||
GrAssert(fCache.find(entry->key()));
|
GrAssert(fCache.find(entry->key()));
|
||||||
count += 1;
|
count += 1;
|
||||||
bytes += entry->texture()->sizeInBytes();
|
bytes += entry->resource()->sizeInBytes();
|
||||||
entry = entry->fNext;
|
entry = entry->fNext;
|
||||||
}
|
}
|
||||||
GrAssert(count == fEntryCount - fClientDetachedCount);
|
GrAssert(count == fEntryCount - fClientDetachedCount);
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2010 Google Inc.
|
Copyright 2011 Google Inc.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef GrTextureCache_DEFINED
|
#ifndef GrResourceCache_DEFINED
|
||||||
#define GrTextureCache_DEFINED
|
#define GrResourceCache_DEFINED
|
||||||
|
|
||||||
#include "GrTypes.h"
|
#include "GrTypes.h"
|
||||||
#include "GrTHashCache.h"
|
#include "GrTHashCache.h"
|
||||||
|
|
||||||
class GrTexture;
|
class GrResource;
|
||||||
|
|
||||||
// return true if a<b, or false if b<a
|
// return true if a<b, or false if b<a
|
||||||
//
|
//
|
||||||
@ -36,11 +36,11 @@ class GrTexture;
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for GrTextureCache, the Key is used to identify src data for
|
* Helper class for GrResourceCache, the Key is used to identify src data for
|
||||||
* a texture. It is identified by 2 32bit data fields which can hold any
|
* a resource. It is identified by 2 32bit data fields which can hold any
|
||||||
* data (uninterpreted by the cache) and a width/height.
|
* data (uninterpreted by the cache) and a width/height.
|
||||||
*/
|
*/
|
||||||
class GrTextureKey {
|
class GrResourceKey {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
kHashBits = 7,
|
kHashBits = 7,
|
||||||
@ -48,51 +48,53 @@ public:
|
|||||||
kHashMask = kHashCount - 1
|
kHashMask = kHashCount - 1
|
||||||
};
|
};
|
||||||
|
|
||||||
GrTextureKey(uint32_t p0, uint32_t p1, uint16_t width, uint16_t height) {
|
GrResourceKey(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) {
|
||||||
fP0 = p0;
|
fP[0] = p0;
|
||||||
fP1 = p1;
|
fP[1] = p1;
|
||||||
fP2 = width | (height << 16);
|
fP[2] = p2;
|
||||||
GR_DEBUGCODE(fHashIndex = -1);
|
fP[3] = p3;
|
||||||
|
this->computeHashIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureKey(const GrTextureKey& src) {
|
GrResourceKey(uint32_t v[4]) {
|
||||||
fP0 = src.fP0;
|
memcpy(fP, v, 4 * sizeof(uint32_t));
|
||||||
fP1 = src.fP1;
|
this->computeHashIndex();
|
||||||
fP2 = src.fP2;
|
}
|
||||||
finalize(src.fPrivateBits);
|
|
||||||
|
GrResourceKey(const GrResourceKey& src) {
|
||||||
|
memcpy(fP, src.fP, 4 * sizeof(uint32_t));
|
||||||
|
#if GR_DEBUG
|
||||||
|
this->computeHashIndex();
|
||||||
|
GrAssert(fHashIndex == src.fHashIndex);
|
||||||
|
#endif
|
||||||
|
fHashIndex = src.fHashIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
//!< returns hash value [0..kHashMask] for the key
|
//!< returns hash value [0..kHashMask] for the key
|
||||||
int hashIndex() const { return fHashIndex; }
|
int hashIndex() const { return fHashIndex; }
|
||||||
|
|
||||||
friend bool operator==(const GrTextureKey& a, const GrTextureKey& b) {
|
friend bool operator==(const GrResourceKey& a, const GrResourceKey& b) {
|
||||||
GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex);
|
GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex);
|
||||||
return a.fP0 == b.fP0 && a.fP1 == b.fP1 && a.fP2 == b.fP2 &&
|
return 0 == memcmp(a.fP, b.fP, 4 * sizeof(uint32_t));
|
||||||
a.fPrivateBits == b.fPrivateBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const GrTextureKey& a, const GrTextureKey& b) {
|
friend bool operator!=(const GrResourceKey& a, const GrResourceKey& b) {
|
||||||
GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex);
|
GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex);
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator<(const GrTextureKey& a, const GrTextureKey& b) {
|
friend bool operator<(const GrResourceKey& a, const GrResourceKey& b) {
|
||||||
RET_IF_LT_OR_GT(a.fP0, b.fP0);
|
RET_IF_LT_OR_GT(a.fP[0], b.fP[0]);
|
||||||
RET_IF_LT_OR_GT(a.fP1, b.fP1);
|
RET_IF_LT_OR_GT(a.fP[1], b.fP[1]);
|
||||||
RET_IF_LT_OR_GT(a.fP2, b.fP2);
|
RET_IF_LT_OR_GT(a.fP[2], b.fP[2]);
|
||||||
return a.fPrivateBits < b.fPrivateBits;
|
return a.fP[3] < b.fP[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t getValue32(int i) const {
|
||||||
|
GrAssert(i >=0 && i < 4);
|
||||||
|
return fP[i];
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
void finalize(uint32_t privateBits) {
|
|
||||||
fPrivateBits = privateBits;
|
|
||||||
this->computeHashIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t width() const { return fP2 & 0xffff; }
|
|
||||||
uint16_t height() const { return (fP2 >> 16); }
|
|
||||||
|
|
||||||
uint32_t getPrivateBits() const { return fPrivateBits; }
|
|
||||||
|
|
||||||
static uint32_t rol(uint32_t x) {
|
static uint32_t rol(uint32_t x) {
|
||||||
return (x >> 24) | (x << 8);
|
return (x >> 24) | (x << 8);
|
||||||
@ -105,7 +107,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void computeHashIndex() {
|
void computeHashIndex() {
|
||||||
uint32_t hash = fP0 ^ rol(fP1) ^ ror(fP2) ^ rohalf(fPrivateBits);
|
uint32_t hash = fP[0] ^ rol(fP[1]) ^ ror(fP[2]) ^ rohalf(fP[3]);
|
||||||
// this way to mix and reduce hash to its index may have to change
|
// this way to mix and reduce hash to its index may have to change
|
||||||
// depending on how many bits we allocate to the index
|
// depending on how many bits we allocate to the index
|
||||||
hash ^= hash >> 16;
|
hash ^= hash >> 16;
|
||||||
@ -113,10 +115,7 @@ private:
|
|||||||
fHashIndex = hash & kHashMask;
|
fHashIndex = hash & kHashMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fP0;
|
uint32_t fP[4];
|
||||||
uint32_t fP1;
|
|
||||||
uint32_t fP2;
|
|
||||||
uint32_t fPrivateBits;
|
|
||||||
|
|
||||||
// this is computed from the fP... fields
|
// this is computed from the fP... fields
|
||||||
int fHashIndex;
|
int fHashIndex;
|
||||||
@ -126,14 +125,14 @@ private:
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class GrTextureEntry {
|
class GrResourceEntry {
|
||||||
public:
|
public:
|
||||||
GrTexture* texture() const { return fTexture; }
|
GrResource* resource() const { return fResource; }
|
||||||
const GrTextureKey& key() const { return fKey; }
|
const GrResourceKey& key() const { return fKey; }
|
||||||
|
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
GrTextureEntry* next() const { return fNext; }
|
GrResourceEntry* next() const { return fNext; }
|
||||||
GrTextureEntry* prev() const { return fPrev; }
|
GrResourceEntry* prev() const { return fPrev; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
@ -143,8 +142,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrTextureEntry(const GrTextureKey& key, GrTexture* texture);
|
GrResourceEntry(const GrResourceKey& key, GrResource* resource);
|
||||||
~GrTextureEntry();
|
~GrResourceEntry();
|
||||||
|
|
||||||
bool isLocked() const { return fLockCount != 0; }
|
bool isLocked() const { return fLockCount != 0; }
|
||||||
void lock() { ++fLockCount; }
|
void lock() { ++fLockCount; }
|
||||||
@ -153,18 +152,18 @@ private:
|
|||||||
--fLockCount;
|
--fLockCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureKey fKey;
|
GrResourceKey fKey;
|
||||||
GrTexture* fTexture;
|
GrResource* fResource;
|
||||||
|
|
||||||
// track if we're in use, used when we need to purge
|
// track if we're in use, used when we need to purge
|
||||||
// we only purge unlocked entries
|
// we only purge unlocked entries
|
||||||
int fLockCount;
|
int fLockCount;
|
||||||
|
|
||||||
// we're a dlinklist
|
// we're a dlinklist
|
||||||
GrTextureEntry* fPrev;
|
GrResourceEntry* fPrev;
|
||||||
GrTextureEntry* fNext;
|
GrResourceEntry* fNext;
|
||||||
|
|
||||||
friend class GrTextureCache;
|
friend class GrResourceCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -172,17 +171,17 @@ private:
|
|||||||
#include "GrTHashCache.h"
|
#include "GrTHashCache.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache of GrTexture objects.
|
* Cache of GrResource objects.
|
||||||
*
|
*
|
||||||
* These have a corresponding GrTextureKey, built from 96bits identifying the
|
* These have a corresponding GrResourceKey, built from 128bits identifying the
|
||||||
* texture/bitmap.
|
* resource.
|
||||||
*
|
*
|
||||||
* The cache stores the entries in a double-linked list, which is its LRU.
|
* The cache stores the entries in a double-linked list, which is its LRU.
|
||||||
* When an entry is "locked" (i.e. given to the caller), it is moved to the
|
* When an entry is "locked" (i.e. given to the caller), it is moved to the
|
||||||
* head of the list. If/when we must purge some of the entries, we walk the
|
* head of the list. If/when we must purge some of the entries, we walk the
|
||||||
* list backwards from the tail, since those are the least recently used.
|
* list backwards from the tail, since those are the least recently used.
|
||||||
*
|
*
|
||||||
* For fast searches, we maintain a sorted array (based on the GrTextureKey)
|
* For fast searches, we maintain a sorted array (based on the GrResourceKey)
|
||||||
* which we can bsearch. When a new entry is added, it is inserted into this
|
* which we can bsearch. When a new entry is added, it is inserted into this
|
||||||
* array.
|
* array.
|
||||||
*
|
*
|
||||||
@ -190,46 +189,46 @@ private:
|
|||||||
* a collision between two keys with the same hash, we fall back on the
|
* a collision between two keys with the same hash, we fall back on the
|
||||||
* bsearch, and update the hash to reflect the most recent Key requested.
|
* bsearch, and update the hash to reflect the most recent Key requested.
|
||||||
*/
|
*/
|
||||||
class GrTextureCache {
|
class GrResourceCache {
|
||||||
public:
|
public:
|
||||||
GrTextureCache(int maxCount, size_t maxBytes);
|
GrResourceCache(int maxCount, size_t maxBytes);
|
||||||
~GrTextureCache();
|
~GrResourceCache();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the current texture cache limits.
|
* Return the current resource cache limits.
|
||||||
*
|
*
|
||||||
* @param maxTextures If non-null, returns maximum number of textures that
|
* @param maxResource If non-null, returns maximum number of resources
|
||||||
* can be held in the cache.
|
* that can be held in the cache.
|
||||||
* @param maxTextureBytes If non-null, returns maximum number of bytes of
|
* @param maxBytes If non-null, returns maximum number of bytes of
|
||||||
* texture memory that can be held in the cache.
|
* gpu memory that can be held in the cache.
|
||||||
*/
|
*/
|
||||||
void getLimits(int* maxTextures, size_t* maxTextureBytes) const;
|
void getLimits(int* maxResources, size_t* maxBytes) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the texture cache limits. If the current cache exceeds either
|
* Specify the resource cache limits. If the current cache exceeds either
|
||||||
* of these, it will be purged (LRU) to keep the cache within these limits.
|
* of these, it will be purged (LRU) to keep the cache within these limits.
|
||||||
*
|
*
|
||||||
* @param maxTextures The maximum number of textures that can be held in
|
* @param maxResources The maximum number of resources that can be held in
|
||||||
* the cache.
|
* the cache.
|
||||||
* @param maxTextureBytes The maximum number of bytes of texture memory
|
* @param maxBytes The maximum number of bytes of resource memory that
|
||||||
* that can be held in the cache.
|
* can be held in the cache.
|
||||||
*/
|
*/
|
||||||
void setLimits(int maxTextures, size_t maxTextureBytes);
|
void setLimits(int maxResource, size_t maxResourceBytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for an entry with the same Key. If found, "lock" it and return it.
|
* Search for an entry with the same Key. If found, "lock" it and return it.
|
||||||
* If not found, return null.
|
* If not found, return null.
|
||||||
*/
|
*/
|
||||||
GrTextureEntry* findAndLock(const GrTextureKey&);
|
GrResourceEntry* findAndLock(const GrResourceKey&);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new entry, based on the specified key and texture, and return
|
* Create a new entry, based on the specified key and resource, and return
|
||||||
* its "locked" entry.
|
* its "locked" entry.
|
||||||
*
|
*
|
||||||
* Ownership of the texture is transferred to the Entry, which will unref()
|
* Ownership of the resource is transferred to the Entry, which will unref()
|
||||||
* it when we are purged or deleted.
|
* it when we are purged or deleted.
|
||||||
*/
|
*/
|
||||||
GrTextureEntry* createAndLock(const GrTextureKey&, GrTexture*);
|
GrResourceEntry* createAndLock(const GrResourceKey&, GrResource*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach removes an entry from the cache. This prevents the entry from
|
* Detach removes an entry from the cache. This prevents the entry from
|
||||||
@ -237,20 +236,20 @@ public:
|
|||||||
* entry still counts against the cache's budget and should be reattached
|
* entry still counts against the cache's budget and should be reattached
|
||||||
* when exclusive access is no longer needed.
|
* when exclusive access is no longer needed.
|
||||||
*/
|
*/
|
||||||
void detach(GrTextureEntry*);
|
void detach(GrResourceEntry*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reattaches a texture to the cache and unlocks it. Allows it to be found
|
* Reattaches a resource to the cache and unlocks it. Allows it to be found
|
||||||
* by a subsequent findAndLock or be purged (provided its lock count is
|
* by a subsequent findAndLock or be purged (provided its lock count is
|
||||||
* now 0.)
|
* now 0.)
|
||||||
*/
|
*/
|
||||||
void reattachAndUnlock(GrTextureEntry*);
|
void reattachAndUnlock(GrResourceEntry*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When done with an entry, call unlock(entry) on it, which returns it to
|
* When done with an entry, call unlock(entry) on it, which returns it to
|
||||||
* a purgable state.
|
* a purgable state.
|
||||||
*/
|
*/
|
||||||
void unlock(GrTextureEntry*);
|
void unlock(GrResourceEntry*);
|
||||||
|
|
||||||
void removeAll();
|
void removeAll();
|
||||||
|
|
||||||
@ -261,16 +260,16 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void internalDetach(GrTextureEntry*, bool);
|
void internalDetach(GrResourceEntry*, bool);
|
||||||
void attachToHead(GrTextureEntry*, bool);
|
void attachToHead(GrResourceEntry*, bool);
|
||||||
void purgeAsNeeded(); // uses kFreeTexture_DeleteMode
|
void purgeAsNeeded(); // uses kFreeResource_DeleteMode
|
||||||
|
|
||||||
class Key;
|
class Key;
|
||||||
GrTHashTable<GrTextureEntry, Key, 8> fCache;
|
GrTHashTable<GrResourceEntry, Key, 8> fCache;
|
||||||
|
|
||||||
// manage the dlink list
|
// manage the dlink list
|
||||||
GrTextureEntry* fHead;
|
GrResourceEntry* fHead;
|
||||||
GrTextureEntry* fTail;
|
GrResourceEntry* fTail;
|
||||||
|
|
||||||
// our budget, used in purgeAsNeeded()
|
// our budget, used in purgeAsNeeded()
|
||||||
int fMaxCount;
|
int fMaxCount;
|
||||||
@ -286,21 +285,21 @@ private:
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
class GrAutoTextureCacheValidate {
|
class GrAutoResourceCacheValidate {
|
||||||
public:
|
public:
|
||||||
GrAutoTextureCacheValidate(GrTextureCache* cache) : fCache(cache) {
|
GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) {
|
||||||
cache->validate();
|
cache->validate();
|
||||||
}
|
}
|
||||||
~GrAutoTextureCacheValidate() {
|
~GrAutoResourceCacheValidate() {
|
||||||
fCache->validate();
|
fCache->validate();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
GrTextureCache* fCache;
|
GrResourceCache* fCache;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
class GrAutoTextureCacheValidate {
|
class GrAutoResourceCacheValidate {
|
||||||
public:
|
public:
|
||||||
GrAutoTextureCacheValidate(GrTextureCache*) {}
|
GrAutoResourceCacheValidate(GrResourceCache*) {}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -132,7 +132,6 @@
|
|||||||
'../gpu/include/GrTextContext.h',
|
'../gpu/include/GrTextContext.h',
|
||||||
'../gpu/include/GrTextStrike.h',
|
'../gpu/include/GrTextStrike.h',
|
||||||
'../gpu/include/GrTexture.h',
|
'../gpu/include/GrTexture.h',
|
||||||
'../gpu/include/GrTextureCache.h',
|
|
||||||
'../gpu/include/GrTHashCache.h',
|
'../gpu/include/GrTHashCache.h',
|
||||||
'../gpu/include/GrTLList.h',
|
'../gpu/include/GrTLList.h',
|
||||||
'../gpu/include/GrTypes.h',
|
'../gpu/include/GrTypes.h',
|
||||||
@ -173,13 +172,14 @@
|
|||||||
'../gpu/src/GrRectanizer.cpp',
|
'../gpu/src/GrRectanizer.cpp',
|
||||||
'../gpu/src/GrRedBlackTree.h',
|
'../gpu/src/GrRedBlackTree.h',
|
||||||
'../gpu/src/GrResource.cpp',
|
'../gpu/src/GrResource.cpp',
|
||||||
|
'../gpu/src/GrResourceCache.cpp',
|
||||||
|
'../gpu/src/GrResourceCache.h',
|
||||||
'../gpu/src/GrStencil.cpp',
|
'../gpu/src/GrStencil.cpp',
|
||||||
'../gpu/src/GrTesselatedPathRenderer.cpp',
|
'../gpu/src/GrTesselatedPathRenderer.cpp',
|
||||||
'../gpu/src/GrTextContext.cpp',
|
'../gpu/src/GrTextContext.cpp',
|
||||||
'../gpu/src/GrTextStrike.cpp',
|
'../gpu/src/GrTextStrike.cpp',
|
||||||
'../gpu/src/GrTextStrike_impl.h',
|
'../gpu/src/GrTextStrike_impl.h',
|
||||||
'../gpu/src/GrTexture.cpp',
|
'../gpu/src/GrTexture.cpp',
|
||||||
'../gpu/src/GrTextureCache.cpp',
|
|
||||||
'../gpu/src/gr_unittests.cpp',
|
'../gpu/src/gr_unittests.cpp',
|
||||||
|
|
||||||
'../gpu/src/mac/GrGLDefaultInterface_mac.cpp',
|
'../gpu/src/mac/GrGLDefaultInterface_mac.cpp',
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "SkBitmap.h"
|
#include "SkBitmap.h"
|
||||||
#include "SkDevice.h"
|
#include "SkDevice.h"
|
||||||
#include "SkRegion.h"
|
#include "SkRegion.h"
|
||||||
|
#include "GrContext.h"
|
||||||
|
|
||||||
struct SkDrawProcs;
|
struct SkDrawProcs;
|
||||||
struct GrSkDrawProcs;
|
struct GrSkDrawProcs;
|
||||||
@ -126,18 +127,16 @@ public:
|
|||||||
virtual void makeRenderTargetCurrent();
|
virtual void makeRenderTargetCurrent();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
typedef GrContext::TextureCacheEntry TexCache;
|
||||||
class TexCache;
|
|
||||||
enum TexType {
|
enum TexType {
|
||||||
kBitmap_TexType,
|
kBitmap_TexType,
|
||||||
kDeviceRenderTarget_TexType,
|
kDeviceRenderTarget_TexType,
|
||||||
kSaveLayerDeviceRenderTarget_TexType
|
kSaveLayerDeviceRenderTarget_TexType
|
||||||
};
|
};
|
||||||
TexCache* lockCachedTexture(const SkBitmap& bitmap,
|
TexCache lockCachedTexture(const SkBitmap& bitmap,
|
||||||
const GrSamplerState& sampler,
|
const GrSamplerState& sampler,
|
||||||
GrTexture** texture,
|
TexType type = kBitmap_TexType);
|
||||||
TexType type = kBitmap_TexType);
|
void unlockCachedTexture(TexCache);
|
||||||
void unlockCachedTexture(TexCache*);
|
|
||||||
|
|
||||||
class SkAutoCachedTexture {
|
class SkAutoCachedTexture {
|
||||||
public:
|
public:
|
||||||
@ -152,7 +151,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
SkGpuDevice* fDevice;
|
SkGpuDevice* fDevice;
|
||||||
TexCache* fTex;
|
TexCache fTex;
|
||||||
};
|
};
|
||||||
friend class SkAutoTexCache;
|
friend class SkAutoTexCache;
|
||||||
|
|
||||||
@ -162,11 +161,11 @@ private:
|
|||||||
GrSkDrawProcs* fDrawProcs;
|
GrSkDrawProcs* fDrawProcs;
|
||||||
|
|
||||||
// state for our offscreen render-target
|
// state for our offscreen render-target
|
||||||
TexCache* fCache;
|
TexCache fCache;
|
||||||
GrTexture* fTexture;
|
GrTexture* fTexture;
|
||||||
GrRenderTarget* fRenderTarget;
|
GrRenderTarget* fRenderTarget;
|
||||||
bool fNeedClear;
|
bool fNeedClear;
|
||||||
bool fNeedPrepareRenderTarget;
|
bool fNeedPrepareRenderTarget;
|
||||||
|
|
||||||
// called from rt and tex cons
|
// called from rt and tex cons
|
||||||
void initFromRenderTarget(GrContext*, GrRenderTarget*);
|
void initFromRenderTarget(GrContext*, GrRenderTarget*);
|
||||||
|
@ -231,10 +231,11 @@ private:
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Helper functions
|
// Helper functions
|
||||||
|
|
||||||
GrTextureEntry* sk_gr_create_bitmap_texture(GrContext* ctx,
|
static const GrContext::TextureKey gUNCACHED_KEY = ~0;
|
||||||
GrTextureKey* key,
|
GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx,
|
||||||
const GrSamplerState& sampler,
|
GrContext::TextureKey key,
|
||||||
const SkBitmap& bitmap);
|
const GrSamplerState& sampler,
|
||||||
|
const SkBitmap& bitmap);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -67,34 +67,33 @@ SkGpuDevice::SkAutoCachedTexture::
|
|||||||
const GrSamplerState& sampler,
|
const GrSamplerState& sampler,
|
||||||
GrTexture** texture) {
|
GrTexture** texture) {
|
||||||
GrAssert(texture);
|
GrAssert(texture);
|
||||||
fTex = NULL;
|
|
||||||
*texture = this->set(device, bitmap, sampler);
|
*texture = this->set(device, bitmap, sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkGpuDevice::SkAutoCachedTexture::SkAutoCachedTexture() {
|
SkGpuDevice::SkAutoCachedTexture::SkAutoCachedTexture() {
|
||||||
fTex = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTexture* SkGpuDevice::SkAutoCachedTexture::set(SkGpuDevice* device,
|
GrTexture* SkGpuDevice::SkAutoCachedTexture::set(SkGpuDevice* device,
|
||||||
const SkBitmap& bitmap,
|
const SkBitmap& bitmap,
|
||||||
const GrSamplerState& sampler) {
|
const GrSamplerState& sampler) {
|
||||||
if (fTex) {
|
if (fTex.texture()) {
|
||||||
fDevice->unlockCachedTexture(fTex);
|
fDevice->unlockCachedTexture(fTex);
|
||||||
}
|
}
|
||||||
fDevice = device;
|
fDevice = device;
|
||||||
GrTexture* texture = (GrTexture*)bitmap.getTexture();
|
GrTexture* texture = (GrTexture*)bitmap.getTexture();
|
||||||
if (texture) {
|
if (texture) {
|
||||||
// return the native texture
|
// return the native texture
|
||||||
fTex = NULL;
|
fTex.reset();
|
||||||
} else {
|
} else {
|
||||||
// look it up in our cache
|
// look it up in our cache
|
||||||
fTex = device->lockCachedTexture(bitmap, sampler, &texture);
|
fTex = device->lockCachedTexture(bitmap, sampler);
|
||||||
|
texture = fTex.texture();
|
||||||
}
|
}
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkGpuDevice::SkAutoCachedTexture::~SkAutoCachedTexture() {
|
SkGpuDevice::SkAutoCachedTexture::~SkAutoCachedTexture() {
|
||||||
if (fTex) {
|
if (fTex.texture()) {
|
||||||
fDevice->unlockCachedTexture(fTex);
|
fDevice->unlockCachedTexture(fTex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +169,6 @@ void SkGpuDevice::initFromRenderTarget(GrContext* context,
|
|||||||
fContext = context;
|
fContext = context;
|
||||||
fContext->ref();
|
fContext->ref();
|
||||||
|
|
||||||
fCache = NULL;
|
|
||||||
fTexture = NULL;
|
fTexture = NULL;
|
||||||
fRenderTarget = NULL;
|
fRenderTarget = NULL;
|
||||||
fNeedClear = false;
|
fNeedClear = false;
|
||||||
@ -199,7 +197,6 @@ SkGpuDevice::SkGpuDevice(GrContext* context, SkBitmap::Config config, int width,
|
|||||||
fContext = context;
|
fContext = context;
|
||||||
fContext->ref();
|
fContext->ref();
|
||||||
|
|
||||||
fCache = NULL;
|
|
||||||
fTexture = NULL;
|
fTexture = NULL;
|
||||||
fRenderTarget = NULL;
|
fRenderTarget = NULL;
|
||||||
fNeedClear = false;
|
fNeedClear = false;
|
||||||
@ -214,10 +211,9 @@ SkGpuDevice::SkGpuDevice(GrContext* context, SkBitmap::Config config, int width,
|
|||||||
TexType type = (kSaveLayer_Usage == usage) ?
|
TexType type = (kSaveLayer_Usage == usage) ?
|
||||||
kSaveLayerDeviceRenderTarget_TexType :
|
kSaveLayerDeviceRenderTarget_TexType :
|
||||||
kDeviceRenderTarget_TexType;
|
kDeviceRenderTarget_TexType;
|
||||||
fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(),
|
fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(), type);
|
||||||
&fTexture, type);
|
fTexture = fCache.texture();
|
||||||
if (fCache) {
|
if (fTexture) {
|
||||||
SkASSERT(NULL != fTexture);
|
|
||||||
SkASSERT(NULL != fTexture->asRenderTarget());
|
SkASSERT(NULL != fTexture->asRenderTarget());
|
||||||
// hold a ref directly on fTexture (even though fCache has one) to match
|
// hold a ref directly on fTexture (even though fCache has one) to match
|
||||||
// other constructor paths. Simplifies cleanup.
|
// other constructor paths. Simplifies cleanup.
|
||||||
@ -260,10 +256,10 @@ SkGpuDevice::~SkGpuDevice() {
|
|||||||
|
|
||||||
SkSafeUnref(fTexture);
|
SkSafeUnref(fTexture);
|
||||||
SkSafeUnref(fRenderTarget);
|
SkSafeUnref(fRenderTarget);
|
||||||
if (fCache) {
|
if (fCache.texture()) {
|
||||||
GrAssert(NULL != fTexture);
|
GrAssert(NULL != fTexture);
|
||||||
GrAssert(fRenderTarget == fTexture->asRenderTarget());
|
GrAssert(fRenderTarget == fTexture->asRenderTarget());
|
||||||
fContext->unlockTexture((GrTextureEntry*)fCache);
|
fContext->unlockTexture(fCache);
|
||||||
}
|
}
|
||||||
fContext->unref();
|
fContext->unref();
|
||||||
}
|
}
|
||||||
@ -895,15 +891,13 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
|||||||
kRGBA_8888_GrPixelConfig
|
kRGBA_8888_GrPixelConfig
|
||||||
};
|
};
|
||||||
|
|
||||||
GrTextureEntry* srcEntry = context->findApproximateKeylessTexture(desc);
|
GrAutoScratchTexture srcEntry(context, desc);
|
||||||
GrTextureEntry* dstEntry = context->findApproximateKeylessTexture(desc);
|
GrAutoScratchTexture dstEntry(context, desc);
|
||||||
GrAutoUnlockTextureEntry srcLock(context, srcEntry),
|
if (NULL == srcEntry.texture() || NULL == dstEntry.texture()) {
|
||||||
dstLock(context, dstEntry);
|
|
||||||
if (NULL == srcEntry || NULL == dstEntry) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
GrTexture* srcTexture = srcEntry->texture();
|
GrTexture* srcTexture = srcEntry.texture();
|
||||||
GrTexture* dstTexture = dstEntry->texture();
|
GrTexture* dstTexture = dstEntry.texture();
|
||||||
if (NULL == srcTexture || NULL == dstTexture) {
|
if (NULL == srcTexture || NULL == dstTexture) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -939,18 +933,18 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
|||||||
paint.reset();
|
paint.reset();
|
||||||
paint.getTextureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
|
paint.getTextureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
|
||||||
paint.getTextureSampler(0)->setMatrix(sampleM);
|
paint.getTextureSampler(0)->setMatrix(sampleM);
|
||||||
GrTextureEntry* origEntry = NULL;
|
GrAutoScratchTexture origEntry;
|
||||||
|
|
||||||
if (blurType != SkMaskFilter::kNormal_BlurType) {
|
if (blurType != SkMaskFilter::kNormal_BlurType) {
|
||||||
// Stash away a copy of the unblurred image.
|
// Stash away a copy of the unblurred image.
|
||||||
origEntry = context->findApproximateKeylessTexture(desc);
|
origEntry.set(context, desc);
|
||||||
if (NULL == origEntry) {
|
if (NULL == origEntry.texture()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
context->setRenderTarget(origEntry->texture()->asRenderTarget());
|
context->setRenderTarget(origEntry.texture()->asRenderTarget());
|
||||||
paint.setTexture(0, srcTexture);
|
paint.setTexture(0, srcTexture);
|
||||||
context->drawRect(paint, srcRect);
|
context->drawRect(paint, srcRect);
|
||||||
}
|
}
|
||||||
GrAutoUnlockTextureEntry origLock(context, origEntry);
|
|
||||||
for (int i = 1; i < scaleFactor; i *= 2) {
|
for (int i = 1; i < scaleFactor; i *= 2) {
|
||||||
sampleM.setIDiv(srcTexture->width(), srcTexture->height());
|
sampleM.setIDiv(srcTexture->width(), srcTexture->height());
|
||||||
paint.getTextureSampler(0)->setMatrix(sampleM);
|
paint.getTextureSampler(0)->setMatrix(sampleM);
|
||||||
@ -1011,7 +1005,7 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (blurType != SkMaskFilter::kNormal_BlurType) {
|
if (blurType != SkMaskFilter::kNormal_BlurType) {
|
||||||
GrTexture* origTexture = origEntry->texture();
|
GrTexture* origTexture = origEntry.texture();
|
||||||
paint.getTextureSampler(0)->setFilter(GrSamplerState::kNearest_Filter);
|
paint.getTextureSampler(0)->setFilter(GrSamplerState::kNearest_Filter);
|
||||||
sampleM.setIDiv(origTexture->width(), origTexture->height());
|
sampleM.setIDiv(origTexture->width(), origTexture->height());
|
||||||
paint.getTextureSampler(0)->setMatrix(sampleM);
|
paint.getTextureSampler(0)->setMatrix(sampleM);
|
||||||
@ -1102,9 +1096,8 @@ static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
|
|||||||
kAlpha_8_GrPixelConfig
|
kAlpha_8_GrPixelConfig
|
||||||
};
|
};
|
||||||
|
|
||||||
GrAutoUnlockTextureEntry aute(context,
|
GrAutoScratchTexture ast(context, desc);
|
||||||
context->findApproximateKeylessTexture(desc));
|
GrTexture* texture = ast.texture();
|
||||||
GrTexture* texture = aute.texture();
|
|
||||||
|
|
||||||
if (NULL == texture) {
|
if (NULL == texture) {
|
||||||
return false;
|
return false;
|
||||||
@ -1723,12 +1716,10 @@ bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
|
SkGpuDevice::TexCache SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
|
||||||
const GrSamplerState& sampler,
|
const GrSamplerState& sampler,
|
||||||
GrTexture** texture,
|
TexType type) {
|
||||||
TexType type) {
|
GrContext::TextureCacheEntry entry;
|
||||||
GrTexture* newTexture = NULL;
|
|
||||||
GrTextureEntry* entry = NULL;
|
|
||||||
GrContext* ctx = this->context();
|
GrContext* ctx = this->context();
|
||||||
|
|
||||||
if (kBitmap_TexType != type) {
|
if (kBitmap_TexType != type) {
|
||||||
@ -1739,46 +1730,41 @@ SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
|
|||||||
bitmap.height(),
|
bitmap.height(),
|
||||||
SkGr::Bitmap2PixelConfig(bitmap)
|
SkGr::Bitmap2PixelConfig(bitmap)
|
||||||
};
|
};
|
||||||
|
GrContext::ScratchTexMatch match;
|
||||||
if (kSaveLayerDeviceRenderTarget_TexType == type) {
|
if (kSaveLayerDeviceRenderTarget_TexType == type) {
|
||||||
// we know layers will only be drawn through drawDevice.
|
// we know layers will only be drawn through drawDevice.
|
||||||
// drawDevice has been made to work with content embedded in a
|
// drawDevice has been made to work with content embedded in a
|
||||||
// larger texture so its okay to use the approximate version.
|
// larger texture so its okay to use the approximate version.
|
||||||
entry = ctx->findApproximateKeylessTexture(desc);
|
match = GrContext::kApprox_ScratchTexMatch;
|
||||||
} else {
|
} else {
|
||||||
SkASSERT(kDeviceRenderTarget_TexType == type);
|
SkASSERT(kDeviceRenderTarget_TexType == type);
|
||||||
entry = ctx->lockKeylessTexture(desc);
|
match = GrContext::kExact_ScratchTexMatch;
|
||||||
}
|
}
|
||||||
|
entry = ctx->lockScratchTexture(desc, match);
|
||||||
} else {
|
} else {
|
||||||
if (!bitmap.isVolatile()) {
|
if (!bitmap.isVolatile()) {
|
||||||
uint32_t p0, p1;
|
GrContext::TextureKey key = bitmap.getGenerationID();
|
||||||
p0 = bitmap.getGenerationID();
|
key |= ((uint64_t) bitmap.pixelRefOffset()) << 32;
|
||||||
p1 = bitmap.pixelRefOffset();
|
|
||||||
GrTextureKey key(p0, p1, bitmap.width(), bitmap.height());
|
|
||||||
|
|
||||||
entry = ctx->findAndLockTexture(&key, sampler);
|
entry = ctx->findAndLockTexture(key, bitmap.width(),
|
||||||
if (NULL == entry)
|
bitmap.height(), sampler);
|
||||||
entry = sk_gr_create_bitmap_texture(ctx, &key, sampler,
|
if (NULL == entry.texture()) {
|
||||||
|
entry = sk_gr_create_bitmap_texture(ctx, key, sampler,
|
||||||
bitmap);
|
bitmap);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
entry = sk_gr_create_bitmap_texture(ctx, NULL, sampler, bitmap);
|
entry = sk_gr_create_bitmap_texture(ctx, gUNCACHED_KEY, sampler, bitmap);
|
||||||
}
|
}
|
||||||
if (NULL == entry) {
|
if (NULL == entry.texture()) {
|
||||||
GrPrintf("---- failed to create texture for cache [%d %d]\n",
|
GrPrintf("---- failed to create texture for cache [%d %d]\n",
|
||||||
bitmap.width(), bitmap.height());
|
bitmap.width(), bitmap.height());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return entry;
|
||||||
if (NULL != entry) {
|
|
||||||
newTexture = entry->texture();
|
|
||||||
if (texture) {
|
|
||||||
*texture = newTexture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (TexCache*)entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkGpuDevice::unlockCachedTexture(TexCache* cache) {
|
void SkGpuDevice::unlockCachedTexture(TexCache cache) {
|
||||||
this->context()->unlockTexture((GrTextureEntry*)cache);
|
this->context()->unlockTexture(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkDevice* SkGpuDevice::onCreateCompatibleDevice(SkBitmap::Config config,
|
SkDevice* SkGpuDevice::onCreateCompatibleDevice(SkBitmap::Config config,
|
||||||
|
@ -63,13 +63,15 @@ static void build_compressed_data(void* buffer, const SkBitmap& bitmap) {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GrTextureEntry* sk_gr_create_bitmap_texture(GrContext* ctx,
|
GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx,
|
||||||
GrTextureKey* key,
|
GrContext::TextureKey key,
|
||||||
const GrSamplerState& sampler,
|
const GrSamplerState& sampler,
|
||||||
const SkBitmap& origBitmap) {
|
const SkBitmap& origBitmap) {
|
||||||
SkAutoLockPixels alp(origBitmap);
|
SkAutoLockPixels alp(origBitmap);
|
||||||
|
GrContext::TextureCacheEntry entry;
|
||||||
|
|
||||||
if (!origBitmap.readyToDraw()) {
|
if (!origBitmap.readyToDraw()) {
|
||||||
return NULL;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkBitmap tmpBitmap;
|
SkBitmap tmpBitmap;
|
||||||
@ -98,12 +100,13 @@ GrTextureEntry* sk_gr_create_bitmap_texture(GrContext* ctx,
|
|||||||
// our compressed data will be trimmed, so pass width() for its
|
// our compressed data will be trimmed, so pass width() for its
|
||||||
// "rowBytes", since they are the same now.
|
// "rowBytes", since they are the same now.
|
||||||
|
|
||||||
if (NULL != key) {
|
if (gUNCACHED_KEY != key) {
|
||||||
return ctx->createAndLockTexture(key, sampler, desc, storage.get(),
|
return ctx->createAndLockTexture(key, sampler, desc, storage.get(),
|
||||||
bitmap->width());
|
bitmap->width());
|
||||||
} else {
|
} else {
|
||||||
GrTextureEntry* entry = ctx->lockKeylessTexture(desc);
|
entry = ctx->lockScratchTexture(desc,
|
||||||
entry->texture()->uploadTextureData(0, 0, bitmap->width(),
|
GrContext::kExact_ScratchTexMatch);
|
||||||
|
entry.texture()->uploadTextureData(0, 0, bitmap->width(),
|
||||||
bitmap->height(), storage.get(), 0);
|
bitmap->height(), storage.get(), 0);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@ -116,12 +119,14 @@ GrTextureEntry* sk_gr_create_bitmap_texture(GrContext* ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
desc.fFormat = SkGr::Bitmap2PixelConfig(*bitmap);
|
desc.fFormat = SkGr::Bitmap2PixelConfig(*bitmap);
|
||||||
if (NULL != key) {
|
if (gUNCACHED_KEY != key) {
|
||||||
return ctx->createAndLockTexture(key, sampler, desc,
|
return ctx->createAndLockTexture(key, sampler, desc,
|
||||||
bitmap->getPixels(), bitmap->rowBytes());
|
bitmap->getPixels(),
|
||||||
|
bitmap->rowBytes());
|
||||||
} else {
|
} else {
|
||||||
GrTextureEntry* entry = ctx->lockKeylessTexture(desc);
|
entry = ctx->lockScratchTexture(desc,
|
||||||
entry->texture()->uploadTextureData(0, 0, bitmap->width(),
|
GrContext::kExact_ScratchTexMatch);
|
||||||
|
entry.texture()->uploadTextureData(0, 0, bitmap->width(),
|
||||||
bitmap->height(), bitmap->getPixels(), bitmap->rowBytes());
|
bitmap->height(), bitmap->getPixels(), bitmap->rowBytes());
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user