aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gpu/include/GrSamplerState.h3
-rw-r--r--gpu/src/GrGLProgram.cpp66
-rw-r--r--gpu/src/GrGLProgram.h7
-rw-r--r--gpu/src/GrGpuGLShaders.cpp28
-rw-r--r--gyp/SampleApp.gyp1
-rw-r--r--samplecode/SampleDegenerateTwoPtRadials.cpp85
-rw-r--r--samplecode/SampleXfermodesBlur.cpp50
7 files changed, 165 insertions, 75 deletions
diff --git a/gpu/include/GrSamplerState.h b/gpu/include/GrSamplerState.h
index 6d343d04e2..d10d8c4368 100644
--- a/gpu/include/GrSamplerState.h
+++ b/gpu/include/GrSamplerState.h
@@ -203,6 +203,9 @@ public:
GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
bool isRadial2PosRoot() const { return fRadial2PosRoot; }
+ // do the radial gradient params lead to a linear (rather than quadratic)
+ // equation.
+ bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; }
/**
* Sets the parameters for kRadial2_SampleMode. The texture
diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp
index 31571ab597..d6a832ce20 100644
--- a/gpu/src/GrGLProgram.cpp
+++ b/gpu/src/GrGLProgram.cpp
@@ -966,7 +966,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(CachedData* programData) const
//============================================================================
void GrGLProgram::genStageCode(int stageNum,
- const GrGLProgram::ProgramDesc::StageDesc& desc,
+ const GrGLProgram::StageDesc& desc,
const char* fsInColor, // NULL means no incoming color
const char* fsOutColor,
const char* vsInCoord,
@@ -989,7 +989,7 @@ void GrGLProgram::genStageCode(int stageNum,
// and whether the varying needs a perspective coord.
GrStringBuilder texMName;
tex_matrix_name(stageNum, &texMName);
- if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) {
+ if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
varyingDims = coordDims;
} else {
#if GR_GL_ATTRIBUTE_MATRICES
@@ -999,7 +999,7 @@ void GrGLProgram::genStageCode(int stageNum,
segments->fVSUnis.appendf("uniform mat3 %s;\n", texMName.c_str());
locations->fTextureMatrixUni = kUseUniform;
#endif
- if (desc.fOptFlags & ProgramDesc::StageDesc::kNoPerspective_OptFlagBit) {
+ if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
varyingDims = coordDims;
} else {
varyingDims = coordDims + 1;
@@ -1012,7 +1012,7 @@ void GrGLProgram::genStageCode(int stageNum,
locations->fSamplerUni = kUseUniform;
GrStringBuilder texelSizeName;
- if (ProgramDesc::StageDesc::k2x2_FetchMode == desc.fFetchMode) {
+ if (StageDesc::k2x2_FetchMode == desc.fFetchMode) {
normalized_texel_size_name(stageNum, &texelSizeName);
segments->fFSUnis.appendf("uniform vec2 %s;\n", texelSizeName.c_str());
}
@@ -1020,7 +1020,7 @@ void GrGLProgram::genStageCode(int stageNum,
segments->fVaryings.appendf("varying %s %s;\n",
float_vector_type(varyingDims), varyingName.c_str());
- if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) {
+ if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
GrAssert(varyingDims == coordDims);
segments->fVSCode.appendf("\t%s = %s;\n", varyingName.c_str(), vsInCoord);
} else {
@@ -1037,7 +1037,8 @@ void GrGLProgram::genStageCode(int stageNum,
GrStringBuilder radial2VaryingName;
radial2_varying_name(stageNum, &radial2VaryingName);
- if (ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) {
+ if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping ||
+ StageDesc::kRadial2GradientDegenerate_CoordMapping == desc.fCoordMapping) {
segments->fVSUnis.appendf("uniform %s float %s[6];\n",
GrPrecision(), radial2ParamsName.c_str());
@@ -1061,16 +1062,16 @@ void GrGLProgram::genStageCode(int stageNum,
GrStringBuilder fsCoordName;
// function used to access the shader, may be made projective
GrStringBuilder texFunc("texture2D");
- if (desc.fOptFlags & (ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit |
- ProgramDesc::StageDesc::kNoPerspective_OptFlagBit)) {
+ if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit |
+ StageDesc::kNoPerspective_OptFlagBit)) {
GrAssert(varyingDims == coordDims);
fsCoordName = varyingName;
} else {
// if we have to do some special op on the varyings to get
// our final tex coords then when in perspective we have to
// do an explicit divide. Otherwise, we can use a Proj func.
- if (ProgramDesc::StageDesc::kIdentity_CoordMapping == desc.fCoordMapping &&
- ProgramDesc::StageDesc::kSingle_FetchMode == desc.fFetchMode) {
+ if (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping &&
+ StageDesc::kSingle_FetchMode == desc.fFetchMode) {
texFunc.append("Proj");
fsCoordName = varyingName;
} else {
@@ -1089,18 +1090,18 @@ void GrGLProgram::genStageCode(int stageNum,
GrStringBuilder sampleCoords;
bool complexCoord = false;
switch (desc.fCoordMapping) {
- case ProgramDesc::StageDesc::kIdentity_CoordMapping:
+ case StageDesc::kIdentity_CoordMapping:
sampleCoords = fsCoordName;
break;
- case ProgramDesc::StageDesc::kSweepGradient_CoordMapping:
+ case StageDesc::kSweepGradient_CoordMapping:
sampleCoords.printf("vec2(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5, 0.5)", fsCoordName.c_str(), fsCoordName.c_str());
complexCoord = true;
break;
- case ProgramDesc::StageDesc::kRadialGradient_CoordMapping:
+ case StageDesc::kRadialGradient_CoordMapping:
sampleCoords.printf("vec2(length(%s.xy), 0.5)", fsCoordName.c_str());
complexCoord = true;
break;
- case ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping: {
+ case StageDesc::kRadial2Gradient_CoordMapping: {
GrStringBuilder cName("c");
GrStringBuilder ac4Name("ac4");
GrStringBuilder rootName("root");
@@ -1147,10 +1148,41 @@ void GrGLProgram::genStageCode(int stageNum,
rootName.c_str(), radial2ParamsName.c_str());
complexCoord = true;
break;}
+ case StageDesc::kRadial2GradientDegenerate_CoordMapping: {
+ GrStringBuilder cName("c");
+
+ cName.appendS32(stageNum);
+
+ // if we were able to interpolate the linear component bVar is the varying
+ // otherwise compute it
+ GrStringBuilder bVar;
+ if (coordDims == varyingDims) {
+ bVar = radial2VaryingName;
+ GrAssert(2 == varyingDims);
+ } else {
+ GrAssert(3 == varyingDims);
+ bVar = "b";
+ bVar.appendS32(stageNum);
+ segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
+ bVar.c_str(), radial2ParamsName.c_str(),
+ fsCoordName.c_str(), radial2ParamsName.c_str());
+ }
+
+ // c = (x^2)+(y^2) - params[4]
+ segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
+ cName.c_str(), fsCoordName.c_str(),
+ fsCoordName.c_str(),
+ radial2ParamsName.c_str());
+
+ // x coord is: -c/b
+ // y coord is 0.5 (texture is effectively 1D)
+ sampleCoords.printf("vec2((-%s / %s), 0.5)", cName.c_str(), bVar.c_str());
+ complexCoord = true;
+ break;}
};
const char* smear;
- if (desc.fModulation == ProgramDesc::StageDesc::kAlpha_Modulation) {
+ if (desc.fModulation == StageDesc::kAlpha_Modulation) {
smear = ".aaaa";
} else {
smear = "";
@@ -1161,7 +1193,7 @@ void GrGLProgram::genStageCode(int stageNum,
}
if (desc.fOptFlags &
- ProgramDesc::StageDesc::kCustomTextureDomain_OptFlagBit) {
+ StageDesc::kCustomTextureDomain_OptFlagBit) {
GrStringBuilder texDomainName;
tex_domain_name(stageNum, &texDomainName);
segments->fFSUnis.appendf("uniform %s %s;\n",
@@ -1178,7 +1210,7 @@ void GrGLProgram::genStageCode(int stageNum,
locations->fTexDomUni = kUseUniform;
}
- if (ProgramDesc::StageDesc::k2x2_FetchMode == desc.fFetchMode) {
+ if (StageDesc::k2x2_FetchMode == desc.fFetchMode) {
locations->fNormalizedTexelSizeUni = kUseUniform;
if (complexCoord) {
// assign the coord to a var rather than compute 4x.
diff --git a/gpu/src/GrGLProgram.h b/gpu/src/GrGLProgram.h
index 2c4152d4ca..edd47374ab 100644
--- a/gpu/src/GrGLProgram.h
+++ b/gpu/src/GrGLProgram.h
@@ -122,7 +122,9 @@ private:
kRadialGradient_CoordMapping,
kSweepGradient_CoordMapping,
kRadial2Gradient_CoordMapping,
-
+ // need different shader computation when quadratic
+ // eq describing the gradient degenerates to a linear eq.
+ kRadial2GradientDegenerate_CoordMapping,
kCoordMappingCnt
};
@@ -180,6 +182,9 @@ private:
const ProgramDesc& getDesc() { return fProgramDesc; }
+ // for code readability
+ typedef ProgramDesc::StageDesc StageDesc;
+
public:
enum {
kUnusedUniform = -1,
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index 2de995081a..1309802f81 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -433,6 +433,11 @@ void GrGpuGLShaders::flushRadial2(int s) {
GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
+ // when were in the degenerate (linear) case the second
+ // value will be INF but the program doesn't read it. (We
+ // use the same 6 uniforms even though we don't need them
+ // all in the linear case just to keep the code complexity
+ // down).
float values[6] = {
GrScalarToFloat(a),
1 / (2.f * values[0]),
@@ -737,14 +742,15 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
lastEnabledStage = s;
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
GrAssert(NULL != texture);
+ const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
// we matrix to invert when orientation is TopDown, so make sure
// we aren't in that case before flagging as identity.
- if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
+ if (TextureMatrixIsIdentity(texture, sampler)) {
stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit;
} else if (!getSamplerMatrix(s).hasPerspective()) {
stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit;
}
- switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
+ switch (sampler.getSampleMode()) {
case GrSamplerState::kNormal_SampleMode:
stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
break;
@@ -752,7 +758,13 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping;
break;
case GrSamplerState::kRadial2_SampleMode:
- stage.fCoordMapping = StageDesc::kRadial2Gradient_CoordMapping;
+ if (sampler.radial2IsDegenerate()) {
+ stage.fCoordMapping =
+ StageDesc::kRadial2GradientDegenerate_CoordMapping;
+ } else {
+ stage.fCoordMapping =
+ StageDesc::kRadial2Gradient_CoordMapping;
+ }
break;
case GrSamplerState::kSweep_SampleMode:
stage.fCoordMapping = StageDesc::kSweepGradient_CoordMapping;
@@ -762,7 +774,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
break;
}
- switch (fCurrDrawState.fSamplerStates[s].getFilter()) {
+ switch (sampler.getFilter()) {
// these both can use a regular texture2D()
case GrSamplerState::kNearest_Filter:
case GrSamplerState::kBilinear_Filter:
@@ -777,11 +789,11 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
break;
}
- if (fCurrDrawState.fSamplerStates[s].hasTextureDomain()) {
+ if (sampler.hasTextureDomain()) {
GrAssert(GrSamplerState::kClamp_WrapMode ==
- fCurrDrawState.fSamplerStates[s].getWrapX() &&
- GrSamplerState::kClamp_WrapMode ==
- fCurrDrawState.fSamplerStates[s].getWrapY());
+ sampler.getWrapX() &&
+ GrSamplerState::kClamp_WrapMode ==
+ sampler.getWrapY());
stage.fOptFlags |= StageDesc::kCustomTextureDomain_OptFlagBit;
}
diff --git a/gyp/SampleApp.gyp b/gyp/SampleApp.gyp
index a0c98a8a4a..084ae71a41 100644
--- a/gyp/SampleApp.gyp
+++ b/gyp/SampleApp.gyp
@@ -48,6 +48,7 @@
'../samplecode/SampleConcavePaths.cpp',
'../samplecode/SampleCull.cpp',
'../samplecode/SampleDecode.cpp',
+ '../samplecode/SampleDegenerateTwoPtRadials.cpp',
'../samplecode/SampleDither.cpp',
'../samplecode/SampleDitherBitmap.cpp',
'../samplecode/SampleDrawLooper.cpp',
diff --git a/samplecode/SampleDegenerateTwoPtRadials.cpp b/samplecode/SampleDegenerateTwoPtRadials.cpp
new file mode 100644
index 0000000000..ed10ce2304
--- /dev/null
+++ b/samplecode/SampleDegenerateTwoPtRadials.cpp
@@ -0,0 +1,85 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkGradientShader.h"
+
+static void draw_gradient2(SkCanvas* canvas, const SkRect& rect, SkScalar delta) {
+ SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorMAGENTA };
+ SkScalar pos[] = { 0, SkFloatToScalar(0.25f), SkFloatToScalar(0.75f), SK_Scalar1 };
+
+ SkScalar l = rect.fLeft;
+ SkScalar t = rect.fTop;
+ SkScalar w = rect.width();
+ SkScalar h = rect.height();
+
+ SkASSERT(0 == SkScalarMod(w, SK_Scalar1 * 5));
+
+ SkPoint c0 = { l + 2 * w / 5 + delta, t + h / 2 };
+ SkPoint c1 = { l + 3 * w / 5, t + h / 2 };
+ SkScalar r0 = w / 5;
+ SkScalar r1 = 2 * w / 5;
+ SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
+ pos, SK_ARRAY_COUNT(pos),
+ SkShader::kClamp_TileMode);
+ SkPaint paint;
+ paint.setShader(s)->unref();
+
+ canvas->drawRect(rect, paint);
+}
+
+
+class DegenerateTwoPtRadialsView : public SampleView {
+
+public:
+ DegenerateTwoPtRadialsView() {
+ fTime = 0;
+ this->setBGColor(0xFFDDDDDD);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "DegenerateTwoPtRadials");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ virtual void onDrawContent(SkCanvas* canvas) {
+ fTime += SampleCode::GetAnimSecondsDelta();
+ SkScalar delta = fTime / 15.f;
+ int intPart = SkScalarFloor(delta);
+ delta = delta - SK_Scalar1 * intPart;
+ if (intPart % 2) {
+ delta = SK_Scalar1 - delta;
+ }
+ delta -= SK_ScalarHalf;
+ static const int DELTA_SCALE = 500;
+ delta /= DELTA_SCALE;
+
+ SkRect rect;
+ SkScalar w = SK_Scalar1 * 500;
+ SkScalar h = SK_Scalar1 * 500;
+ SkScalar l = SK_Scalar1 * 100;
+ SkScalar t = SK_Scalar1 * 100;
+ draw_gradient2(canvas, SkRect::MakeXYWH(l, t, w, h), delta);
+ char txt[512];
+ sprintf(txt, "gap at \"tangent\" pt = %f", SkScalarToFloat(delta));
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(SK_ColorBLACK);
+ canvas->drawText(txt, strlen(txt), l + w/2 + w*DELTA_SCALE*delta, t + h + SK_Scalar1 * 10, paint);
+ this->inval(NULL);
+ }
+
+private:
+ SkScalar fTime;
+ typedef SampleView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new DegenerateTwoPtRadialsView; }
+static SkViewRegister reg(MyFactory);
diff --git a/samplecode/SampleXfermodesBlur.cpp b/samplecode/SampleXfermodesBlur.cpp
index 0167a6d4a0..03b29683a3 100644
--- a/samplecode/SampleXfermodesBlur.cpp
+++ b/samplecode/SampleXfermodesBlur.cpp
@@ -24,50 +24,6 @@
#include "SkImageDecoder.h"
#include "SkBlurMaskFilter.h"
-static void test_gradient2(SkCanvas* canvas) {
-#if 1
- SkBitmap bm;
- bm.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
- bm.allocPixels();
- *bm.getAddr32(0, 0) = SkPackARGB32(0xFF, 0, 0xFF, 0);
-
- SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
- SkShader::kRepeat_TileMode);
-#else
-/*
- ctx.fillStyle = '#f00';
- ctx.fillRect(0, 0, 100, 50);
-
- var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
- g.addColorStop(0, '#f00');
- g.addColorStop(0.01, '#0f0');
- g.addColorStop(0.99, '#0f0');
- g.addColorStop(1, '#f00');
- ctx.fillStyle = g;
- ctx.fillRect(0, 0, 100, 50);
-*/
- SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
- SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
- SkPoint c0 = { -80, 25 };
- SkScalar r0 = 70;
- SkPoint c1 = { 0, 25 };
- SkScalar r1 = 150;
- SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
- pos, SK_ARRAY_COUNT(pos),
- SkShader::kClamp_TileMode);
-#endif
-
- SkPaint paint;
- paint.setShader(s)->unref();
-
- canvas->drawPaint(paint);
-
- paint.setShader(NULL);
- paint.setStyle(SkPaint::kStroke_Style);
- SkRect r = { 0, 0, 100, 50 };
- canvas->drawRect(r, paint);
-}
-
static void setNamedTypeface(SkPaint* paint, const char name[]) {
SkTypeface* face = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
paint->setTypeface(face);
@@ -110,7 +66,7 @@ class XfermodesBlurView : public SampleView {
public:
const static int W = 64;
const static int H = 64;
- XfermodesBlurView() {
+ XfermodesBlurView() {
const int W = 64;
const int H = 64;
@@ -130,10 +86,6 @@ protected:
}
virtual void onDrawContent(SkCanvas* canvas) {
- if (false) {
- test_gradient2(canvas);
- return;
- }
canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
const struct {