Add color filters to gpu path.
git-svn-id: http://skia.googlecode.com/svn/trunk@1297 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
0faac1e857
commit
97c88c255c
@ -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;
|
||||
@ -311,6 +318,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).
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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[] = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user