aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/effects/gradients
diff options
context:
space:
mode:
Diffstat (limited to 'src/effects/gradients')
-rw-r--r--src/effects/gradients/SkGradientShader.cpp68
-rw-r--r--src/effects/gradients/SkGradientShaderPriv.h22
-rw-r--r--src/effects/gradients/SkTwoPointConicalGradient.cpp4
-rw-r--r--src/effects/gradients/SkTwoPointRadialGradient.cpp4
4 files changed, 81 insertions, 17 deletions
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index a07b38878d..176e6f8868 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -12,6 +12,7 @@
#include "SkTwoPointRadialGradient.h"
#include "SkTwoPointConicalGradient.h"
#include "SkSweepGradient.h"
+#include "effects/GrTextureStripAtlas.h"
SkGradientShaderBase::SkGradientShaderBase(const SkColor colors[], const SkScalar pos[],
int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper) {
@@ -675,17 +676,34 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
#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,20 +723,40 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
SkBitmap bitmap;
shader.getGradientTableBitmap(&bitmap);
- GrContext::TextureCacheEntry entry = GrLockCachedBitmapTexture(ctx, bitmap,
- sampler->textureParams());
- fTexture = entry.texture();
- SkSafeRef(fTexture);
- fUseTexture = true;
+ 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 {
+ GrContext::TextureCacheEntry entry = GrLockCachedBitmapTexture(ctx, bitmap,
+ sampler->textureParams());
+ fTexture = entry.texture();
+ 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(ctx, entry);
+ // 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(ctx, entry);
+ }
}
GrGradientEffect::~GrGradientEffect() {
- SkSafeUnref(fTexture);
+ if (this->useAtlas()) {
+ fAtlas->unlockRow(fRow);
+ } else {
+ SkSafeUnref(fTexture);
+ }
}
unsigned int GrGradientEffect::numTextures() const {
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index 8152d5fb71..4c3b6c777f 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -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;
};
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index 528291bdc1..e1d8cb4d1e 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -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);
diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp
index 441f5a8d09..9d937713fd 100644
--- a/src/effects/gradients/SkTwoPointRadialGradient.cpp
+++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp
@@ -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);