Add lockKeylessTexture() for caching texture without a content key.
Review URL: http://codereview.appspot.com/4440065/
git-svn-id: http://skia.googlecode.com/svn/trunk@1172 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 07d76f8..395eb56 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -91,35 +91,29 @@
*/
GrTextureEntry* createAndLockTexture(GrTextureKey* key,
const GrSamplerState&,
- const GrGpu::TextureDesc&,
+ const GrTextureDesc&,
void* srcData, size_t rowBytes);
/**
+ * Returns a texture matching the desc. It's contents are unknown. Subsequent
+ * 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
+ * unlocked.
+ */
+ GrTextureEntry* lockKeylessTexture(const GrTextureDesc& desc,
+ const GrSamplerState& state);
+
+ /**
* When done with an entry, call unlockTexture(entry) on it, which returns
* it to the cache, where it may be purged.
*/
void unlockTexture(GrTextureEntry* entry);
/**
- * Removes an texture from the cache. This prevents the texture from
- * being found by a subsequent findAndLockTexture() until it is
- * reattached. The entry still counts against the cache's budget and should
- * be reattached when exclusive access is no longer needed.
- */
- void detachCachedTexture(GrTextureEntry*);
-
- /**
- * Reattaches a texture to the cache and unlocks it. Allows it to be found
- * by a subsequent findAndLock or be purged (provided its lock count is
- * now 0.)
- */
- void reattachAndUnlockCachedTexture(GrTextureEntry*);
-
- /**
* Creates a texture that is outside the cache. Does not count against
* cache's budget.
*/
- GrTexture* createUncachedTexture(const GrGpu::TextureDesc&,
+ GrTexture* createUncachedTexture(const GrTextureDesc&,
void* srcData,
size_t rowBytes);
@@ -594,7 +588,9 @@
static void SetPaint(const GrPaint& paint, GrDrawTarget* target);
- bool finalizeTextureKey(GrTextureKey*, const GrSamplerState&) const;
+ bool finalizeTextureKey(GrTextureKey*,
+ const GrSamplerState&,
+ bool keyless) const;
GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index 5bbe85d..1966f22 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -57,61 +57,6 @@
static GrGpu* Create(Engine, Platform3DContext context3D);
/**
- * Used to control the level of antialiasing available for a rendertarget.
- * Anti-alias quality levels depend on the underlying API/GPU capabilities.
- */
- enum AALevels {
- kNone_AALevel, //<! No antialiasing available.
- kLow_AALevel, //<! Low quality antialiased rendering. Actual
- // interpretation is platform-dependent.
- kMed_AALevel, //<! Medium quality antialiased rendering. Actual
- // interpretation is platform-dependent.
- kHigh_AALevel, //<! High quality antialiased rendering. Actual
- // interpretation is platform-dependent.
- };
-
-
- /**
- * Optional bitfield flags that can be passed to createTexture.
- */
- enum TextureFlags {
- kRenderTarget_TextureFlag = 0x1, //<! Creates a texture that can be
- // rendered to by calling
- // GrGpu::setRenderTarget() with
- // GrTexture::asRenderTarget().
- kNoStencil_TextureFlag = 0x2, //<! If the texture is used as a
- // rendertarget but a stencil
- // buffer is not required. Stencil
- // may be required for clipping and
- // path rendering.
- kDynamicUpdate_TextureFlag = 0x4 //!< Hint that the CPU may modify
- // this texture after creation
- };
-
- enum {
- /**
- * For Index8 pixel config, the colortable must be 256 entries
- */
- kColorTableSize = 256 * sizeof(GrColor)
- };
- /**
- * Describes a texture to be created.
- */
- struct TextureDesc {
- uint32_t fFlags; //!< bitfield of TextureFlags
- GrGpu::AALevels fAALevel;//!< The level of antialiasing available
- // for a rendertarget texture. Only
- // flags contains
- // kRenderTarget_TextureFlag.
- uint32_t fWidth; //!< Width of the texture
- uint32_t fHeight; //!< Height of the texture
- GrPixelConfig fFormat; //!< Format of source data of the
- // texture. Not guaraunteed to be the
- // same as internal format used by
- // 3D API.
- };
-
- /**
* Gpu usage statistics.
*/
struct Stats {
@@ -180,7 +125,7 @@
*
* @return The texture object if successful, otherwise NULL.
*/
- GrTexture* createTexture(const TextureDesc& desc,
+ GrTexture* createTexture(const GrTextureDesc& desc,
const void* srcData, size_t rowBytes);
/**
* Wraps an externally-created rendertarget in a GrRenderTarget.
@@ -490,7 +435,7 @@
virtual void resetContext() = 0;
// overridden by API-specific derived class to create objects.
- virtual GrTexture* onCreateTexture(const TextureDesc& desc,
+ virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes) = 0;
virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) = 0;
diff --git a/gpu/include/GrTextureCache.h b/gpu/include/GrTextureCache.h
index 466dafa..444ffea 100644
--- a/gpu/include/GrTextureCache.h
+++ b/gpu/include/GrTextureCache.h
@@ -92,6 +92,8 @@
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) {
return (x >> 24) | (x << 8);
}
diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h
index f5bd036..d4cfc10 100644
--- a/gpu/include/GrTypes.h
+++ b/gpu/include/GrTypes.h
@@ -23,6 +23,32 @@
#include <memory.h>
#include <string.h>
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Defines overloaded bitwise operators to make it easier to use an enum as a
+ * bitfield.
+ */
+#define GR_MAKE_BITFIELD_OPS(X) \
+ static inline X operator | (X a, X b) { \
+ return (X) (+a | +b); \
+ } \
+ \
+ static inline X operator & (X a, X b) { \
+ return (X) (+a & +b); \
+ } \
+ template <typename T> \
+ static inline X operator & (T a, X b) { \
+ return (X) (+a & +b); \
+ } \
+ template <typename T> \
+ static inline X operator & (X a, T b) { \
+ return (X) (+a & +b); \
+ } \
+
+////////////////////////////////////////////////////////////////////////////////
+
+
/**
* Macro to round n up to the next multiple of 4, or return it unchanged if
* n is already a multiple of 4
@@ -258,6 +284,71 @@
}
/**
+ * Used to control the level of antialiasing available for a rendertarget.
+ * Anti-alias quality levels depend on the underlying API/GPU capabilities.
+ */
+enum GrAALevels {
+ kNone_GrAALevel, //<! No antialiasing available.
+ kLow_GrAALevel, //<! Low quality antialiased rendering. Actual
+ // interpretation is platform-dependent.
+ kMed_GrAALevel, //<! Medium quality antialiased rendering. Actual
+ // interpretation is platform-dependent.
+ kHigh_GrAALevel, //<! High quality antialiased rendering. Actual
+ // interpretation is platform-dependent.
+};
+
+/**
+ * Optional bitfield flags that can be passed to createTexture.
+ */
+enum GrTextureFlags {
+ kNone_GrTextureFlags = 0x0,
+ /**
+ * Creates a texture that can be rendered to as a GrRenderTarget. Use
+ * GrTexture::asRenderTarget() to access.
+ */
+ kRenderTarget_GrTextureFlagBit = 0x1,
+ /**
+ * By default all render targets have an associated stencil buffer that
+ * may be required for path filling. This flag overrides stencil buffer
+ * creation.
+ * MAKE THIS PRIVATE?
+ */
+ kNoStencil_GrTextureFlagBit = 0x2,
+ /**
+ * Hint that the CPU may modify this texture after creation.
+ */
+ kDynamicUpdate_GrTextureFlagBit = 0x4,
+};
+
+GR_MAKE_BITFIELD_OPS(GrTextureFlags)
+
+enum {
+ /**
+ * For Index8 pixel config, the colortable must be 256 entries
+ */
+ kGrColorTableSize = 256 * 4 //sizeof(GrColor)
+};
+
+/**
+ * Describes a texture to be created.
+ */
+struct GrTextureDesc {
+ GrTextureFlags fFlags; //!< bitfield of TextureFlags
+ /**
+ * The level of antialiasing available for a rendertarget texture. Only used
+ * fFlags contains kRenderTarget_GrTextureFlag.
+ */
+ GrAALevels fAALevel;
+ uint32_t fWidth; //!< Width of the texture
+ uint32_t fHeight; //!< Height of the texture
+ /**
+ * Format of source data of the texture. Not guaraunteed to be the same as
+ * internal format used by 3D API.
+ */
+ GrPixelConfig fFormat;
+};
+
+/**
* Set Operations used to construct clips.
*/
enum GrSetOp {
@@ -411,13 +502,7 @@
kGrCanResolve_GrPlatformRenderTargetFlagBit = 0x2,
};
-static inline GrPlatformRenderTargetFlags operator | (GrPlatformRenderTargetFlags a, GrPlatformRenderTargetFlags b) {
- return (GrPlatformRenderTargetFlags) (+a | +b);
-}
-
-static inline GrPlatformRenderTargetFlags operator & (GrPlatformRenderTargetFlags a, GrPlatformRenderTargetFlags b) {
- return (GrPlatformRenderTargetFlags) (+a & +b);
-}
+GR_MAKE_BITFIELD_OPS(GrPlatformRenderTargetFlags)
// opaque type for 3D API object handles
typedef intptr_t GrPlatform3DObject;
diff --git a/gpu/src/GrAtlas.cpp b/gpu/src/GrAtlas.cpp
index dfc0a69..e577beb 100644
--- a/gpu/src/GrAtlas.cpp
+++ b/gpu/src/GrAtlas.cpp
@@ -175,9 +175,9 @@
GrAssert(0 == kA8_GrMaskFormat);
GrAssert(1 == kA565_GrMaskFormat);
if (NULL == fTexture[format]) {
- GrGpu::TextureDesc desc = {
- GrGpu::kDynamicUpdate_TextureFlag,
- GrGpu::kNone_AALevel,
+ GrTextureDesc desc = {
+ kDynamicUpdate_GrTextureFlagBit,
+ kNone_GrAALevel,
GR_ATLAS_TEXTURE_WIDTH,
GR_ATLAS_TEXTURE_HEIGHT,
maskformat2pixelconfig(format)
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 7cf0cca..75caa74 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -103,9 +103,46 @@
fFontCache->freeAll();
}
+////////////////////////////////////////////////////////////////////////////////
+
+
+enum {
+ kNPOTBit = 0x1,
+ kFilterBit = 0x2,
+ kKeylessBit = 0x4,
+};
+
+bool GrContext::finalizeTextureKey(GrTextureKey* key,
+ const GrSamplerState& sampler,
+ bool keyless) const {
+ uint32_t bits = 0;
+ uint16_t width = key->width();
+ uint16_t height = key->height();
+
+ if (!fGpu->npotTextureTileSupport()) {
+ bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
+
+ bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
+ (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
+
+ if (tiled && !isPow2) {
+ bits |= kNPOTBit;
+ if (sampler.isFilter()) {
+ bits |= kFilterBit;
+ }
+ }
+ }
+
+ if (keyless) {
+ bits |= kKeylessBit;
+ }
+ key->finalize(bits);
+ return 0 != bits;
+}
+
GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
const GrSamplerState& sampler) {
- finalizeTextureKey(key, sampler);
+ finalizeTextureKey(key, sampler, false);
return fTextureCache->findAndLock(*key);
}
@@ -138,7 +175,7 @@
GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
const GrSamplerState& sampler,
- const GrGpu::TextureDesc& desc,
+ const GrTextureDesc& desc,
void* srcData, size_t rowBytes) {
GrAssert(key->width() == desc.fWidth);
GrAssert(key->height() == desc.fHeight);
@@ -148,7 +185,7 @@
#endif
GrTextureEntry* entry = NULL;
- bool special = finalizeTextureKey(key, sampler);
+ bool special = finalizeTextureKey(key, sampler, false);
if (special) {
GrTextureEntry* clampEntry;
GrTextureKey clampKey(*key);
@@ -163,9 +200,10 @@
return NULL;
}
}
- GrGpu::TextureDesc rtDesc = desc;
- rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag |
- GrGpu::kNoStencil_TextureFlag;
+ GrTextureDesc rtDesc = desc;
+ rtDesc.fFlags = rtDesc.fFlags |
+ kRenderTarget_GrTextureFlagBit |
+ kNoStencil_GrTextureFlagBit;
rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth,
fGpu->minRenderTargetWidth()));
rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
@@ -211,7 +249,7 @@
// not. Either implement filtered stretch blit on CPU or just create
// one when FBO case fails.
- rtDesc.fFlags = 0;
+ rtDesc.fFlags = kNone_GrTextureFlags;
// no longer need to clamp at min RT size.
rtDesc.fWidth = GrNextPow2(desc.fWidth);
rtDesc.fHeight = GrNextPow2(desc.fHeight);
@@ -243,19 +281,37 @@
return entry;
}
+GrTextureEntry* GrContext::lockKeylessTexture(const GrTextureDesc& desc,
+ const GrSamplerState& state) {
+ uint32_t p0 = desc.fFormat;
+ uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
+ GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight);
+ this->finalizeTextureKey(&key, state, true);
+ GrTextureEntry* entry = fTextureCache->findAndLock(key);
+ if (NULL == entry) {
+ GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
+ if (NULL != texture) {
+ entry = fTextureCache->createAndLock(key, texture);
+ }
+ }
+ // 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;
+}
+
void GrContext::unlockTexture(GrTextureEntry* entry) {
- fTextureCache->unlock(entry);
+ if (kKeylessBit & entry->key().getPrivateBits()) {
+ fTextureCache->reattachAndUnlock(entry);
+ } else {
+ fTextureCache->unlock(entry);
+ }
}
-void GrContext::detachCachedTexture(GrTextureEntry* entry) {
- fTextureCache->detach(entry);
-}
-
-void GrContext::reattachAndUnlockCachedTexture(GrTextureEntry* entry) {
- fTextureCache->reattachAndUnlock(entry);
-}
-
-GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc,
+GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
void* srcData,
size_t rowBytes) {
return fGpu->createTexture(desc, srcData, rowBytes);
@@ -935,8 +991,8 @@
// TODO: when underlying api has a direct way to do this we should use it
// (e.g. glDrawPixels on desktop GL).
- const GrGpu::TextureDesc desc = {
- 0, GrGpu::kNone_AALevel, width, height, config
+ const GrTextureDesc desc = {
+ kNone_GrTextureFlags, kNone_GrAALevel, width, height, config
};
GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
if (NULL == texture) {
@@ -1123,28 +1179,6 @@
#endif
}
-bool GrContext::finalizeTextureKey(GrTextureKey* key,
- const GrSamplerState& sampler) const {
- uint32_t bits = 0;
- uint16_t width = key->width();
- uint16_t height = key->height();
-
-
- if (!fGpu->npotTextureTileSupport()) {
- bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
-
- bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
- (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
-
- if (tiled && !isPow2) {
- bits |= 1;
- bits |= sampler.isFilter() ? 2 : 0;
- }
- }
- key->finalize(bits);
- return 0 != bits;
-}
-
GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
GrDrawTarget* target;
#if DEFER_TEXT_RENDERING
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index c8e2bc7..c05a04a 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -136,7 +136,7 @@
////////////////////////////////////////////////////////////////////////////////
-GrTexture* GrGpu::createTexture(const TextureDesc& desc,
+GrTexture* GrGpu::createTexture(const GrTextureDesc& desc,
const void* srcData, size_t rowBytes) {
this->handleDirtyContext();
return this->onCreateTexture(desc, srcData, rowBytes);
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index f2ec450..b0ec2bc 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -223,10 +223,10 @@
GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
}
- GR_STATIC_ASSERT(0 == kNone_AALevel);
- GR_STATIC_ASSERT(1 == kLow_AALevel);
- GR_STATIC_ASSERT(2 == kMed_AALevel);
- GR_STATIC_ASSERT(3 == kHigh_AALevel);
+ GR_STATIC_ASSERT(0 == kNone_GrAALevel);
+ GR_STATIC_ASSERT(1 == kLow_GrAALevel);
+ GR_STATIC_ASSERT(2 == kMed_GrAALevel);
+ GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
memset(fAASamples, 0, sizeof(fAASamples));
fMSFBOType = kNone_MSFBO;
@@ -268,14 +268,14 @@
GrGLint maxSamples;
GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
if (maxSamples > 1 ) {
- fAASamples[kNone_AALevel] = 0;
- fAASamples[kLow_AALevel] = GrMax(2,
- GrFixedFloorToInt((GR_FixedHalf) *
- maxSamples));
- fAASamples[kMed_AALevel] = GrMax(2,
- GrFixedFloorToInt(((GR_Fixed1*3)/4) *
- maxSamples));
- fAASamples[kHigh_AALevel] = maxSamples;
+ fAASamples[kNone_GrAALevel] = 0;
+ fAASamples[kLow_GrAALevel] = GrMax(2,
+ GrFixedFloorToInt((GR_FixedHalf) *
+ maxSamples));
+ fAASamples[kMed_GrAALevel] = GrMax(2,
+ GrFixedFloorToInt(((GR_Fixed1*3)/4) *
+ maxSamples));
+ fAASamples[kHigh_GrAALevel] = maxSamples;
}
if (gPrintStartupSpew) {
GrPrintf("\tMax Samples: %d\n", maxSamples);
@@ -529,8 +529,10 @@
fHWGeometryState.fIndexBuffer = NULL;
fHWGeometryState.fVertexBuffer = NULL;
+
GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
+
fHWGeometryState.fArrayPtrsDirty = true;
GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
@@ -701,7 +703,7 @@
}
#endif
-GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc,
+GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes) {
@@ -728,7 +730,7 @@
glDesc.fFormat = desc.fFormat;
glDesc.fOwnsID = true;
- bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
+ bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
if (!canBeTexture(desc.fFormat,
&internalFormat,
&glDesc.fUploadFormat,
@@ -738,7 +740,7 @@
GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
GrGLint samples = fAASamples[desc.fAALevel];
- if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
+ if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
GrPrintf("AA RT requested but not supported on this platform.");
}
@@ -815,7 +817,7 @@
GrAssert(desc.fWidth == glDesc.fAllocWidth);
GrAssert(desc.fHeight == glDesc.fAllocHeight);
GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
- kColorTableSize;
+ kGrColorTableSize;
GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
glDesc.fAllocWidth, glDesc.fAllocHeight,
0, imageSize, srcData));
@@ -932,7 +934,7 @@
} else {
rtIDs.fRTFBOID = rtIDs.fTexFBOID;
}
- if (!(kNoStencil_TextureFlag & desc.fFlags)) {
+ if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
GrAssert(0 != rtIDs.fStencilRenderbufferID);
}
@@ -1079,7 +1081,7 @@
fHWDrawState.fRenderTarget = NULL;
// clear the new stencil buffer if we have one
- if (!(desc.fFlags & kNoStencil_TextureFlag)) {
+ if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
fCurrDrawState.fRenderTarget = rt;
this->clearStencil(0, ~0);
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index 08edb27..918ab80 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -72,7 +72,7 @@
// overrides from GrGpu
virtual void resetContext();
- virtual GrTexture* onCreateTexture(const TextureDesc& desc,
+ virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes);
virtual GrVertexBuffer* onCreateVertexBuffer(uint32_t size,