virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
SkScalar kd() const { return fKD; }
private:
+ GR_DECLARE_CUSTOM_STAGE_TEST;
typedef GrLightingEffect INHERITED;
SkScalar fKD;
};
SkScalar shininess() const { return fShininess; }
private:
+ GR_DECLARE_CUSTOM_STAGE_TEST;
typedef GrLightingEffect INHERITED;
SkScalar fKS;
SkScalar fShininess;
virtual ~GrGLLight() {}
virtual void setupVariables(GrGLShaderBuilder* builder);
virtual void emitVS(SkString* out) const {}
- virtual void emitFuncs(const GrGLShaderBuilder* builder, SkString* out) const {}
+ virtual void emitFuncs(GrGLShaderBuilder* builder) {}
virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
SkString* out,
const char* z) const = 0;
- virtual void emitLightColor(const GrGLShaderBuilder*,
- SkString* out,
+ virtual void emitLightColor(GrGLShaderBuilder*,
const char *surfaceToLight) const;
virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const;
virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
virtual void emitVS(SkString* out) const SK_OVERRIDE;
- virtual void emitFuncs(const GrGLShaderBuilder* builder, SkString* out) const;
+ virtual void emitFuncs(GrGLShaderBuilder* builder);
virtual void emitSurfaceToLight(const GrGLShaderBuilder* builder,
SkString* out,
const char* z) const SK_OVERRIDE;
- virtual void emitLightColor(const GrGLShaderBuilder*,
- SkString* out,
+ virtual void emitLightColor(GrGLShaderBuilder*,
const char *surfaceToLight) const SK_OVERRIDE;
private:
typedef GrGLLight INHERITED;
+ SkString fLightColorFunc;
UniformHandle fLocationUni;
UniformHandle fExponentUni;
UniformHandle fCosOuterConeAngleUni;
///////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
+
+namespace {
+SkPoint3 random_point3(SkRandom* random) {
+ return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
+ SkScalarToFloat(random->nextSScalar1()),
+ SkScalarToFloat(random->nextSScalar1()));
+}
+
+SkLight* create_random_light(SkRandom* random) {
+ int type = random->nextULessThan(3);
+ switch (type) {
+ case 0: {
+ return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU()));
+ }
+ case 1: {
+ return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU()));
+ }
+ case 2: {
+ return SkNEW_ARGS(SkSpotLight, (random_point3(random),
+ random_point3(random),
+ random->nextUScalar1(),
+ random->nextUScalar1(),
+ random->nextU()));
+ }
+ default:
+ GrCrash();
+ return NULL;
+ }
+}
+
+}
+
class GrGLLightingEffect : public GrGLProgramStage {
public:
GrGLLightingEffect(const GrProgramStageFactory& factory,
const char* inputColor,
const char* samplerName) SK_OVERRIDE;
- virtual void emitLightFunc(const GrGLShaderBuilder*, SkString* funcs) = 0;
+ virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0;
static inline StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
const GrCustomStage& stage);
virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
- virtual void emitLightFunc(const GrGLShaderBuilder*, SkString* funcs) SK_OVERRIDE;
+ virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
virtual void setData(const GrGLUniformManager&,
const GrCustomStage&,
const GrRenderTarget*,
GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
const GrCustomStage& stage);
virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
- virtual void emitLightFunc(const GrGLShaderBuilder*, SkString* funcs) SK_OVERRIDE;
+ virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
virtual void setData(const GrGLUniformManager&,
const GrCustomStage&,
const GrRenderTarget*,
this->kd() == s.kd();
}
+GR_DEFINE_CUSTOM_STAGE_TEST(GrDiffuseLightingEffect);
+
+GrCustomStage* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ GrTexture* textures[]) {
+ SkScalar surfaceScale = random->nextSScalar1();
+ SkScalar kd = random->nextUScalar1();
+ SkAutoTUnref<SkLight> light(create_random_light(random));
+ return SkNEW_ARGS(GrDiffuseLightingEffect, (textures[GrCustomStageUnitTest::kAlphaTextureIdx],
+ light, surfaceScale, kd));
+}
+
+
///////////////////////////////////////////////////////////////////////////////
GrGLLightingEffect::GrGLLightingEffect(const GrProgramStageFactory& factory,
const char* inputColor,
const char* samplerName) {
SkString* code = &builder->fFSCode;
- SkString* funcs = &builder->fFSFunctions;
- fLight->emitFuncs(builder, funcs);
- this->emitLightFunc(builder, funcs);
- funcs->appendf("float sobel(float a, float b, float c, float d, float e, float f, float scale) {\n");
- funcs->appendf("\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n");
- funcs->appendf("}\n");
- funcs->appendf("vec3 pointToNormal(float x, float y, float scale) {\n");
- funcs->appendf("\treturn normalize(vec3(-x * scale, -y * scale, 1));\n");
- funcs->appendf("}\n");
- funcs->append("\n\
-vec3 interiorNormal(float m[9], float surfaceScale) {\n\
- return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n\
- sobel(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n\
- surfaceScale);\n}\n");
+ fLight->emitFuncs(builder);
+ SkString lightFunc;
+ this->emitLightFunc(builder, &lightFunc);
+ static const GrGLShaderVar gSobelArgs[] = {
+ GrGLShaderVar("a", kFloat_GrSLType),
+ GrGLShaderVar("b", kFloat_GrSLType),
+ GrGLShaderVar("c", kFloat_GrSLType),
+ GrGLShaderVar("d", kFloat_GrSLType),
+ GrGLShaderVar("e", kFloat_GrSLType),
+ GrGLShaderVar("f", kFloat_GrSLType),
+ GrGLShaderVar("scale", kFloat_GrSLType),
+ };
+ SkString sobelFuncName;
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kFloat_GrSLType,
+ "sobel",
+ SK_ARRAY_COUNT(gSobelArgs),
+ gSobelArgs,
+ "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
+ &sobelFuncName);
+ static const GrGLShaderVar gPointToNormalArgs[] = {
+ GrGLShaderVar("x", kFloat_GrSLType),
+ GrGLShaderVar("y", kFloat_GrSLType),
+ GrGLShaderVar("scale", kFloat_GrSLType),
+ };
+ SkString pointToNormalName;
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec3f_GrSLType,
+ "pointToNormal",
+ SK_ARRAY_COUNT(gPointToNormalArgs),
+ gPointToNormalArgs,
+ "\treturn normalize(vec3(-x * scale, -y * scale, 1));\n",
+ &pointToNormalName);
+
+ static const GrGLShaderVar gInteriorNormalArgs[] = {
+ GrGLShaderVar("m", kFloat_GrSLType, 9),
+ GrGLShaderVar("surfaceScale", kFloat_GrSLType),
+ };
+ SkString interiorNormalBody;
+ interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
+ "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName.c_str(),
+ sobelFuncName.c_str(),
+ sobelFuncName.c_str());
+ SkString interiorNormalName;
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec3f_GrSLType,
+ "interiorNormal",
+ SK_ARRAY_COUNT(gInteriorNormalArgs),
+ gInteriorNormalArgs,
+ interiorNormalBody.c_str(),
+ &interiorNormalName);
code->appendf("\t\tvec2 coord = %s;\n", builder->fSampleCoords.c_str());
code->appendf("\t\tfloat m[9];\n");
arg.appendf("%s * m[4]", surfScale);
fLight->emitSurfaceToLight(builder, code, arg.c_str());
code->appendf(";\n");
- code->appendf("\t\t%s = light(interiorNormal(m, %s), surfaceToLight, ", outputColor, surfScale);
- fLight->emitLightColor(builder, code, "surfaceToLight");
+ code->appendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
+ outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
+ fLight->emitLightColor(builder, "surfaceToLight");
code->appendf(")%s;\n", builder->fModulate.c_str());
}
fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kFloat_GrSLType, "KD");
}
-void GrGLDiffuseLightingEffect::emitLightFunc(const GrGLShaderBuilder* builder, SkString* funcs) {
+void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
const char* kd = builder->getUniformCStr(fKDUni);
- funcs->appendf("vec4 light(vec3 normal, vec3 surfaceToLight, vec3 lightColor) {\n");
- funcs->appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
- funcs->appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
- funcs->appendf("}\n");
+ static const GrGLShaderVar gLightArgs[] = {
+ GrGLShaderVar("normal", kVec3f_GrSLType),
+ GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
+ GrGLShaderVar("lightColor", kVec3f_GrSLType)
+ };
+ SkString lightBody;
+ lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
+ lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec4f_GrSLType,
+ "light",
+ SK_ARRAY_COUNT(gLightArgs),
+ gLightArgs,
+ lightBody.c_str(),
+ funcName);
}
void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman,
this->shininess() == s.shininess();
}
+GR_DEFINE_CUSTOM_STAGE_TEST(GrSpecularLightingEffect);
+
+GrCustomStage* GrSpecularLightingEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ GrTexture* textures[]) {
+ SkScalar surfaceScale = random->nextSScalar1();
+ SkScalar ks = random->nextUScalar1();
+ SkScalar shininess = random->nextUScalar1();
+ SkAutoTUnref<SkLight> light(create_random_light(random));
+ return SkNEW_ARGS(GrSpecularLightingEffect, (textures[GrCustomStageUnitTest::kAlphaTextureIdx],
+ light, surfaceScale, ks, shininess));
+}
+
///////////////////////////////////////////////////////////////////////////////
GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
kFloat_GrSLType, "Shininess");
}
-void GrGLSpecularLightingEffect::emitLightFunc(const GrGLShaderBuilder* builder, SkString* funcs) {
- funcs->appendf("vec4 light(vec3 normal, vec3 surfaceToLight, vec3 lightColor) {\n");
- funcs->appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
-
+void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
const char* ks = builder->getUniformCStr(fKSUni);
const char* shininess = builder->getUniformCStr(fShininessUni);
- funcs->appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
- funcs->appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
- funcs->appendf("}\n");
+
+ static const GrGLShaderVar gLightArgs[] = {
+ GrGLShaderVar("normal", kVec3f_GrSLType),
+ GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
+ GrGLShaderVar("lightColor", kVec3f_GrSLType)
+ };
+ SkString lightBody;
+ lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
+ lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
+ lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec4f_GrSLType,
+ "light",
+ SK_ARRAY_COUNT(gLightArgs),
+ gLightArgs,
+ lightBody.c_str(),
+ funcName);
}
void GrGLSpecularLightingEffect::setData(const GrGLUniformManager& uman,
///////////////////////////////////////////////////////////////////////////////
-void GrGLLight::emitLightColor(const GrGLShaderBuilder* builder,
- SkString* out,
+void GrGLLight::emitLightColor(GrGLShaderBuilder* builder,
const char *surfaceToLight) const {
const char* color = builder->getUniformCStr(fColorUni);
- out->append(color);
+ builder->fFSCode.append(color);
}
void GrGLLight::setupVariables(GrGLShaderBuilder* builder) {
void GrGLSpotLight::emitVS(SkString* out) const {
}
-void GrGLSpotLight::emitFuncs(const GrGLShaderBuilder* builder, SkString* out) const {
+void GrGLSpotLight::emitFuncs(GrGLShaderBuilder* builder) {
const char* exponent = builder->getUniformCStr(fExponentUni);
const char* cosInner = builder->getUniformCStr(fCosInnerConeAngleUni);
const char* cosOuter = builder->getUniformCStr(fCosOuterConeAngleUni);
const char* coneScale = builder->getUniformCStr(fConeScaleUni);
const char* s = builder->getUniformCStr(fSUni);
const char* color = builder->getUniformCStr(fColorUni);
-
- out->appendf("vec3 lightColor(vec3 surfaceToLight) {\n");
- out->appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
- out->appendf("\tif (cosAngle < %s) {\n", cosOuter);
- out->appendf("\t\treturn vec3(0);\n");
- out->appendf("\t}\n");
- out->appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
- out->appendf("\tif (cosAngle < %s) {\n", cosInner);
- out->appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", color, cosOuter, coneScale);
- out->appendf("\t}\n");
- out->appendf("\treturn %s;\n", color);
- out->appendf("}\n");
+ static const GrGLShaderVar gLightColorArgs[] = {
+ GrGLShaderVar("surfaceToLight", kVec3f_GrSLType)
+ };
+ SkString lightColorBody;
+ lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
+ lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
+ lightColorBody.appendf("\t\treturn vec3(0);\n");
+ lightColorBody.appendf("\t}\n");
+ lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
+ lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
+ lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
+ color, cosOuter, coneScale);
+ lightColorBody.appendf("\t}\n");
+ lightColorBody.appendf("\treturn %s;\n", color);
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec3f_GrSLType,
+ "lightColor",
+ SK_ARRAY_COUNT(gLightColorArgs),
+ gLightColorArgs,
+ lightColorBody.c_str(),
+ &fLightColorFunc);
}
void GrGLSpotLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
out->appendf("normalize(%s - vec3(gl_FragCoord.xy, %s))", location, z);
}
-void GrGLSpotLight::emitLightColor(const GrGLShaderBuilder* builder,
- SkString* out, const char *surfaceToLight) const {
- out->appendf("lightColor(%s)", surfaceToLight);
+void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder,
+ const char *surfaceToLight) const {
+ builder->fFSCode.appendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
}
#endif
#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
#include "gl/GrGpuGL.h"
-#include "SkLightingImageFilter.h"
#include "GrProgramStageFactory.h"
+
#include "GrRandom.h"
#include "Test.h"
return r->nextF() > .5f;
}
-SkPoint3 random_point3(GrRandom* r) {
- return SkPoint3(r->nextF(), r->nextF(), r->nextF());
-}
-
typedef GrGLProgram::StageDesc StageDesc;
// TODO: Effects should be able to register themselves for inclusion in the
// randomly generated shaders. They should be able to configure themselves
GrRandom* random,
GrContext* context,
GrTexture* dummyTextures[]) {
- enum EffectType {
- /**
- * Lighting effects don't work in unit test because they assume they insert functions and
- * assume the names are unique. This breaks when there are two light effects in the same
- * shader.
- */
- /*
- kDiffuseDistant_EffectType,
- kDiffusePoint_EffectType,
- kDiffuseSpot_EffectType,
- kSpecularDistant_EffectType,
- kSpecularPoint_EffectType,
- kSpecularSpot_EffectType,
- */
-
- kEffectCount
- };
// TODO: Remove this when generator doesn't apply this non-custom-stage
// notion to custom stages automatically.
// TODO: Remove GrRandom.
SkRandom sk_random;
sk_random.setSeed(random->nextU());
-
- bool useFactory = random_bool(random);
- if (useFactory) {
- GrCustomStage* stage = GrCustomStageTestFactory::CreateStage(&sk_random,
- context,
- dummyTextures);
- GrAssert(stage);
- return stage;
- }
-
-
- // TODO: When matrices are property of the custom-stage then remove the
- // no-persp flag code below.
- int effect = random_int(random, kEffectCount);
-/* switch (effect) {
- case kDiffuseDistant_EffectType: {
- SkPoint3 direction = random_point3(random);
- direction.normalize();
- SkColor lightColor = random->nextU();
- SkScalar surfaceScale = SkFloatToScalar(random->nextF());
- SkScalar kd = SkFloatToScalar(random->nextF());
- SkAutoTUnref<SkImageFilter> filter(SkLightingImageFilter::CreateDistantLitDiffuse(direction, lightColor, surfaceScale, kd));
- // does not work with perspective or mul-by-alpha-mask
- GrCustomStage* stage;
- bool ok = filter->asNewCustomStage(&stage, NULL);
- SkASSERT(ok);
- return stage;
- }
- case kDiffusePoint_EffectType: {
- SkPoint3 location = random_point3(random);
- SkColor lightColor = random->nextU();
- SkScalar surfaceScale = SkFloatToScalar(random->nextF());
- SkScalar kd = SkFloatToScalar(random->nextF());
- SkAutoTUnref<SkImageFilter> filter(SkLightingImageFilter::CreatePointLitDiffuse(location, lightColor, surfaceScale, kd));
- // does not work with perspective or mul-by-alpha-mask
- GrCustomStage* stage;
- bool ok = filter->asNewCustomStage(&stage, NULL);
- SkASSERT(ok);
- return stage;
- }
- case kDiffuseSpot_EffectType: {
- SkPoint3 location = random_point3(random);
- SkPoint3 target = random_point3(random);
- SkScalar cutoffAngle = SkFloatToScalar(random->nextF());
- SkScalar specularExponent = SkFloatToScalar(random->nextF());
- SkColor lightColor = random->nextU();
- SkScalar surfaceScale = SkFloatToScalar(random->nextF());
- SkScalar ks = SkFloatToScalar(random->nextF());
- SkScalar shininess = SkFloatToScalar(random->nextF());
- SkAutoTUnref<SkImageFilter> filter(SkLightingImageFilter::CreateSpotLitSpecular(
- location, target, specularExponent, cutoffAngle, lightColor, surfaceScale, ks, shininess));
- // does not work with perspective or mul-by-alpha-mask
- GrCustomStage* stage;
- bool ok = filter->asNewCustomStage(&stage, NULL);
- SkASSERT(ok);
- return stage;
- }
- case kSpecularDistant_EffectType: {
- SkPoint3 direction = random_point3(random);
- direction.normalize();
- SkColor lightColor = random->nextU();
- SkScalar surfaceScale = SkFloatToScalar(random->nextF());
- SkScalar ks = SkFloatToScalar(random->nextF());
- SkScalar shininess = SkFloatToScalar(random->nextF());
- SkAutoTUnref<SkImageFilter> filter(SkLightingImageFilter::CreateDistantLitSpecular(direction, lightColor, surfaceScale, ks, shininess));
- // does not work with perspective or mul-by-alpha-mask
- GrCustomStage* stage;
- bool ok = filter->asNewCustomStage(&stage, NULL);
- SkASSERT(ok);
- return stage;
- }
- case kSpecularPoint_EffectType: {
- SkPoint3 location = random_point3(random);
- SkColor lightColor = random->nextU();
- SkScalar surfaceScale = SkFloatToScalar(random->nextF());
- SkScalar ks = SkFloatToScalar(random->nextF());
- SkScalar shininess = SkFloatToScalar(random->nextF());
- SkAutoTUnref<SkImageFilter> filter(SkLightingImageFilter::CreatePointLitSpecular(location, lightColor, surfaceScale, ks, shininess));
- // does not work with perspective or mul-by-alpha-mask
- GrCustomStage* stage;
- bool ok = filter->asNewCustomStage(&stage, NULL);
- SkASSERT(ok);
- return stage;
- }
- case kSpecularSpot_EffectType: {
- SkPoint3 location = random_point3(random);
- SkPoint3 target = random_point3(random);
- SkScalar cutoffAngle = SkFloatToScalar(random->nextF());
- SkScalar specularExponent = SkFloatToScalar(random->nextF());
- SkColor lightColor = random->nextU();
- SkScalar surfaceScale = SkFloatToScalar(random->nextF());
- SkScalar ks = SkFloatToScalar(random->nextF());
- SkScalar shininess = SkFloatToScalar(random->nextF());
- SkAutoTUnref<SkImageFilter> filter(SkLightingImageFilter::CreateSpotLitSpecular(
- location, target, specularExponent, cutoffAngle, lightColor, surfaceScale, ks, shininess));
- // does not work with perspective or mul-by-alpha-mask
- GrCustomStage* stage;
- bool ok = filter->asNewCustomStage(&stage, NULL);
- SkASSERT(ok);
- return stage;
- }
- default:
- GrCrash("Unexpected custom effect type");
- }
- */
- return NULL;
+ GrCustomStage* stage = GrCustomStageTestFactory::CreateStage(&sk_random,
+ context,
+ dummyTextures);
+ GrAssert(stage);
+ return stage;
}
}
#include "TestClassDef.h"
DEFINE_GPUTESTCLASS("GLPrograms", GLProgramsTestClass, GLProgramsTest)
+// This is evil evil evil. The linker may throw away whole translation units as dead code if it
+// thinks none of the functions are called. It will do this even if there are static initilializers
+// in the unit that could pass pointers to functions from the unit out to other translation units!
+// We force some of the effects that would otherwise be discarded to link here.
+
+#include "SkLightingImageFilter.h"
+
+void forceLinking();
+
+void forceLinking() {
+ SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0);
+}
+
#endif