Implement SkColorFilter as a GrGLEffect

Adds GrEffect::willUseInputColor() which indicates whether or not the
input color affects the output of the effect. This is needed for
certain Xfermodes, such as kSrc_Mode. For these modes the color filter
will not use the input color.

An effect with GrEffect::willUseInputColor() true will cause all color
or coverage effects before it to be discarded, as their computations
cannot affect the output. In these cases program is marked as having
white input color.

This fixes an assert when Skia is compiled in a mode that prefers
using uniforms instead of attributes for constants. (Flags
GR_GL_USE_NV_PATH_RENDERING or GR_GL_NO_CONSTANT_ATTRIBUTES). Using
attributes hides the problem where the fragment shader does not need
input color for color filters that ignore DST part of the filter. The
assert would be hit when uniform manager tries to bind an uniform which
has been optimized away by the shader compiler.

Adds specific GrGLSLExpr4 and GrGLSLExpr1 classes. This way the GLSL
expressions like "(v - src.a)" can remain somewhat readable in form of
"(v - src.a())". The GrGLSLExpr<typename> template implements the
generic functionality, GrGLSLExprX is the specialization that exposes
the type-safe interface to this functionality.

Also adds operators so that GLSL binary operators of the form
"(float * vecX)" can be expressed in C++. Before only the equivalent
"(vecX * float)" was possible. This reverts the common blending
calculations to more conventional order, such as "(1-a) * c" instead of
"c * (1-a)".

Changes GrGLSLExpr1::OnesStr from 1 to 1.0 in order to preserve the
color filter blending formula string the same (with the exception of
variable name change).

Shaders change in case of input color being needed:
 -   vec4 filteredColor;
 -   filteredColor = (((1.0 - uFilterColor.a) * output_Stage0) + uFilterColor);
 -   fsColorOut = filteredColor;
 +   vec4 output_Stage1;
 +   { // Stage 1: ModeColorFilterEffect
 +   output_Stage1 = (((1.0 - uFilterColor_Stage1.a) * output_Stage0) + uFilterColor_Stage1);
 +   }
 +   fsColorOut = output_Stage1;

Shaders change in case of input color being not needed:
 -uniform vec4 uFilterColor;
 -in vec4 vColor;
 +uniform vec4 uFilterColor_Stage0;
  out vec4 fsColorOut;
  void main() {
 -   vec4 filteredColor;
 -   filteredColor = uFilterColor;
 -   fsColorOut = filteredColor;
 +   vec4 output_Stage0;
 +   { // Stage 0: ModeColorFilterEffect
 +   output_Stage0 = uFilterColor_Stage0;
 +   }
 +   fsColorOut = output_Stage0;
  }

R=bsalomon@google.com, robertphillips@google.com, jvanverth@google.com

Author: kkinnunen@nvidia.com

Review URL: https://codereview.chromium.org/25023003

git-svn-id: http://skia.googlecode.com/svn/trunk@11912 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-10-23 05:42:03 +00:00
parent afba64434d
commit a34995e18b
29 changed files with 796 additions and 472 deletions

View File

@ -69,6 +69,7 @@
'../tests/GLInterfaceValidation.cpp',
'../tests/GLProgramsTest.cpp',
'../tests/GpuBitmapCopyTest.cpp',
'../tests/GpuColorFilterTest.cpp',
'../tests/GpuDrawPathTest.cpp',
'../tests/GrContextFactoryTest.cpp',
'../tests/GradientTest.cpp',

View File

@ -95,6 +95,9 @@ public:
*/
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const = 0;
/** Will this effect read the source color value? */
bool willUseInputColor() const { return fWillUseInputColor; }
/** This object, besides creating back-end-specific helper objects, is used for run-time-type-
identification. The factory should be an instance of templated class,
GrTBackendEffectFactory. It is templated on the subclass of GrEffect. The subclass must have
@ -221,6 +224,7 @@ protected:
GrEffect()
: fWillReadDstColor(false)
, fWillReadFragmentPosition(false)
, fWillUseInputColor(true)
, fHasVertexCode(false)
, fEffectRef(NULL) {}
@ -287,6 +291,13 @@ protected:
*/
void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; }
/**
* If the effect will generate a result that does not depend on the input color value then it must
* call this function from its constructor. Otherwise, when its generated backend-specific code
* might fail during variable binding due to unused variables.
*/
void setWillNotUseInputColor() { fWillUseInputColor = false; }
private:
bool isEqual(const GrEffect& other) const {
if (&this->getFactory() != &other.getFactory()) {
@ -321,6 +332,7 @@ private:
SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes;
bool fWillReadDstColor;
bool fWillReadFragmentPosition;
bool fWillUseInputColor;
bool fHasVertexCode;
GrEffectRef* fEffectRef;

View File

@ -84,32 +84,14 @@ public:
void setDither(bool dither) { fDither = dither; }
bool isDither() const { return fDither; }
/**
* Enables a SkXfermode::Mode-based color filter applied to the primitive color. The constant
* color passed to this function is considered the "src" color and the primitive's color is
* considered the "dst" color. Defaults to kDst_Mode which equates to simply passing through
* the primitive color unmodified.
*/
void setXfermodeColorFilter(SkXfermode::Mode mode, GrColor color) {
fColorFilterColor = color;
fColorFilterXfermode = mode;
}
SkXfermode::Mode getColorFilterMode() const { return fColorFilterXfermode; }
GrColor getColorFilterColor() const { return fColorFilterColor; }
/**
* Disables the SkXfermode::Mode color filter.
*/
void resetColorFilter() {
fColorFilterXfermode = SkXfermode::kDst_Mode;
fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
}
/**
* Appends an additional color effect to the color computation.
*/
const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
SkASSERT(NULL != effect);
if (!(*effect)->willUseInputColor()) {
fColorStages.reset();
}
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1));
return effect;
}
@ -119,6 +101,9 @@ public:
*/
const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
SkASSERT(NULL != effect);
if (!(*effect)->willUseInputColor()) {
fCoverageStages.reset();
}
SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1));
return effect;
}
@ -153,9 +138,6 @@ public:
fColor = paint.fColor;
fCoverage = paint.fCoverage;
fColorFilterColor = paint.fColorFilterColor;
fColorFilterXfermode = paint.fColorFilterXfermode;
fColorStages = paint.fColorStages;
fCoverageStages = paint.fCoverageStages;
@ -171,7 +153,6 @@ public:
this->resetColor();
this->resetCoverage();
this->resetStages();
this->resetColorFilter();
}
/**
@ -245,9 +226,6 @@ private:
GrColor fColor;
uint8_t fCoverage;
GrColor fColorFilterColor;
SkXfermode::Mode fColorFilterXfermode;
void resetBlend() {
fSrcBlendCoeff = kOne_GrBlendCoeff;
fDstBlendCoeff = kZero_GrBlendCoeff;

View File

@ -150,7 +150,7 @@ public:
"\t\t}\n");
builder->fsCodeAppendf("color = %s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("color")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("color")).c_str());
}
virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& e) SK_OVERRIDE {

View File

@ -85,6 +85,9 @@ public:
}
#endif
#if SK_SUPPORT_GPU
virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
protected:
@ -117,6 +120,293 @@ private:
typedef SkColorFilter INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
#include "GrBlend.h"
#include "GrEffect.h"
#include "GrEffectUnitTest.h"
#include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h"
#include "SkGr.h"
namespace {
/**
* A definition of blend equation for one coefficient. Generates a
* blend_coeff * value "expression".
*/
template<typename ColorExpr>
static inline ColorExpr blend_term(SkXfermode::Coeff coeff,
const ColorExpr& src,
const ColorExpr& dst,
const ColorExpr& value) {
switch (coeff) {
default:
GrCrash("Unexpected xfer coeff.");
case SkXfermode::kZero_Coeff: /** 0 */
return ColorExpr(0);
case SkXfermode::kOne_Coeff: /** 1 */
return value;
case SkXfermode::kSC_Coeff:
return src * value;
case SkXfermode::kISC_Coeff:
return (ColorExpr(1) - src) * dst;
case SkXfermode::kDC_Coeff:
return dst * value;
case SkXfermode::kIDC_Coeff:
return (ColorExpr(1) - dst) * value;
case SkXfermode::kSA_Coeff: /** src alpha */
return src.a() * value;
case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
return (typename ColorExpr::AExpr(1) - src.a()) * value;
case SkXfermode::kDA_Coeff: /** dst alpha */
return dst.a() * value;
case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
return (typename ColorExpr::AExpr(1) - dst.a()) * value;
}
}
/**
* Creates a color filter expression which modifies the color by
* the specified color filter.
*/
template <typename ColorExpr>
static inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode,
const ColorExpr& filterColor,
const ColorExpr& inColor) {
SkXfermode::Coeff colorCoeff;
SkXfermode::Coeff filterColorCoeff;
SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff));
return blend_term(colorCoeff, filterColor, inColor, inColor) +
blend_term(filterColorCoeff, filterColor, inColor, filterColor);
}
}
class ModeColorFilterEffect : public GrEffect {
public:
static GrEffectRef* Create(const GrColor& c, SkXfermode::Mode mode) {
AutoEffectUnref effect(SkNEW_ARGS(ModeColorFilterEffect, (c, mode)));
return CreateEffectRef(effect);
}
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
bool willUseFilterColor() const {
SkXfermode::Coeff dstCoeff;
SkXfermode::Coeff srcCoeff;
SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
if (SkXfermode::kZero_Coeff == srcCoeff) {
return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff));
}
return true;
}
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
return GrTBackendEffectFactory<ModeColorFilterEffect>::getInstance();
}
static const char* Name() { return "ModeColorFilterEffect"; }
SkXfermode::Mode mode() const { return fMode; }
GrColor color() const { return fColor; }
class GLEffect : public GrGLEffect {
public:
GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
: INHERITED(factory) {
}
virtual void emitCode(GrGLShaderBuilder* builder,
const GrDrawEffect& drawEffect,
EffectKey key,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) SK_OVERRIDE {
SkXfermode::Mode mode = drawEffect.castEffect<ModeColorFilterEffect>().mode();
SkASSERT(SkXfermode::kDst_Mode != mode);
const char* colorFilterColorUniName = NULL;
if (drawEffect.castEffect<ModeColorFilterEffect>().willUseFilterColor()) {
fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "FilterColor",
&colorFilterColorUniName);
}
GrGLSLExpr4 filter =
color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName), GrGLSLExpr4(inputColor));
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
// The SL code does not depend on filter color at the moment, so no need to represent it
// in the key.
EffectKey modeKey = colorModeFilter.mode();
return modeKey;
}
virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE {
if (fFilterColorUni.isValid()) {
const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
GrGLfloat c[4];
GrColorToRGBAFloat(colorModeFilter.color(), c);
uman.set4fv(fFilterColorUni, 0, 1, c);
}
}
private:
GrGLUniformManager::UniformHandle fFilterColorUni;
typedef GrGLEffect INHERITED;
};
GR_DECLARE_EFFECT_TEST;
private:
ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
: fMode(mode),
fColor(color) {
SkXfermode::Coeff dstCoeff;
SkXfermode::Coeff srcCoeff;
SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
// These could be calculated from the blend equation with template trickery..
if (SkXfermode::kZero_Coeff == dstCoeff && !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) {
this->setWillNotUseInputColor();
}
}
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
const ModeColorFilterEffect& s = CastEffect<ModeColorFilterEffect>(other);
return fMode == s.fMode && fColor == s.fColor;
}
SkXfermode::Mode fMode;
GrColor fColor;
typedef GrEffect INHERITED;
};
namespace {
/** Function color_component_to_int tries to reproduce the GLSL rounding. The spec doesn't specify
* to which direction the 0.5 goes.
*/
static inline int color_component_to_int(float value) {
return sk_float_round2int(GrMax(0.f, GrMin(1.f, value)) * 255.f);
}
/** MaskedColorExpr is used to evaluate the color and valid color component flags through the
* blending equation. It has members similar to GrGLSLExpr so that it can be used with the
* templated helpers above.
*/
class MaskedColorExpr {
public:
MaskedColorExpr(const float color[], uint32_t flags)
: fFlags(flags) {
fColor[0] = color[0];
fColor[1] = color[1];
fColor[2] = color[2];
fColor[3] = color[3];
}
MaskedColorExpr(float v, uint32_t flags = kRGBA_GrColorComponentFlags)
: fFlags(flags) {
fColor[0] = v;
fColor[1] = v;
fColor[2] = v;
fColor[3] = v;
}
MaskedColorExpr operator*(const MaskedColorExpr& other) const {
float tmp[4];
tmp[0] = fColor[0] * other.fColor[0];
tmp[1] = fColor[1] * other.fColor[1];
tmp[2] = fColor[2] * other.fColor[2];
tmp[3] = fColor[3] * other.fColor[3];
return MaskedColorExpr(tmp, fFlags & other.fFlags);
}
MaskedColorExpr operator+(const MaskedColorExpr& other) const {
float tmp[4];
tmp[0] = fColor[0] + other.fColor[0];
tmp[1] = fColor[1] + other.fColor[1];
tmp[2] = fColor[2] + other.fColor[2];
tmp[3] = fColor[3] + other.fColor[3];
return MaskedColorExpr(tmp, fFlags & other.fFlags);
}
MaskedColorExpr operator-(const MaskedColorExpr& other) const {
float tmp[4];
tmp[0] = fColor[0] - other.fColor[0];
tmp[1] = fColor[1] - other.fColor[1];
tmp[2] = fColor[2] - other.fColor[2];
tmp[3] = fColor[3] - other.fColor[3];
return MaskedColorExpr(tmp, fFlags & other.fFlags);
}
MaskedColorExpr a() const {
uint32_t flags = (fFlags & kA_GrColorComponentFlag) ? kRGBA_GrColorComponentFlags : 0;
return MaskedColorExpr(fColor[3], flags);
}
GrColor getColor() const {
return GrColorPackRGBA(color_component_to_int(fColor[0]),
color_component_to_int(fColor[1]),
color_component_to_int(fColor[2]),
color_component_to_int(fColor[3]));
}
uint32_t getValidComponents() const { return fFlags; }
typedef MaskedColorExpr AExpr;
private:
float fColor[4];
uint32_t fFlags;
};
}
void ModeColorFilterEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
float inputColor[4];
GrColorToRGBAFloat(*color, inputColor);
float filterColor[4];
GrColorToRGBAFloat(fColor, filterColor);
MaskedColorExpr result =
color_filter_expression(fMode,
MaskedColorExpr(filterColor, kRGBA_GrColorComponentFlags),
MaskedColorExpr(inputColor, *validFlags));
*color = result.getColor();
*validFlags = result.getValidComponents();
}
GR_DEFINE_EFFECT_TEST(ModeColorFilterEffect);
GrEffectRef* ModeColorFilterEffect::TestCreate(SkRandom* rand,
GrContext*,
const GrDrawTargetCaps&,
GrTexture*[]) {
int mode = rand->nextRangeU(0, SkXfermode::kLastCoeffMode);
GrColor color = rand->nextU();
static AutoEffectUnref gEffect(SkNEW_ARGS(ModeColorFilterEffect, (color, static_cast<SkXfermode::Mode>(mode))));
return CreateEffectRef(gEffect);
}
GrEffectRef* SkModeColorFilter::asNewEffect(GrContext*) const {
if (SkXfermode::kDst_Mode != fMode) {
return ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
}
return NULL;
}
#endif
///////////////////////////////////////////////////////////////////////////////
class Src_SkModeColorFilter : public SkModeColorFilter {
public:
Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}

View File

@ -348,6 +348,7 @@ GrDisplacementMapEffect::GrDisplacementMapEffect(
this->addTextureAccess(&fDisplacementAccess);
this->addCoordTransform(&fColorTransform);
this->addTextureAccess(&fColorAccess);
this->setWillNotUseInputColor();
}
GrDisplacementMapEffect::~GrDisplacementMapEffect() {

View File

@ -423,6 +423,7 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) {
sk_ignore_unused_variable(inputColor);
SkString coords2D = builder->ensureFSCoords2D(coords, 0);
fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "Bounds");
@ -548,6 +549,7 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture,
}
fTarget[0] = static_cast<float>(target.x());
fTarget[1] = static_cast<float>(target.y());
this->setWillNotUseInputColor();
}
GrMatrixConvolutionEffect::~GrMatrixConvolutionEffect() {

View File

@ -610,6 +610,7 @@ protected:
m.postTranslate(SK_Scalar1, SK_Scalar1);
fCoordTransform.reset(kLocal_GrCoordSet, m);
this->addCoordTransform(&fCoordTransform);
this->setWillNotUseInputColor();
}
SkPerlinNoiseShader::Type fType;

View File

@ -951,7 +951,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("colorTemp")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
} else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){
builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
gradientTValue);
@ -975,7 +975,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("colorTemp")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
} else {
builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n",
gradientTValue,

View File

@ -564,7 +564,7 @@ public:
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
}

View File

@ -86,7 +86,7 @@ public:
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("coverage")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@ -219,7 +219,7 @@ public:
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("coverage")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {

View File

@ -59,7 +59,6 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
this->setCoverage(paint.getCoverage());
}
@ -219,13 +218,6 @@ bool GrDrawState::srcAlphaWillBeOne() const {
(*effect)->getConstantColorComponents(&color, &validComponentFlags);
}
// Check if the color filter could introduce an alpha.
// We could skip the above work when this is true, but it is rare and the right fix is to make
// the color filter a GrEffect and implement getConstantColorComponents() for it.
if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
validComponentFlags = 0;
}
// Check whether coverage is treated as color. If so we run through the coverage computation.
if (this->isCoverageDrawing()) {
GrColor coverageColor = this->getCoverage();

View File

@ -264,18 +264,6 @@ public:
this->setColor((a << 24) | (a << 16) | (a << 8) | a);
}
/**
* Add a color filter that can be represented by a color and a mode. Applied
* after color-computing effect stages.
*/
void setColorFilter(GrColor c, SkXfermode::Mode mode) {
fCommon.fColorFilterColor = c;
fCommon.fColorFilterMode = mode;
}
GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
/**
* Constructor sets the color to be 'color' which is undone by the destructor.
*/
@ -914,8 +902,6 @@ private:
fCommon.fFlagBits = 0x0;
fCommon.fStencilSettings.setDisabled();
fCommon.fCoverage = 0xffffffff;
fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
fCommon.fColorFilterColor = 0x0;
fCommon.fDrawFace = kBoth_DrawFace;
}
@ -932,8 +918,6 @@ private:
int fVACount;
GrStencilSettings fStencilSettings;
GrColor fCoverage;
SkXfermode::Mode fColorFilterMode;
GrColor fColorFilterColor;
DrawFace fDrawFace;
// This is simply a different representation of info in fVertexAttribs and thus does
@ -951,8 +935,6 @@ private:
!memcmp(fVAPtr, other.fVAPtr, fVACount * sizeof(GrVertexAttrib)) &&
fStencilSettings == other.fStencilSettings &&
fCoverage == other.fCoverage &&
fColorFilterMode == other.fColorFilterMode &&
fColorFilterColor == other.fColorFilterColor &&
fDrawFace == other.fDrawFace;
SkASSERT(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices,
other.fFixedFunctionVertexAttribIndices,

View File

@ -117,7 +117,7 @@ public:
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@ -249,7 +249,7 @@ public:
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@ -407,7 +407,7 @@ public:
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {

View File

@ -56,12 +56,6 @@ bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
// TODO: Share this implementation with GrDrawState
// Since fColorFilterXfermode is going away soon, we aren't attempting to handle anything but
// the default setting.
if (SkXfermode::kDst_Mode != fColorFilterXfermode) {
return false;
}
GrColor coverage = GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
uint32_t coverageComps = kRGBA_GrColorComponentFlags;
int count = fCoverageStages.count();

View File

@ -475,13 +475,6 @@ inline bool skPaint2GrPaintNoShader(SkGpuDevice* dev,
SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(dev->context()));
if (NULL != effect.get()) {
grPaint->addColorEffect(effect);
} else {
// TODO: rewrite this using asNewEffect()
SkColor color;
SkXfermode::Mode filterMode;
if (colorFilter->asColorMode(&color, &filterMode)) {
grPaint->setXfermodeColorFilter(filterMode, SkColor2GrColor(color));
}
}
}
}

View File

@ -111,7 +111,7 @@ void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
GrGLEffect::EffectKey GrGLConicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@ -239,7 +239,7 @@ void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
@ -383,7 +383,7 @@ void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
GrGLEffect::EffectKey GrGLCubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {

View File

@ -44,6 +44,8 @@ void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) {
sk_ignore_unused_variable(inputColor);
SkString coords2D = builder->ensureFSCoords2D(coords, 0);
fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kMat44f_GrSLType, "Coefficients");
@ -106,6 +108,7 @@ GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
}
}
this->setWillNotUseInputColor();
}
GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
@ -120,6 +123,7 @@ GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
}
}
this->setWillNotUseInputColor();
}
GrBicubicEffect::~GrBicubicEffect() {

View File

@ -48,7 +48,6 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
fDstCopyTexUnit = -1;
fColor = GrColor_ILLEGAL;
fColorFilterColor = GrColor_ILLEGAL;
if (fDesc.getHeader().fHasVertexCode ||
!fGpu->shouldUseFixedFunctionTexturing()) {
@ -97,117 +96,6 @@ void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
}
}
namespace {
// given two blend coefficients determine whether the src
// and/or dst computation can be omitted.
inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
SkXfermode::Coeff dstCoeff,
bool* needSrcValue,
bool* needDstValue) {
if (SkXfermode::kZero_Coeff == srcCoeff) {
switch (dstCoeff) {
// these all read the src
case SkXfermode::kSC_Coeff:
case SkXfermode::kISC_Coeff:
case SkXfermode::kSA_Coeff:
case SkXfermode::kISA_Coeff:
*needSrcValue = true;
break;
default:
*needSrcValue = false;
break;
}
} else {
*needSrcValue = true;
}
if (SkXfermode::kZero_Coeff == dstCoeff) {
switch (srcCoeff) {
// these all read the dst
case SkXfermode::kDC_Coeff:
case SkXfermode::kIDC_Coeff:
case SkXfermode::kDA_Coeff:
case SkXfermode::kIDA_Coeff:
*needDstValue = true;
break;
default:
*needDstValue = false;
break;
}
} else {
*needDstValue = true;
}
}
/**
* Create a blend_coeff * value string to be used in shader code. Sets empty
* string if result is trivially zero.
*/
inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
const char* src, const char* dst,
const char* value) {
switch (coeff) {
case SkXfermode::kZero_Coeff: /** 0 */
*str = "";
break;
case SkXfermode::kOne_Coeff: /** 1 */
*str = value;
break;
case SkXfermode::kSC_Coeff:
str->printf("(%s * %s)", src, value);
break;
case SkXfermode::kISC_Coeff:
str->printf("((vec4(1) - %s) * %s)", src, value);
break;
case SkXfermode::kDC_Coeff:
str->printf("(%s * %s)", dst, value);
break;
case SkXfermode::kIDC_Coeff:
str->printf("((vec4(1) - %s) * %s)", dst, value);
break;
case SkXfermode::kSA_Coeff: /** src alpha */
str->printf("(%s.a * %s)", src, value);
break;
case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
str->printf("((1.0 - %s.a) * %s)", src, value);
break;
case SkXfermode::kDA_Coeff: /** dst alpha */
str->printf("(%s.a * %s)", dst, value);
break;
case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
str->printf("((1.0 - %s.a) * %s)", dst, value);
break;
default:
GrCrash("Unexpected xfer coeff.");
break;
}
}
/**
* Adds a line to the fragment shader code which modifies the color by
* the specified color filter.
*/
void add_color_filter(GrGLShaderBuilder* builder,
const char * outputVar,
SkXfermode::Coeff uniformCoeff,
SkXfermode::Coeff colorCoeff,
const char* filterColor,
const char* inColor) {
SkString colorStr, constStr;
blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
GrGLSLExpr<4> sum;
if (colorStr.isEmpty() && constStr.isEmpty()) {
sum = GrGLSLExpr<4>(0);
} else if (colorStr.isEmpty()) {
sum = constStr;
} else if (constStr.isEmpty()) {
sum = colorStr;
} else {
sum = GrGLSLExpr<4>(colorStr) + GrGLSLExpr<4>(constStr);
}
builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
}
}
bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
@ -216,40 +104,17 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
// incoming color to current stage being processed.
GrGLSLExpr<4> inColor = builder->getInputColor();
// Get the coeffs for the Mode-based color filter, determine if color is needed.
SkXfermode::Coeff colorCoeff;
SkXfermode::Coeff filterColorCoeff;
SkAssertResult(
SkXfermode::ModeAsCoeff(header.fColorFilterXfermode,
&filterColorCoeff,
&colorCoeff));
bool needColor, needFilterColor;
need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
GrGLSLExpr4 inColor = builder->getInputColor();
fColorEffects.reset(
builder->createAndEmitEffects(colorStages,
fDesc.effectKeys(),
needColor ? fDesc.numColorEffects() : 0,
fDesc.numColorEffects(),
&inColor));
// Insert the color filter. This will soon be replaced by a color effect.
if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
const char* colorFilterColorUniName = NULL;
fUniformHandles.fColorFilterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "FilterColor",
&colorFilterColorUniName);
builder->fsCodeAppend("\tvec4 filteredColor;\n");
add_color_filter(builder, "filteredColor", filterColorCoeff,
colorCoeff, colorFilterColorUniName, inColor.c_str());
inColor = "filteredColor";
}
///////////////////////////////////////////////////////////////////////////
// compute the partial coverage
GrGLSLExpr<4> inCoverage = builder->getInputCoverage();
GrGLSLExpr4 inCoverage = builder->getInputCoverage();
fCoverageEffects.reset(
builder->createAndEmitEffects(coverageStages,
@ -272,13 +137,13 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const char* secondaryOutputName = builder->enableSecondaryOutput();
// default coeff to ones for kCoverage_DualSrcOutput
GrGLSLExpr<4> coeff(1);
GrGLSLExpr4 coeff(1);
if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
// Get (1-A) into coeff
coeff = GrGLSLExprCast4(GrGLSLExpr<1>(1) - GrGLSLExprExtractAlpha(inColor));
coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a());
} else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
// Get (1-RGBA) into coeff
coeff = GrGLSLExpr<4>(1) - inColor;
coeff = GrGLSLExpr4(1) - inColor;
}
// Get coeff * coverage into modulate and then write that to the dual source output.
builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
@ -288,12 +153,12 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
// combine color and coverage as frag color
// Get "color * coverage" into fragColor
GrGLSLExpr<4> fragColor = inColor * inCoverage;
GrGLSLExpr4 fragColor = inColor * inCoverage;
// Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
GrGLSLExpr<4> dstCoeff = GrGLSLExpr<4>(1) - inCoverage;
GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage;
GrGLSLExpr<4> dstContribution = dstCoeff * GrGLSLExpr<4>(builder->dstColor());
GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor());
fragColor = fragColor + dstContribution;
}
@ -352,15 +217,6 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
this->setCoverage(drawState, coverage, sharedState);
this->setMatrixAndRenderTargetHeight(drawState);
// Setup the SkXfermode::Mode-based colorfilter uniform if necessary
if (fUniformHandles.fColorFilterUni.isValid() &&
fColorFilterColor != drawState.getColorFilterColor()) {
GrGLfloat c[4];
GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c);
fColorFilterColor = drawState.getColorFilterColor();
}
if (NULL != dstCopy) {
if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
@ -409,7 +265,7 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
if (fColor != color) {
if (fColor != color && fUniformHandles.fColorUni.isValid()) {
// OpenGL ES doesn't support unsigned byte varieties of glUniform
GrGLfloat c[4];
GrColorToRGBAFloat(color, c);

View File

@ -139,7 +139,6 @@ private:
UniformHandle fViewMatrixUni;
UniformHandle fColorUni;
UniformHandle fCoverageUni;
UniformHandle fColorFilterUni;
// We use the render target height to provide a y-down frag coord when specifying
// origin_upper_left is not supported.
@ -187,7 +186,6 @@ private:
MatrixState fMatrixState;
GrColor fColor;
GrColor fCoverage;
GrColor fColorFilterColor;
int fDstCopyTexUnit;
SkAutoTDelete<GrGLProgramEffects> fColorEffects;

View File

@ -56,6 +56,27 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
GrDrawState::kEmitCoverage_BlendOptFlag));
int firstEffectiveColorStage = 0;
bool inputColorIsUsed = true;
if (!skipColor) {
firstEffectiveColorStage = drawState.numColorStages();
while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
--firstEffectiveColorStage;
const GrEffect* effect = drawState.getColorStage(firstEffectiveColorStage).getEffect()->get();
inputColorIsUsed = effect->willUseInputColor();
}
}
int firstEffectiveCoverageStage = 0;
bool inputCoverageIsUsed = true;
if (!skipCoverage) {
firstEffectiveCoverageStage = drawState.numCoverageStages();
while (firstEffectiveCoverageStage > 0 && inputCoverageIsUsed) {
--firstEffectiveCoverageStage;
const GrEffect* effect = drawState.getCoverageStage(firstEffectiveCoverageStage).getEffect()->get();
inputCoverageIsUsed = effect->willUseInputColor();
}
}
// The descriptor is used as a cache key. Thus when a field of the
// descriptor will not affect program generation (because of the attribute
@ -70,10 +91,11 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
(!requiresColorAttrib && 0xffffffff == drawState.getColor());
(!requiresColorAttrib && 0xffffffff == drawState.getColor()) ||
(!inputColorIsUsed);
int numEffects = (skipColor ? 0 : drawState.numColorStages()) +
(skipCoverage ? 0 : drawState.numCoverageStages());
int numEffects = (skipColor ? 0 : (drawState.numColorStages() - firstEffectiveColorStage)) +
(skipCoverage ? 0 : (drawState.numCoverageStages() - firstEffectiveCoverageStage));
size_t newKeyLength = KeyLength(numEffects);
bool allocChanged;
@ -93,7 +115,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool readFragPosition = false;
bool hasVertexCode = false;
if (!skipColor) {
for (int s = 0; s < drawState.numColorStages(); ++s) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
effectKeys[currEffectKey++] =
get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &readsDst, &readFragPosition,
@ -101,7 +123,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
}
}
if (!skipCoverage) {
for (int s = 0; s < drawState.numCoverageStages(); ++s) {
for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
effectKeys[currEffectKey++] =
get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &readsDst, &readFragPosition,
@ -111,7 +133,6 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib;
header->fEmitsPointSize = isPoints;
header->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
// Currently the experimental GS will only work with triangle prims (and it doesn't do anything
// other than pass through values from the VS to the FS anyway).
@ -139,7 +160,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
if (skipCoverage) {
header->fCoverageInput = kTransBlack_ColorInput;
} else if (covIsSolidWhite) {
} else if (covIsSolidWhite || !inputCoverageIsUsed) {
header->fCoverageInput = kSolidWhite_ColorInput;
} else if (defaultToUniformInputs && !requiresCoverageAttrib) {
header->fCoverageInput = kUniform_ColorInput;
@ -202,10 +223,6 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool separateCoverageFromColor = false;
if (!drawState.isCoverageDrawing() && !skipCoverage &&
(drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
// color filter is applied between color/coverage computation
if (SkXfermode::kDst_Mode != header->fColorFilterXfermode) {
separateCoverageFromColor = true;
}
// If we're stenciling then we want to discard samples that have zero coverage
if (drawState.getStencil().doesWrite()) {
@ -237,24 +254,23 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
}
}
if (!skipColor) {
for (int s = 0; s < drawState.numColorStages(); ++s) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
colorStages->push_back(&drawState.getColorStage(s));
}
header->fColorEffectCnt = drawState.numColorStages();
}
if (!skipCoverage) {
SkTArray<const GrEffectStage*, true>* array;
if (separateCoverageFromColor) {
array = coverageStages;
header->fCoverageEffectCnt = drawState.numCoverageStages();
} else {
array = colorStages;
header->fColorEffectCnt += drawState.numCoverageStages();
}
for (int s = 0; s < drawState.numCoverageStages(); ++s) {
for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
array->push_back(&drawState.getCoverageStage(s));
}
}
header->fColorEffectCnt = colorStages->count();
header->fCoverageEffectCnt = coverageStages->count();
*desc->checksum() = 0;
*desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()),

View File

@ -160,7 +160,6 @@ private:
SkBool8 fHasVertexCode;
SkBool8 fEmitsPointSize;
SkXfermode::Mode fColorFilterXfermode : 8;
// To enable experimental geometry shader code (not for use in
// production)

View File

@ -77,7 +77,7 @@ namespace {
void GrGLSLMulVarBy4f(SkString* outAppend,
unsigned tabCnt,
const char* vec4VarName,
const GrGLSLExpr<4>& mulFactor) {
const GrGLSLExpr4& mulFactor) {
if (mulFactor.isOnes()) {
*outAppend = SkString();
}

View File

@ -76,34 +76,48 @@ static inline const char* GrGLSLTypeString(GrSLType t) {
}
}
/** A class representing a GLSL expression.
/** A generic base-class representing a GLSL expression.
* The instance can be a variable name, expression or vecN(0) or vecN(1). Does simple constant
* folding with help of 1 and 0.
* Complex expressions can be constructed with operators *, +, -
*
* Clients should not use this class, rather the specific instantiations defined
* later, for example GrGLSLExpr4.
*/
template <int N>
template <typename Self>
class GrGLSLExpr {
public:
bool isOnes() const { return kOnes_ExprType == fType; }
bool isZeros() const { return kZeros_ExprType == fType; }
const char* c_str() const {
if (kZeros_ExprType == fType) {
return Self::ZerosStr();
} else if (kOnes_ExprType == fType) {
return Self::OnesStr();
}
SkASSERT(!fExpr.isEmpty()); // Empty expressions should not be used.
return fExpr.c_str();
}
protected:
/** Constructs an invalid expression.
* Useful only as a return value from functions that never actually return
* this and instances that will be assigned to later. */
GrGLSLExpr()
: fType(kFullExpr_ExprType) {
SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
// The only constructor that is allowed to build an empty expression.
SkASSERT(!this->isValid());
}
/** Constructs an expression with all components as value v */
explicit GrGLSLExpr(int v) {
SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (v == 0) {
fType = kZeros_ExprType;
} else if (v == 1) {
fType = kOnes_ExprType;
} else {
fType = kFullExpr_ExprType;
fExpr.appendf(CastIntStr(), v);
fExpr.appendf(Self::CastIntStr(), v);
}
}
@ -111,7 +125,6 @@ public:
* Argument expr is a simple expression or a parenthesized expression. */
// TODO: make explicit once effects input Exprs.
GrGLSLExpr(const char expr[]) {
SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (NULL == expr) { // TODO: remove this once effects input Exprs.
fType = kOnes_ExprType;
} else {
@ -125,7 +138,6 @@ public:
* Argument expr is a simple expression or a parenthesized expression. */
// TODO: make explicit once effects input Exprs.
GrGLSLExpr(const SkString& expr) {
SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (expr.isEmpty()) { // TODO: remove this once effects input Exprs.
fType = kOnes_ExprType;
} else {
@ -135,77 +147,61 @@ public:
SkASSERT(this->isValid());
}
bool isOnes() const { return kOnes_ExprType == fType; }
bool isZeros() const { return kZeros_ExprType == fType; }
const char* c_str() const {
if (kZeros_ExprType == fType) {
return ZerosStr();
} else if (kOnes_ExprType == fType) {
return OnesStr();
}
SkASSERT(!fExpr.isEmpty()); // Empty expressions should not be used.
return fExpr.c_str();
}
private:
/** Constructs an expression from a string with one substitution. */
GrGLSLExpr(const char format[], const char in0[])
: fType(kFullExpr_ExprType) {
fExpr.appendf(format, in0);
}
/** Constructs an expression from a string with two substitutions. */
GrGLSLExpr(const char format[], const char in0[], const char in1[])
: fType(kFullExpr_ExprType) {
fExpr.appendf(format, in0, in1);
}
GrGLSLExpr(const char format[], const char in0[], char in1)
: fType(kFullExpr_ExprType) {
fExpr.appendf(format, in0, in1);
}
bool isValid() const {
return kFullExpr_ExprType != fType || !fExpr.isEmpty();
}
static const char* ZerosStr();
static const char* OnesStr();
static const char* ExtractAlphaStr();
static const char* CastStr();
static const char* CastIntStr();
/** Returns expression casted to another type.
* Generic implementation that is called for non-trivial cases of casts. */
template <typename T>
static Self VectorCastImpl(const T& other);
/** Casts the expression expr into smaller or bigger expression.
* Casting is done with GLSL rules:
* M==3, N==4 vec3(a, b, c) -> vec4(a, b, c, 0)
* N==4, M==3 vec4(a, b, c, d) -> vec3(a, b, c)
/** Returns a GLSL multiplication: component-wise or component-by-scalar.
* The multiplication will be component-wise or multiply each component by a scalar.
*
* The returned expression will compute the value of:
* vecN(in0.x * in1.x, ...) if dim(T0) == dim(T1) (component-wise)
* vecN(in0.x * in1, ...) if dim(T1) == 1 (vector by scalar)
* vecN(in0 * in1.x, ...) if dim(T0) == 1 (scalar by vector)
*/
template <int M>
static GrGLSLExpr<N> VectorCast(const GrGLSLExpr<M>& expr);
template <typename T0, typename T1>
static Self Mul(T0 in0, T1 in1);
/** GLSL multiplication: component-wise or multiply each component by a scalar.
* M == N --> vecN(in0.x * in1.x, ...)
* M == 1 --> vecN(in0.x * in1, ...)
* otherwise --> compile-time error
/** Returns a GLSL addition: component-wise or add a scalar to each component.
* Return value computes:
* vecN(in0.x + in1.x, ...) or vecN(in0.x + in1, ...) or vecN(in0 + in1.x, ...).
*/
template <int M>
static GrGLSLExpr<N> Mul(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
template <typename T0, typename T1>
static Self Add(T0 in0, T1 in1);
/** GLSL addition: component-wise or add a scalar to each compoment.
* M == N --> vecN(in0.x + in1.x, ...)
* M == 1 --> vecN(in0.x + in1, ...)
* otherwise --> compile-time error
/** Returns a GLSL subtraction: component-wise or subtract compoments by a scalar.
* Return value computes
* vecN(in0.x - in1.x, ...) or vecN(in0.x - in1, ...) or vecN(in0 - in1.x, ...).
*/
template <int M>
static GrGLSLExpr<N> Add(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
template <typename T0, typename T1>
static Self Sub(T0 in0, T1 in1);
/** GLSL subtraction: component-wise or subtract compoments by a scalar.
* M == N --> vecN(in0.x - in1.x, ...)
* M == 1 --> vecN(in0.x - in1, ...)
* otherwise --> compile-time error
/** Returns expression that accesses component(s) of the expression.
* format should be the form "%s.x" where 'x' is the component(s) to access.
* Caller is responsible for making sure the amount of components in the
* format string is equal to dim(T).
*/
template <int M>
static GrGLSLExpr<N> Sub(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
template <typename T>
T extractComponents(const char format[]) const;
private:
enum ExprType {
kZeros_ExprType,
kOnes_ExprType,
@ -213,66 +209,112 @@ private:
};
ExprType fType;
SkString fExpr;
template <int> friend class GrGLSLExpr;
/** Multiplies two expressions component-wise. */
template <int M> friend GrGLSLExpr<M> operator*(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
/** Adds two expressions component-wise. */
template <int M> friend GrGLSLExpr<M> operator+(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
/** Subtracts two expressions component-wise. */
template <int M> friend GrGLSLExpr<M> operator-(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
/** Multiplies every component of an expression with a scalar expression. */
friend GrGLSLExpr<4> operator*(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
/** Adds a scalar expression to every component of an expression. */
friend GrGLSLExpr<4> operator+(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
/** Subtracts a scalar expression from every component of an expression. */
friend GrGLSLExpr<4> operator-(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
friend GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr);
friend GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr);
};
class GrGLSLExpr1;
class GrGLSLExpr4;
template <int N>
inline GrGLSLExpr<N> operator*(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
return GrGLSLExpr<N>::Mul(in0, in1);
}
/** Class representing a float GLSL expression. */
class GrGLSLExpr1 : public GrGLSLExpr<GrGLSLExpr1> {
public:
GrGLSLExpr1()
: INHERITED() {
}
explicit GrGLSLExpr1(int v)
: INHERITED(v) {
}
GrGLSLExpr1(const char* expr)
: INHERITED(expr) {
}
GrGLSLExpr1(const SkString& expr)
: INHERITED(expr) {
}
template <int N>
inline GrGLSLExpr<N> operator+(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
return GrGLSLExpr<N>::Add(in0, in1);
}
static GrGLSLExpr1 VectorCast(const GrGLSLExpr1& expr);
template <int N>
inline GrGLSLExpr<N> operator-(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
return GrGLSLExpr<N>::Sub(in0, in1);
}
private:
GrGLSLExpr1(const char format[], const char in0[])
: INHERITED(format, in0) {
}
GrGLSLExpr1(const char format[], const char in0[], const char in1[])
: INHERITED(format, in0, in1) {
}
inline GrGLSLExpr<4> operator*(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
return GrGLSLExpr<4>::Mul(in0, in1);
}
static const char* ZerosStr();
static const char* OnesStr();
static const char* CastStr();
static const char* CastIntStr();
inline GrGLSLExpr<4> operator+(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
return GrGLSLExpr<4>::Add(in0, in1);
}
friend GrGLSLExpr1 operator*(const GrGLSLExpr1& in0, const GrGLSLExpr1&in1);
friend GrGLSLExpr1 operator+(const GrGLSLExpr1& in0, const GrGLSLExpr1&in1);
friend GrGLSLExpr1 operator-(const GrGLSLExpr1& in0, const GrGLSLExpr1&in1);
inline GrGLSLExpr<4> operator-(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
return GrGLSLExpr<4>::Sub(in0, in1);
}
friend class GrGLSLExpr<GrGLSLExpr1>;
friend class GrGLSLExpr<GrGLSLExpr4>;
/** Casts an vec1 expression to vec4 expresison, eg. vec1(v) -> vec4(v,v,v,v). */
GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr);
typedef GrGLSLExpr<GrGLSLExpr1> INHERITED;
};
/** Extracts alpha component from an expression of vec<4>. */
GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr);
/** Class representing a float vector (vec4) GLSL expression. */
class GrGLSLExpr4 : public GrGLSLExpr<GrGLSLExpr4> {
public:
GrGLSLExpr4()
: INHERITED() {
}
explicit GrGLSLExpr4(int v)
: INHERITED(v) {
}
GrGLSLExpr4(const char* expr)
: INHERITED(expr) {
}
GrGLSLExpr4(const SkString& expr)
: INHERITED(expr) {
}
typedef GrGLSLExpr1 AExpr;
AExpr a() const;
/** GLSL vec4 cast / constructor, eg vec4(floatv) -> vec4(floatv, floatv, floatv, floatv) */
static GrGLSLExpr4 VectorCast(const GrGLSLExpr1& expr);
static GrGLSLExpr4 VectorCast(const GrGLSLExpr4& expr);
private:
GrGLSLExpr4(const char format[], const char in0[])
: INHERITED(format, in0) {
}
GrGLSLExpr4(const char format[], const char in0[], const char in1[])
: INHERITED(format, in0, in1) {
}
static const char* ZerosStr();
static const char* OnesStr();
static const char* CastStr();
static const char* CastIntStr();
// The vector-by-scalar and scalar-by-vector binary operations.
friend GrGLSLExpr4 operator*(const GrGLSLExpr1& in0, const GrGLSLExpr4&in1);
friend GrGLSLExpr4 operator+(const GrGLSLExpr1& in0, const GrGLSLExpr4&in1);
friend GrGLSLExpr4 operator-(const GrGLSLExpr1& in0, const GrGLSLExpr4&in1);
friend GrGLSLExpr4 operator*(const GrGLSLExpr4& in0, const GrGLSLExpr1&in1);
friend GrGLSLExpr4 operator+(const GrGLSLExpr4& in0, const GrGLSLExpr1&in1);
friend GrGLSLExpr4 operator-(const GrGLSLExpr4& in0, const GrGLSLExpr1&in1);
// The vector-by-vector, i.e. component-wise, binary operations.
friend GrGLSLExpr4 operator*(const GrGLSLExpr4& in0, const GrGLSLExpr4&in1);
friend GrGLSLExpr4 operator+(const GrGLSLExpr4& in0, const GrGLSLExpr4&in1);
friend GrGLSLExpr4 operator-(const GrGLSLExpr4& in0, const GrGLSLExpr4&in1);
friend class GrGLSLExpr<GrGLSLExpr4>;
typedef GrGLSLExpr<GrGLSLExpr4> INHERITED;
};
/**
* Does an inplace mul, *=, of vec4VarName by mulFactor.
* A semicolon and newline are added after the assignment.
*/
void GrGLSLMulVarBy4f(SkString* outAppend, unsigned tabCnt,
const char* vec4VarName, const GrGLSLExpr<4>& mulFactor);
const char* vec4VarName, const GrGLSLExpr4& mulFactor);
#include "GrGLSL_impl.h"

View File

@ -8,133 +8,168 @@
#ifndef GrGLSL_impl_DEFINED
#define GrGLSL_impl_DEFINED
template<>
inline const char* GrGLSLExpr<4>::ZerosStr() {
return "vec4(0)";
}
template<>
inline const char* GrGLSLExpr<4>::OnesStr() {
return "vec4(1)";
}
template<>
inline const char* GrGLSLExpr<4>::ExtractAlphaStr() {
return "%s.a";
}
template<>
inline const char* GrGLSLExpr<4>::CastStr() {
return "vec4(%s)";
}
template<>
inline const char* GrGLSLExpr<4>::CastIntStr() {
return "vec4(%d)";
}
template<>
inline const char* GrGLSLExpr<1>::ZerosStr() {
return "0";
}
template<>
inline const char* GrGLSLExpr<1>::OnesStr() {
return "1";
}
// GrGLSLExpr<1>::ExtractAlphaStr() and GrGLSLExpr<1>::CastStr() are
// unimplemented because using them is likely an error. This is now caught
// compile-time.
template<>
inline const char* GrGLSLExpr<1>::CastIntStr() {
return "%d";
}
template<>
template<>
inline GrGLSLExpr<4> GrGLSLExpr<4>::VectorCast(const GrGLSLExpr<4>& expr) {
return expr;
}
template<>
template<>
inline GrGLSLExpr<1> GrGLSLExpr<1>::VectorCast(const GrGLSLExpr<1>& expr) {
return expr;
}
template<int N>
template<int M>
inline GrGLSLExpr<N> GrGLSLExpr<N>::VectorCast(const GrGLSLExpr<M>& expr) {
template<typename Self>
template<typename T>
inline Self GrGLSLExpr<Self>::VectorCastImpl(const T& expr) {
if (expr.isZeros()) {
return GrGLSLExpr<N>(0);
return Self(0);
}
if (expr.isOnes()) {
return GrGLSLExpr<N>(1);
return Self(1);
}
return GrGLSLExpr<N>(GrGLSLExpr<N>::CastStr(), expr.c_str());
return Self(Self::CastStr(), expr.c_str());
}
template<int N>
template<int M>
inline GrGLSLExpr<N> GrGLSLExpr<N>::Mul(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
template<typename Self>
template<typename T0, typename T1>
inline Self GrGLSLExpr<Self>::Mul(T0 in0, T1 in1) {
if (in0.isZeros() || in1.isZeros()) {
return GrGLSLExpr<N>(0);
return Self(0);
}
if (in0.isOnes()) {
return VectorCast<M>(in1);
return Self::VectorCast(in1);
}
if (in1.isOnes()) {
return in0;
return Self::VectorCast(in0);
}
return GrGLSLExpr<N>("(%s * %s)", in0.c_str(), in1.c_str());
return Self("(%s * %s)", in0.c_str(), in1.c_str());
}
template<int N>
template<int M>
inline GrGLSLExpr<N> GrGLSLExpr<N>::Add(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
template<typename Self>
template<typename T0, typename T1>
inline Self GrGLSLExpr<Self>::Add(T0 in0, T1 in1) {
if (in1.isZeros()) {
return in0;
return Self::VectorCast(in0);
}
if (in0.isZeros()) {
return VectorCast<M>(in1);
return Self::VectorCast(in1);
}
if (in0.isOnes() && in1.isOnes()) {
return GrGLSLExpr<N>(2);
return Self(2);
}
return GrGLSLExpr<N>("(%s + %s)", in0.c_str(), in1.c_str());
return Self("(%s + %s)", in0.c_str(), in1.c_str());
}
template<int N>
template<int M>
inline GrGLSLExpr<N> GrGLSLExpr<N>::Sub(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
template<typename Self>
template<typename T0, typename T1>
inline Self GrGLSLExpr<Self>::Sub(T0 in0, T1 in1) {
if (in1.isZeros()) {
return in0;
return Self::VectorCast(in0);
}
if (in1.isOnes()) {
if (in0.isOnes()) {
return GrGLSLExpr<N>(0);
return Self(0);
}
}
return GrGLSLExpr<N>("(%s - %s)", in0.c_str(), in1.c_str());
return Self("(%s - %s)", in0.c_str(), in1.c_str());
}
inline GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr) {
return GrGLSLExpr<4>::VectorCast(expr);
template <typename Self>
template <typename T>
T GrGLSLExpr<Self>::extractComponents(const char format[]) const {
if (this->isZeros()) {
return T(0);
}
if (this->isOnes()) {
return T(1);
}
return T(format, this->c_str());
}
inline GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr) {
if (expr.isZeros()) {
return GrGLSLExpr<1>(0);
}
if (expr.isOnes()) {
return GrGLSLExpr<1>(1);
}
return GrGLSLExpr<1>(GrGLSLExpr<4>::ExtractAlphaStr(), expr.c_str());
inline GrGLSLExpr1 GrGLSLExpr1::VectorCast(const GrGLSLExpr1& expr) {
return expr;
}
inline const char* GrGLSLExpr1::ZerosStr() {
return "0";
}
inline const char* GrGLSLExpr1::OnesStr() {
return "1.0";
}
// GrGLSLExpr1::CastStr() is unimplemented because using them is likely an
// error. This is now caught compile-time.
inline const char* GrGLSLExpr1::CastIntStr() {
return "%d";
}
inline GrGLSLExpr1 operator*(const GrGLSLExpr1& in0, const GrGLSLExpr1& in1) {
return GrGLSLExpr1::Mul(in0, in1);
}
inline GrGLSLExpr1 operator+(const GrGLSLExpr1& in0, const GrGLSLExpr1& in1) {
return GrGLSLExpr1::Add(in0, in1);
}
inline GrGLSLExpr1 operator-(const GrGLSLExpr1& in0, const GrGLSLExpr1& in1) {
return GrGLSLExpr1::Sub(in0, in1);
}
inline const char* GrGLSLExpr4::ZerosStr() {
return "vec4(0)";
}
inline const char* GrGLSLExpr4::OnesStr() {
return "vec4(1)";
}
inline const char* GrGLSLExpr4::CastStr() {
return "vec4(%s)";
}
inline const char* GrGLSLExpr4::CastIntStr() {
return "vec4(%d)";
}
inline GrGLSLExpr4 GrGLSLExpr4::VectorCast(const GrGLSLExpr1& expr) {
return INHERITED::VectorCastImpl(expr);
}
inline GrGLSLExpr4 GrGLSLExpr4::VectorCast(const GrGLSLExpr4& expr) {
return expr;
}
inline GrGLSLExpr4::AExpr GrGLSLExpr4::a() const {
return this->extractComponents<GrGLSLExpr4::AExpr>("%s.a");
}
inline GrGLSLExpr4 operator*(const GrGLSLExpr1& in0, const GrGLSLExpr4& in1) {
return GrGLSLExpr4::Mul(in0, in1);
}
inline GrGLSLExpr4 operator+(const GrGLSLExpr1& in0, const GrGLSLExpr4& in1) {
return GrGLSLExpr4::Add(in0, in1);
}
inline GrGLSLExpr4 operator-(const GrGLSLExpr1& in0, const GrGLSLExpr4& in1) {
return GrGLSLExpr4::Sub(in0, in1);
}
inline GrGLSLExpr4 operator*(const GrGLSLExpr4& in0, const GrGLSLExpr1& in1) {
return GrGLSLExpr4::Mul(in0, in1);
}
inline GrGLSLExpr4 operator+(const GrGLSLExpr4& in0, const GrGLSLExpr1& in1) {
return GrGLSLExpr4::Add(in0, in1);
}
inline GrGLSLExpr4 operator-(const GrGLSLExpr4& in0, const GrGLSLExpr1& in1) {
return GrGLSLExpr4::Sub(in0, in1);
}
inline GrGLSLExpr4 operator*(const GrGLSLExpr4& in0, const GrGLSLExpr4& in1) {
return GrGLSLExpr4::Mul(in0, in1);
}
inline GrGLSLExpr4 operator+(const GrGLSLExpr4& in0, const GrGLSLExpr4& in1) {
return GrGLSLExpr4::Add(in0, in1);
}
inline GrGLSLExpr4 operator-(const GrGLSLExpr4& in0, const GrGLSLExpr4& in1) {
return GrGLSLExpr4::Sub(in0, in1);
}
#endif

View File

@ -149,22 +149,22 @@ GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
const char* name;
fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "Color", &name);
fInputColor = name;
fInputColor = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) {
fInputColor = GrGLSLExpr<4>(1);
fInputColor = GrGLSLExpr4(1);
} else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) {
fInputColor = GrGLSLExpr<4>(0);
fInputColor = GrGLSLExpr4(0);
}
if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
const char* name;
fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "Coverage", &name);
fInputCoverage = name;
fInputCoverage = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) {
fInputCoverage = GrGLSLExpr<4>(1);
fInputCoverage = GrGLSLExpr4(1);
} else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) {
fInputCoverage = GrGLSLExpr<4>(0);
fInputCoverage = GrGLSLExpr4(0);
}
if (k110_GrGLSLGeneration != fGpu->glslGeneration()) {
@ -295,7 +295,7 @@ void GrGLShaderBuilder::fsAppendTextureLookupAndModulate(
GrSLType varyingType) {
SkString lookup;
this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
fFSCode.append((GrGLSLExpr<4>(modulation) * GrGLSLExpr<4>(lookup)).c_str());
fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str());
}
GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
@ -515,11 +515,11 @@ void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programE
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
GrGLSLExpr<4>* fsInOutColor) {
GrGLSLExpr4* fsInOutColor) {
bool effectEmitted = false;
GrGLSLExpr<4> inColor = *fsInOutColor;
GrGLSLExpr<4> outColor;
GrGLSLExpr4 inColor = *fsInOutColor;
GrGLSLExpr4 outColor;
for (int e = 0; e < effectCnt; ++e) {
SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
@ -839,7 +839,7 @@ GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
GrGLSLExpr<4>* inOutFSColor) {
GrGLSLExpr4* inOutFSColor) {
GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
@ -954,7 +954,7 @@ GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
GrGLSLExpr<4>* inOutFSColor) {
GrGLSLExpr4* inOutFSColor) {
GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt);
this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder,

View File

@ -168,10 +168,10 @@ public:
/**
* Interfaces used by GrGLProgram.
*/
const GrGLSLExpr<4>& getInputColor() const {
const GrGLSLExpr4& getInputColor() const {
return fInputColor;
}
const GrGLSLExpr<4>& getInputCoverage() const {
const GrGLSLExpr4& getInputCoverage() const {
return fInputCoverage;
}
@ -186,7 +186,7 @@ public:
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
GrGLSLExpr<4>* inOutFSColor) = 0;
GrGLSLExpr4* inOutFSColor) = 0;
const char* getColorOutputName() const;
const char* enableSecondaryOutput();
@ -211,8 +211,8 @@ public:
protected:
GrGpuGL* gpu() const { return fGpu; }
void setInputColor(const GrGLSLExpr<4>& inputColor) { fInputColor = inputColor; }
void setInputCoverage(const GrGLSLExpr<4>& inputCoverage) { fInputCoverage = inputCoverage; }
void setInputColor(const GrGLSLExpr4& inputColor) { fInputColor = inputColor; }
void setInputCoverage(const GrGLSLExpr4& inputCoverage) { fInputCoverage = inputCoverage; }
/** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
@ -227,7 +227,7 @@ protected:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
GrGLSLExpr<4>* inOutFSColor);
GrGLSLExpr4* inOutFSColor);
virtual bool compileAndAttachShaders(GrGLuint programId) const;
virtual void bindProgramLocations(GrGLuint programId) const;
@ -329,8 +329,8 @@ private:
bool fSetupFragPosition;
GrGLUniformManager::UniformHandle fDstCopySamplerUniform;
GrGLSLExpr<4> fInputColor;
GrGLSLExpr<4> fInputCoverage;
GrGLSLExpr4 fInputColor;
GrGLSLExpr4 fInputCoverage;
bool fHasCustomColorOutput;
bool fHasSecondaryOutput;
@ -396,7 +396,7 @@ public:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
GrGLSLExpr<4>* inOutFSColor) SK_OVERRIDE;
GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
GrGLUniformManager::UniformHandle getViewMatrixUniform() const {
return fViewMatrixUniform;
@ -445,7 +445,7 @@ public:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
GrGLSLExpr<4>* inOutFSColor) SK_OVERRIDE;
GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
private:
int fNumTexCoordSets;

View File

@ -61,9 +61,6 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
currAttribIndex++ :
-1;
header->fColorFilterXfermode = static_cast<SkXfermode::Mode>(
random->nextULessThan(SkXfermode::kLastCoeffMode + 1));
#if GR_GL_EXPERIMENTAL_GS
header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool();
#endif

View File

@ -0,0 +1,131 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrContextFactory.h"
#include "GrEffect.h"
#include "SkColorFilter.h"
#include "Test.h"
#include "SkGr.h"
namespace {
static GrColor filterColor(const GrColor& color, uint32_t flags) {
uint32_t mask = 0;
if (flags & kR_GrColorComponentFlag) {
mask = 0xFF << GrColor_SHIFT_R;
}
if (flags & kG_GrColorComponentFlag) {
mask |= 0xFF << GrColor_SHIFT_G;
}
if (flags & kB_GrColorComponentFlag) {
mask |= 0xFF << GrColor_SHIFT_B;
}
if (flags & kA_GrColorComponentFlag) {
mask |= 0xFF << GrColor_SHIFT_A;
}
return color & mask;
}
static void test_getConstantColorComponents(skiatest::Reporter* reporter, GrContext* grContext) {
struct GetConstantComponentTestCase {
// "Shape drawn with"
uint32_t inputComponents; // "rgb of", "red of", "alpha of", ...
GrColor inputColor; // "[color]"
SkColor filterColor; // "with filter color [color]"
SkXfermode::Mode filterMode; // "in mode [mode]"
// "produces"
uint32_t outputComponents; // "rgb of", "red of", "alpha of", ...
GrColor outputColor; // "[color]"
};
// Shorthands.
enum {
kR = kR_GrColorComponentFlag,
kG = kG_GrColorComponentFlag,
kB = kB_GrColorComponentFlag,
kA = kA_GrColorComponentFlag,
kRGB = kRGB_GrColorComponentFlags,
kRGBA = kRGBA_GrColorComponentFlags
};
// Note: below, SkColors are non-premultiplied, where as GrColors are premultiplied.
const SkColor c1 = SkColorSetARGB(200, 200, 200, 200);
const SkColor c2 = SkColorSetARGB(60, 60, 60, 60);
const GrColor gr_c1 = SkColor2GrColor(c1);
const GrColor gr_c2 = SkColor2GrColor(c2);
const GrColor gr_black = GrColorPackRGBA(0, 0, 0, 0);
const GrColor gr_white = GrColorPackRGBA(255, 255, 255, 255);
const GrColor gr_whiteTrans = GrColorPackRGBA(128, 128, 128, 128);
GetConstantComponentTestCase filterTests[] = {
// A color filtered with Clear produces black.
{ kRGBA, gr_white, SK_ColorBLACK, SkXfermode::kClear_Mode, kRGBA, gr_black },
{ kRGBA, gr_c1, SK_ColorWHITE, SkXfermode::kClear_Mode, kRGBA, gr_black },
{ kR, gr_white, c1, SkXfermode::kClear_Mode, kRGBA, gr_black },
// A color filtered with a color in mode Src, produces the filter color.
{ kRGBA, gr_c2, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 },
{ kA, gr_c1, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 },
// A color filtered with SrcOver produces a color.
{ kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGBA, GrColorPackRGBA(164, 164, 164, 192)},
// An unknown color with known alpha filtered with SrcOver produces an unknown color with known alpha.
{ kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kA , GrColorPackRGBA(0, 0, 0, 192)},
// A color with unknown alpha filtered with SrcOver produces a color with unknown alpha.
{ kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGB, GrColorPackRGBA(164, 164, 164, 0)},
// A color filtered with DstOver produces a color.
{ kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kRGBA, GrColorPackRGBA(178, 178, 178, 192)},
// An unknown color with known alpha filtered with DstOver produces an unknown color with known alpha.
{ kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kA , GrColorPackRGBA(0, 0, 0, 192)},
// A color with unknown alpha filtered with DstOver produces an unknown color.
{ kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, 0 , gr_black},
// An unknown color with known alpha and red component filtered with Multiply produces an unknown color with known red and alpha.
{ kR|kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kModulate_Mode, kR|kA, GrColorPackRGBA(50, 0, 0, 64) }
};
for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) {
const GetConstantComponentTestCase& test = filterTests[i];
SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(test.filterColor, test.filterMode));
SkAutoTUnref<GrEffectRef> grEffect(cf->asNewEffect(grContext));
GrColor color = test.inputColor;
uint32_t components = test.inputComponents;
grEffect->get()->getConstantColorComponents(&color, &components);
REPORTER_ASSERT(reporter, filterColor(color, components) == test.outputColor);
REPORTER_ASSERT(reporter, test.outputComponents == components);
}
}
static void TestGpuColorFilter(skiatest::Reporter* reporter, GrContextFactory* factory) {
for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
GrContext* grContext = factory->get(glType);
if (NULL == grContext) {
continue;
}
test_getConstantColorComponents(reporter, grContext);
}
}
}
#include "TestClassDef.h"
DEFINE_GPUTESTCLASS("GpuColorFilter", TestGpuColorFilterClass, TestGpuColorFilter)
#endif