aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Scroggo <Scroggo@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-05-11 14:05:25 +0000
committerGravatar Scroggo <Scroggo@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-05-11 14:05:25 +0000
commit97c88c255cff3dbb8343c5d090526fdbedad6dd6 (patch)
tree018288372381d57dfd8eef285be5d7354067e926
parent0faac1e8579088a39f38d02ff675f14d7deb608d (diff)
Add color filters to gpu path.
git-svn-id: http://skia.googlecode.com/svn/trunk@1297 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--gpu/include/GrDrawTarget.h12
-rw-r--r--gpu/include/GrPaint.h14
-rw-r--r--gpu/src/GrContext.cpp1
-rw-r--r--gpu/src/GrDrawTarget.cpp5
-rw-r--r--gpu/src/GrGLProgram.cpp116
-rw-r--r--gpu/src/GrGLProgram.h8
-rw-r--r--gpu/src/GrGpuGLShaders.cpp15
-rw-r--r--gyp/skia.gyp1
-rw-r--r--samplecode/SampleColorFilter.cpp6
-rw-r--r--src/gpu/SkGpuDevice.cpp10
10 files changed, 174 insertions, 14 deletions
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index 6c92071322..e8f1793759 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -26,6 +26,8 @@
#include "GrTexture.h"
#include "GrStencil.h"
+#include "SkXfermode.h"
+
class GrTexture;
class GrClipIterator;
class GrVertexBuffer;
@@ -131,6 +133,9 @@ protected:
// all DrState members should default to something
// valid by the memset
memset(this, 0, sizeof(DrState));
+ // This is an exception to our memset, since it will
+ // result in no change.
+ fColorFilterXfermode = SkXfermode::kDstIn_Mode;
GrAssert((intptr_t)(void*)NULL == 0LL);
GrAssert(fStencilSettings.isDisabled());
}
@@ -144,6 +149,8 @@ protected:
GrRenderTarget* fRenderTarget;
GrColor fColor;
DrawFace fDrawFace;
+ GrColor fColorFilterColor;
+ SkXfermode::Mode fColorFilterXfermode;
GrStencilSettings fStencilSettings;
GrMatrix fViewMatrix;
@@ -312,6 +319,11 @@ public:
void setColor(GrColor);
/**
+ * Add a color filter that can be represented by a color and a mode.
+ */
+ void setColorFilter(GrColor, SkXfermode::Mode);
+
+ /**
* Sets the color to be used for the next draw to be
* (r,g,b,a) = (alpha, alpha, alpha, alpha).
*
diff --git a/gpu/include/GrPaint.h b/gpu/include/GrPaint.h
index 9402209780..3035ca1b67 100644
--- a/gpu/include/GrPaint.h
+++ b/gpu/include/GrPaint.h
@@ -21,6 +21,8 @@
#include "GrColor.h"
#include "GrSamplerState.h"
+#include "SkXfermode.h"
+
/**
* The paint describes how pixels are colored when the context draws to
* them.
@@ -38,6 +40,9 @@ public:
GrSamplerState fSampler;
+ GrColor fColorFilterColor;
+ SkXfermode::Mode fColorFilterXfermode;
+
void setTexture(GrTexture* texture) {
GrSafeRef(texture);
GrSafeUnref(fTexture);
@@ -59,6 +64,9 @@ public:
fColor = paint.fColor;
+ fColorFilterColor = paint.fColorFilterColor;
+ fColorFilterXfermode = paint.fColorFilterXfermode;
+
fSampler = paint.fSampler;
fTexture = paint.fTexture;
GrSafeRef(fTexture);
@@ -74,6 +82,12 @@ public:
resetOptions();
resetColor();
resetTexture();
+ resetColorFilter();
+ }
+
+ void resetColorFilter() {
+ fColorFilterXfermode = SkXfermode::kDst_Mode;
+ fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
}
private:
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 2d93e4bbd6..8cb932b2c4 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -1335,6 +1335,7 @@ void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
target->disableState(GrDrawTarget::kAntialias_StateBit);
}
target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
+ target->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
}
GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 3810043f5e..695a2abdbb 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -380,6 +380,11 @@ void GrDrawTarget::setColor(GrColor c) {
fCurrDrawState.fColor = c;
}
+void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
+ fCurrDrawState.fColorFilterColor = c;
+ fCurrDrawState.fColorFilterXfermode = mode;
+}
+
void GrDrawTarget::setAlpha(uint8_t a) {
this->setColor((a << 24) | (a << 16) | (a << 8) | a);
}
diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp
index abed043735..f89de9b5da 100644
--- a/gpu/src/GrGLProgram.cpp
+++ b/gpu/src/GrGLProgram.cpp
@@ -21,6 +21,8 @@
#include "GrGLEffect.h"
#include "GrMemory.h"
+#include "SkXfermode.h"
+
namespace {
const char* GrPrecision() {
@@ -52,6 +54,7 @@ const char* GrShaderPrecision() {
#define POS_ATTR_NAME "aPosition"
#define COL_ATTR_NAME "aColor"
#define COL_UNI_NAME "uColor"
+#define COL_FILTER_UNI_NAME "uColorFilter"
static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
*s = "aTexCoord";
@@ -174,6 +177,57 @@ void GrGLProgram::doGLPost() const {
}
}
+/**
+ * Create a text coefficient to be used in fragment shader code.
+ */
+static void coefficientString(GrStringBuilder& str, SkXfermode::Coeff coeff,
+ const char* src, const char* dst) {
+ switch (coeff) {
+ case SkXfermode::kZero_Coeff: /** 0 */
+ str = "0.0";
+ break;
+ case SkXfermode::kOne_Coeff: /** 1 */
+ str = "1.0";
+ break;
+ case SkXfermode::kSA_Coeff: /** src alpha */
+ str.appendf("%s.a", src);
+ break;
+ case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
+ str.appendf("(1.0 - %s.a)", src);
+ break;
+ case SkXfermode::kDA_Coeff: /** dst alpha */
+ str.appendf("%s.a", dst);
+ break;
+ case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
+ str.appendf("(1.0 - %s.a)", dst);
+ break;
+ case SkXfermode::kSC_Coeff:
+ str.append(src);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Adds a line to the fragment shader code which modifies the color by
+ * the specified color filter.
+ */
+static void addColorFilter(GrStringBuilder& FSCode, const char * outputVar,
+ SkXfermode::Mode colorFilterXfermode, const char* dstColor) {
+ SkXfermode::Coeff srcCoeff, dstCoeff;
+ bool success = SkXfermode::ModeAsCoeff(colorFilterXfermode,
+ &srcCoeff, &dstCoeff);
+ // We currently do not handle modes that cannot be represented as
+ // coefficients.
+ GrAssert(success);
+ GrStringBuilder srcCoeffStr, dstCoeffStr;
+ coefficientString(srcCoeffStr, srcCoeff, COL_FILTER_UNI_NAME, dstColor);
+ coefficientString(dstCoeffStr, dstCoeff, COL_FILTER_UNI_NAME, dstColor);
+ FSCode.appendf("\t%s = %s*%s + %s*%s;\n", outputVar, srcCoeffStr.c_str(),
+ COL_FILTER_UNI_NAME, dstCoeffStr.c_str(), dstColor);
+}
+
bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const {
ShaderCodeSegments segments;
@@ -230,23 +284,39 @@ bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const {
}
}
+ bool useColorFilter =
+ // The rest of transfer mode color filters have not been implemented
+ fProgramDesc.fColorFilterXfermode <= SkXfermode::kMultiply_Mode
+ // This mode has no effect.
+ && fProgramDesc.fColorFilterXfermode != SkXfermode::kDst_Mode;
+ bool onlyUseColorFilter = useColorFilter
+ && (fProgramDesc.fColorFilterXfermode == SkXfermode::kClear_Mode
+ || fProgramDesc.fColorFilterXfermode == SkXfermode::kSrc_Mode);
+ if (useColorFilter) {
+ // Set up a uniform for the color
+ segments.fFSUnis.append( "uniform vec4 " COL_FILTER_UNI_NAME ";\n");
+ programData->fUniLocations.fColorFilterUni = kUseUniform;
+ }
+
// for each enabled stage figure out what the input coordinates are
// and count the number of stages in use.
const char* stageInCoords[GrDrawTarget::kNumStages];
int numActiveStages = 0;
- for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
- if (fProgramDesc.fStages[s].fEnabled) {
- if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) {
- stageInCoords[s] = POS_ATTR_NAME;
- } else {
- int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout);
- // we better have input tex coordinates if stage is enabled.
- GrAssert(tcIdx >= 0);
- GrAssert(texCoordAttrs[tcIdx].size());
- stageInCoords[s] = texCoordAttrs[tcIdx].c_str();
+ if (!onlyUseColorFilter) {
+ for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
+ if (fProgramDesc.fStages[s].fEnabled) {
+ if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) {
+ stageInCoords[s] = POS_ATTR_NAME;
+ } else {
+ int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout);
+ // we better have input tex coordinates if stage is enabled.
+ GrAssert(tcIdx >= 0);
+ GrAssert(texCoordAttrs[tcIdx].size());
+ stageInCoords[s] = texCoordAttrs[tcIdx].c_str();
+ }
+ ++numActiveStages;
}
- ++numActiveStages;
}
}
@@ -254,10 +324,10 @@ bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const {
// of each to the next and generating code for each stage.
if (numActiveStages) {
int currActiveStage = 0;
+ GrStringBuilder outColor;
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
if (fProgramDesc.fStages[s].fEnabled) {
- GrStringBuilder outColor;
- if (currActiveStage < (numActiveStages - 1)) {
+ if (currActiveStage < (numActiveStages - 1) || useColorFilter) {
outColor = "color";
outColor.appendS32(currActiveStage);
segments.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
@@ -276,9 +346,21 @@ bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const {
inColor = outColor;
}
}
+ if (useColorFilter) {
+ addColorFilter(segments.fFSCode, "gl_FragColor",
+ fProgramDesc.fColorFilterXfermode, outColor.c_str());
+ }
+
} else {
// we may not have any incoming color
- segments.fFSCode.appendf("\tgl_FragColor = %s;\n", (inColor.size() ? inColor.c_str() : "vec4(1,1,1,1);\n"));
+ const char * incomingColor = (inColor.size() ? inColor.c_str()
+ : "vec4(1,1,1,1)");
+ if (useColorFilter) {
+ addColorFilter(segments.fFSCode, "gl_FragColor",
+ fProgramDesc.fColorFilterXfermode, incomingColor);
+ } else {
+ segments.fFSCode.appendf("\tgl_FragColor = %s;\n", incomingColor);
+ }
}
segments.fVSCode.append("}\n");
segments.fFSCode.append("}\n");
@@ -495,6 +577,11 @@ void GrGLProgram::getUniformLocationsAndInitCache(CachedData* programData) const
GR_GL(GetUniformLocation(progID, COL_UNI_NAME));
GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni);
}
+ if (kUseUniform == programData->fUniLocations.fColorFilterUni) {
+ programData->fUniLocations.fColorFilterUni =
+ GR_GL(GetUniformLocation(progID, COL_FILTER_UNI_NAME));
+ GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni);
+ }
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
StageUniLocations& locations = programData->fUniLocations.fStages[s];
@@ -550,6 +637,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(CachedData* programData) const
}
programData->fViewMatrix = GrMatrix::InvalidMatrix();
programData->fColor = GrColor_ILLEGAL;
+ programData->fColorFilterColor = GrColor_ILLEGAL;
}
//============================================================================
diff --git a/gpu/src/GrGLProgram.h b/gpu/src/GrGLProgram.h
index 54818ec9d0..3b926a78c4 100644
--- a/gpu/src/GrGLProgram.h
+++ b/gpu/src/GrGLProgram.h
@@ -21,6 +21,8 @@
#include "GrStringBuilder.h"
#include "GrDrawTarget.h"
+#include "SkXfermode.h"
+
class GrBinHashKeyBuilder;
class GrGLEffect;
struct ShaderCodeSegments;
@@ -107,6 +109,9 @@ private:
bool fEmitsPointSize;
+ GrColor fColorFilterColor;
+ SkXfermode::Mode fColorFilterXfermode;
+
struct StageDesc {
enum OptFlagBits {
kNoPerspective_OptFlagBit = 0x1,
@@ -159,10 +164,12 @@ public:
struct UniLocations {
GrGLint fViewMatrixUni;
GrGLint fColorUni;
+ GrGLint fColorFilterUni;
StageUniLocations fStages[GrDrawTarget::kNumStages];
void reset() {
fViewMatrixUni = kUnusedUniform;
fColorUni = kUnusedUniform;
+ fColorFilterUni = kUnusedUniform;
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
fStages[s].reset();
}
@@ -217,6 +224,7 @@ public:
// these reflect the current values of uniforms
// (GL uniform values travel with program)
GrColor fColor;
+ GrColor fColorFilterColor;
GrMatrix fTextureMatrices[GrDrawTarget::kNumStages];
// width and height used for normalized texel size
int fTextureWidth[GrDrawTarget::kNumStages];
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index 3ce6e55d69..2487563122 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -438,6 +438,19 @@ void GrGpuGLShaders::flushColor() {
GrCrash("Unknown color type.");
}
}
+ if (fProgramData->fUniLocations.fColorFilterUni
+ != GrGLProgram::kUnusedUniform
+ && fProgramData->fColorFilterColor
+ != fCurrDrawState.fColorFilterColor) {
+ float c[] = {
+ GrColorUnpackR(fCurrDrawState.fColorFilterColor) / 255.f,
+ GrColorUnpackG(fCurrDrawState.fColorFilterColor) / 255.f,
+ GrColorUnpackB(fCurrDrawState.fColorFilterColor) / 255.f,
+ GrColorUnpackA(fCurrDrawState.fColorFilterColor) / 255.f
+ };
+ GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
+ fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor;
+ }
}
@@ -693,6 +706,8 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
fCurrentProgram.fStageEffects[s] = NULL;
}
}
+ desc.fColorFilterColor = fCurrDrawState.fColorFilterColor;
+ desc.fColorFilterXfermode = fCurrDrawState.fColorFilterXfermode;
}
diff --git a/gyp/skia.gyp b/gyp/skia.gyp
index 8f228c9241..c37d567aee 100644
--- a/gyp/skia.gyp
+++ b/gyp/skia.gyp
@@ -1424,6 +1424,7 @@
'../samplecode/SampleCamera.cpp',
'../samplecode/SampleCircle.cpp',
'../samplecode/SampleCode.h',
+ '../samplecode/SampleColorFilter.cpp',
'../samplecode/SampleComplexClip.cpp',
'../samplecode/SampleCull.cpp',
'../samplecode/SampleDecode.cpp',
diff --git a/samplecode/SampleColorFilter.cpp b/samplecode/SampleColorFilter.cpp
index 8b1c317e1d..77b64a898b 100644
--- a/samplecode/SampleColorFilter.cpp
+++ b/samplecode/SampleColorFilter.cpp
@@ -91,14 +91,20 @@ protected:
}
static const SkXfermode::Mode gModes[] = {
+ SkXfermode::kClear_Mode,
SkXfermode::kSrc_Mode,
SkXfermode::kDst_Mode,
+ SkXfermode::kSrcOver_Mode,
+ SkXfermode::kDstOver_Mode,
SkXfermode::kSrcIn_Mode,
SkXfermode::kDstIn_Mode,
SkXfermode::kSrcOut_Mode,
SkXfermode::kDstOut_Mode,
SkXfermode::kSrcATop_Mode,
SkXfermode::kDstATop_Mode,
+ SkXfermode::kXor_Mode,
+ SkXfermode::kPlus_Mode,
+ SkXfermode::kMultiply_Mode,
};
static const SkColor gColors[] = {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 8818dc0b06..563dde74e2 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -22,6 +22,7 @@
#include "SkGpuDeviceFactory.h"
#include "SkGrTexturePixelRef.h"
+#include "SkColorFilter.h"
#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkUtils.h"
@@ -368,6 +369,15 @@ bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint,
grPaint->fColor = SkGr::SkColor2GrColor(skPaint.getColor());
grPaint->setTexture(NULL);
}
+ SkColorFilter* colorFilter = skPaint.getColorFilter();
+ SkColor color;
+ SkXfermode::Mode filterMode;
+ if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) {
+ grPaint->fColorFilterColor = SkGr::SkColor2GrColor(color);
+ grPaint->fColorFilterXfermode = filterMode;
+ } else {
+ grPaint->resetColorFilter();
+ }
return true;
}