Reapply r5101 and r5102: Made gradient effects use GrTextureStripAtlas.
git-svn-id: http://skia.googlecode.com/svn/trunk@5192 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
f0fed9f978
commit
b3e50f23c5
@ -672,20 +672,38 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
#include "effects/GrTextureStripAtlas.h"
|
||||
#include "SkGr.h"
|
||||
|
||||
GrGLGradientStage::GrGLGradientStage(const GrProgramStageFactory& factory)
|
||||
: INHERITED(factory) { }
|
||||
: INHERITED(factory)
|
||||
, fCachedYCoord(GR_ScalarMax)
|
||||
, fFSYUni(GrGLUniformManager::kInvalidUniformHandle) { }
|
||||
|
||||
GrGLGradientStage::~GrGLGradientStage() { }
|
||||
|
||||
void GrGLGradientStage::setupVariables(GrGLShaderBuilder* builder) {
|
||||
fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
||||
kFloat_GrSLType, "GradientYCoordFS");
|
||||
}
|
||||
|
||||
void GrGLGradientStage::setData(const GrGLUniformManager& uman,
|
||||
const GrCustomStage& stage,
|
||||
const GrRenderTarget*,
|
||||
int stageNum) {
|
||||
GrScalar yCoord = static_cast<const GrGradientEffect&>(stage).getYCoord();
|
||||
if (yCoord != fCachedYCoord) {
|
||||
uman.set1f(fFSYUni, yCoord);
|
||||
fCachedYCoord = yCoord;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGradientStage::emitColorLookup(GrGLShaderBuilder* builder,
|
||||
const char* tName,
|
||||
const char* outputColor,
|
||||
const char* samplerName) {
|
||||
// Texture is effectively 1D so the y coordinate is 0.5, if we pack multiple
|
||||
// gradients into a texture, we could instead pick the appropriate row here
|
||||
builder->fSampleCoords.printf("vec2(%s, 0.5)", tName);
|
||||
builder->fSampleCoords.printf("vec2(%s, %s)", tName,
|
||||
builder->getUniformVariable(fFSYUni).c_str());
|
||||
builder->fComplexCoord = true;
|
||||
builder->emitDefaultFetch(outputColor, samplerName);
|
||||
}
|
||||
@ -696,7 +714,7 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
|
||||
const SkGradientShaderBase& shader,
|
||||
GrSamplerState* sampler)
|
||||
: fTexture (NULL)
|
||||
, fUseTexture (false) {
|
||||
, fUseTexture (true) {
|
||||
// TODO: check for simple cases where we don't need a texture:
|
||||
//GradientInfo info;
|
||||
//shader.asAGradient(&info);
|
||||
@ -705,19 +723,38 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
|
||||
SkBitmap bitmap;
|
||||
shader.getGradientTableBitmap(&bitmap);
|
||||
|
||||
fTexture = GrLockCachedBitmapTexture(ctx, bitmap,
|
||||
sampler->textureParams());
|
||||
SkSafeRef(fTexture);
|
||||
fUseTexture = true;
|
||||
|
||||
// Unlock immediately, this is not great, but we don't have a way of
|
||||
// knowing when else to unlock it currently, so it may get purged from
|
||||
// the cache, but it'll still be ref'd until it's no longer being used.
|
||||
GrUnlockCachedBitmapTexture(fTexture);
|
||||
GrTextureStripAtlas::Desc desc;
|
||||
desc.fWidth = bitmap.width();
|
||||
desc.fHeight = 32;
|
||||
desc.fRowHeight = bitmap.height();
|
||||
desc.fContext = ctx;
|
||||
desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config());
|
||||
fAtlas = GrTextureStripAtlas::GetAtlas(desc);
|
||||
GrAssert(NULL != fAtlas);
|
||||
|
||||
fRow = fAtlas->lockRow(bitmap);
|
||||
if (-1 != fRow) {
|
||||
fYCoord = fAtlas->getYOffset(fRow) + GR_ScalarHalf *
|
||||
fAtlas->getVerticalScaleFactor();
|
||||
fTexture = fAtlas->getTexture();
|
||||
} else {
|
||||
fTexture = GrLockCachedBitmapTexture(ctx, bitmap, sampler->textureParams());
|
||||
SkSafeRef(fTexture);
|
||||
fYCoord = GR_ScalarHalf;
|
||||
|
||||
// Unlock immediately, this is not great, but we don't have a way of
|
||||
// knowing when else to unlock it currently, so it may get purged from
|
||||
// the cache, but it'll still be ref'd until it's no longer being used.
|
||||
GrUnlockCachedBitmapTexture(fTexture);
|
||||
}
|
||||
}
|
||||
|
||||
GrGradientEffect::~GrGradientEffect() {
|
||||
SkSafeUnref(fTexture);
|
||||
if (this->useAtlas()) {
|
||||
fAtlas->unlockRow(fRow);
|
||||
} else {
|
||||
SkSafeUnref(fTexture);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int GrGradientEffect::numTextures() const {
|
||||
|
@ -220,6 +220,8 @@ class GrProgramStageFactory;
|
||||
* determines the gradient value.
|
||||
*/
|
||||
|
||||
class GrTextureStripAtlas;
|
||||
|
||||
// Base class for Gr gradient effects
|
||||
class GrGradientEffect : public GrCustomStage {
|
||||
public:
|
||||
@ -233,6 +235,14 @@ public:
|
||||
GrTexture* texture(unsigned int index) const;
|
||||
|
||||
bool useTexture() const { return fUseTexture; }
|
||||
bool useAtlas() const { return SkToBool(-1 != fRow); }
|
||||
GrScalar getYCoord() const { GrAssert(fUseTexture); return fYCoord; };
|
||||
|
||||
bool isEqual(const GrCustomStage& stage) const {
|
||||
const GrGradientEffect& s = static_cast<const GrGradientEffect&>(stage);
|
||||
return INHERITED::isEqual(stage) && this->useAtlas() == s.useAtlas() &&
|
||||
fYCoord == s.getYCoord();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@ -252,6 +262,9 @@ protected:
|
||||
private:
|
||||
GrTexture* fTexture;
|
||||
bool fUseTexture;
|
||||
GrScalar fYCoord;
|
||||
GrTextureStripAtlas* fAtlas;
|
||||
int fRow;
|
||||
|
||||
typedef GrCustomStage INHERITED;
|
||||
|
||||
@ -266,6 +279,12 @@ public:
|
||||
GrGLGradientStage(const GrProgramStageFactory& factory);
|
||||
virtual ~GrGLGradientStage();
|
||||
|
||||
virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
|
||||
virtual void setData(const GrGLUniformManager&,
|
||||
const GrCustomStage&,
|
||||
const GrRenderTarget*,
|
||||
int stageNum) SK_OVERRIDE;
|
||||
|
||||
// emit code that gets a fragment's color from an expression for t; for now
|
||||
// this always uses the texture, but for simpler cases we'll be able to lerp
|
||||
void emitColorLookup(GrGLShaderBuilder* builder, const char* t,
|
||||
@ -273,6 +292,9 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
GrScalar fCachedYCoord;
|
||||
GrGLUniformManager::UniformHandle fFSYUni;
|
||||
|
||||
typedef GrGLProgramStage INHERITED;
|
||||
};
|
||||
|
||||
|
@ -468,6 +468,7 @@ GrGLConical2Gradient::GrGLConical2Gradient(
|
||||
}
|
||||
|
||||
void GrGLConical2Gradient::setupVariables(GrGLShaderBuilder* builder) {
|
||||
INHERITED::setupVariables(builder);
|
||||
// 2 copies of uniform array, 1 for each of vertex & fragment shader,
|
||||
// to work around Xoom bug. Doesn't seem to cause performance decrease
|
||||
// in test apps, but need to keep an eye on it.
|
||||
@ -631,8 +632,9 @@ void GrGLConical2Gradient::emitFS(GrGLShaderBuilder* builder,
|
||||
|
||||
void GrGLConical2Gradient::setData(const GrGLUniformManager& uman,
|
||||
const GrCustomStage& baseData,
|
||||
const GrRenderTarget*,
|
||||
const GrRenderTarget* target,
|
||||
int stageNum) {
|
||||
INHERITED::setData(uman, baseData, target, stageNum);
|
||||
const GrConical2Gradient& data =
|
||||
static_cast<const GrConical2Gradient&>(baseData);
|
||||
GrAssert(data.isDegenerate() == fIsDegenerate);
|
||||
|
@ -501,6 +501,7 @@ GrGLRadial2Gradient::GrGLRadial2Gradient(
|
||||
}
|
||||
|
||||
void GrGLRadial2Gradient::setupVariables(GrGLShaderBuilder* builder) {
|
||||
INHERITED::setupVariables(builder);
|
||||
// 2 copies of uniform array, 1 for each of vertex & fragment shader,
|
||||
// to work around Xoom bug. Doesn't seem to cause performance decrease
|
||||
// in test apps, but need to keep an eye on it.
|
||||
@ -606,8 +607,9 @@ void GrGLRadial2Gradient::emitFS(GrGLShaderBuilder* builder,
|
||||
|
||||
void GrGLRadial2Gradient::setData(const GrGLUniformManager& uman,
|
||||
const GrCustomStage& baseData,
|
||||
const GrRenderTarget*,
|
||||
const GrRenderTarget* target,
|
||||
int stageNum) {
|
||||
INHERITED::setData(uman, baseData, target, stageNum);
|
||||
const GrRadial2Gradient& data =
|
||||
static_cast<const GrRadial2Gradient&>(baseData);
|
||||
GrAssert(data.isDegenerate() == fIsDegenerate);
|
||||
|
@ -34,14 +34,8 @@ public:
|
||||
GrTextureStripAtlas* fAtlas;
|
||||
};
|
||||
|
||||
// Ugly way of ensuring that we clean up the atlases on exit
|
||||
struct AtlasEntries {
|
||||
~AtlasEntries() { fEntries.deleteAll(); }
|
||||
SkTDArray<AtlasEntry*> fEntries;
|
||||
};
|
||||
|
||||
GrTextureStripAtlas* GrTextureStripAtlas::GetAtlas(const GrTextureStripAtlas::Desc& desc) {
|
||||
static AtlasEntries gAtlasEntries;
|
||||
static SkTDArray<AtlasEntry> gAtlasEntries;
|
||||
static GrTHashTable<AtlasEntry, AtlasHashKey, 8> gAtlasCache;
|
||||
AtlasHashKey key;
|
||||
key.setKeyData(desc.asKey());
|
||||
@ -49,8 +43,7 @@ GrTextureStripAtlas* GrTextureStripAtlas::GetAtlas(const GrTextureStripAtlas::De
|
||||
if (NULL != entry) {
|
||||
return entry->fAtlas;
|
||||
} else {
|
||||
entry = SkNEW(AtlasEntry);
|
||||
gAtlasEntries.fEntries.push(entry);
|
||||
entry = gAtlasEntries.push();
|
||||
entry->fAtlas = SkNEW_ARGS(GrTextureStripAtlas, (desc));
|
||||
entry->fKey = key;
|
||||
gAtlasCache.insert(key, entry);
|
||||
@ -93,6 +86,7 @@ int GrTextureStripAtlas::lockRow(const SkBitmap& data) {
|
||||
this->removeFromLRU(row);
|
||||
}
|
||||
++row->fLocks;
|
||||
++fLockedRows;
|
||||
|
||||
// Since all the rows are always stored in a contiguous array, we can save the memory
|
||||
// required for storing row numbers and just compute it with some pointer arithmetic
|
||||
@ -104,11 +98,14 @@ int GrTextureStripAtlas::lockRow(const SkBitmap& data) {
|
||||
// We don't have this data cached, so pick the least recently used row to copy into
|
||||
AtlasRow* row = this->getLRU();
|
||||
|
||||
++fLockedRows;
|
||||
|
||||
if (NULL == row) {
|
||||
// force a flush, which should unlock all the rows; then try again
|
||||
fDesc.fContext->flush();
|
||||
row = this->getLRU();
|
||||
if (NULL == row) {
|
||||
--fLockedRows;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -116,8 +113,6 @@ int GrTextureStripAtlas::lockRow(const SkBitmap& data) {
|
||||
this->removeFromLRU(row);
|
||||
|
||||
uint32_t oldKey = row->fKey;
|
||||
row->fKey = key;
|
||||
row->fLocks = 1;
|
||||
|
||||
// If we are writing into a row that already held bitmap data, we need to remove the
|
||||
// reference to that genID which is stored in our sorted table of key values.
|
||||
@ -126,13 +121,15 @@ int GrTextureStripAtlas::lockRow(const SkBitmap& data) {
|
||||
// Find the entry in the list; if it's before the index where we plan on adding the new
|
||||
// entry, we decrement since it will shift elements ahead of it back by one.
|
||||
int oldIndex = this->searchByKey(oldKey);
|
||||
if (oldIndex <= index) {
|
||||
if (oldIndex < index) {
|
||||
--index;
|
||||
}
|
||||
|
||||
fKeyTable.remove(oldIndex);
|
||||
}
|
||||
|
||||
row->fKey = key;
|
||||
row->fLocks = 1;
|
||||
fKeyTable.insert(index, 1, &row);
|
||||
rowNumber = static_cast<int>(row - fRows);
|
||||
|
||||
@ -149,7 +146,6 @@ int GrTextureStripAtlas::lockRow(const SkBitmap& data) {
|
||||
GrContext::kDontFlush_PixelOpsFlag);
|
||||
}
|
||||
|
||||
++fLockedRows;
|
||||
GrAssert(rowNumber >= 0);
|
||||
VALIDATE;
|
||||
return rowNumber;
|
||||
@ -233,12 +229,16 @@ void GrTextureStripAtlas::removeFromLRU(AtlasRow* row) {
|
||||
if (NULL == row->fNext) {
|
||||
GrAssert(row == fLRUBack);
|
||||
fLRUBack = row->fPrev;
|
||||
fLRUBack->fNext = NULL;
|
||||
if (fLRUBack) {
|
||||
fLRUBack->fNext = NULL;
|
||||
}
|
||||
}
|
||||
if (NULL == row->fPrev) {
|
||||
GrAssert(row == fLRUFront);
|
||||
fLRUFront = row->fNext;
|
||||
fLRUFront->fPrev = NULL;
|
||||
if (fLRUFront) {
|
||||
fLRUFront->fPrev = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
row->fNext = NULL;
|
||||
@ -303,8 +303,10 @@ void GrTextureStripAtlas::validate() {
|
||||
GrAssert(fRows[i].fKey == kEmptyAtlasRowKey || this->searchByKey(fRows[i].fKey) >= 0);
|
||||
}
|
||||
|
||||
// Our count of locks should equal the sum of row locks
|
||||
GrAssert(rowLocks == fLockedRows);
|
||||
// Our count of locks should equal the sum of row locks, unless we ran out of rows and flushed,
|
||||
// in which case we'll have one more lock than recorded in the rows (to represent the pending
|
||||
// lock of a row; which ensures we don't unlock the texture prematurely).
|
||||
GrAssert(rowLocks == fLockedRows || rowLocks + 1 == fLockedRows);
|
||||
|
||||
// We should have one lru entry for each free row
|
||||
GrAssert(freeRows == lruCount);
|
||||
|
Loading…
Reference in New Issue
Block a user