blob: 48ab362944e91744d7f8807f1c7e35c66ff4ff41 [file] [log] [blame]
bsalomon@google.coma8e686e2011-08-16 15:45:58 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
bsalomon@google.comd4726202012-08-03 14:34:46 +00009// This is a GPU-backend specific test. It relies on static intializers to work
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000010
bsalomon@google.com2a48c3a2012-08-03 14:54:45 +000011#include "SkTypes.h"
12
13#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
14
joshualittb0a8a372014-09-23 09:50:21 -070015#include "GrBackendProcessorFactory.h"
bsalomon@google.com67b915d2013-02-04 16:13:32 +000016#include "GrContextFactory.h"
egdanielc0648242014-09-22 13:17:02 -070017#include "GrOptDrawState.h"
bsalomon@google.coma04e8e82012-08-27 12:53:13 +000018#include "effects/GrConfigConversionEffect.h"
kkinnunenec56e452014-08-25 22:21:16 -070019#include "gl/GrGLPathRendering.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000020#include "gl/GrGpuGL.h"
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000021#include "SkChecksum.h"
tfarina@chromium.org223137f2012-11-21 22:38:36 +000022#include "SkRandom.h"
bsalomon@google.comc3841b92012-08-02 18:11:43 +000023#include "Test.h"
24
joshualitt07a25532014-10-07 08:05:21 -070025static const int kRenderTargetHeight = 1;
26static const int kRenderTargetWidth = 1;
egdaniela7dc0a82014-09-17 08:25:05 -070027
joshualitt07a25532014-10-07 08:05:21 -070028static GrRenderTarget* random_render_target(GrGpuGL* gpu,
29 const GrCacheID& cacheId,
30 SkRandom* random) {
31 // setup render target
32 GrTextureParams params;
33 GrTextureDesc texDesc;
34 texDesc.fWidth = kRenderTargetWidth;
35 texDesc.fHeight = kRenderTargetHeight;
36 texDesc.fFlags = kRenderTarget_GrTextureFlagBit;
37 texDesc.fConfig = kRGBA_8888_GrPixelConfig;
38 texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin :
39 kBottomLeft_GrSurfaceOrigin;
bsalomon848faf02014-07-11 10:01:02 -070040
joshualitt07a25532014-10-07 08:05:21 -070041 GrTexture* texture = gpu->getContext()->findAndRefTexture(texDesc, cacheId, &params);
42 if (NULL == texture) {
43 texture = gpu->getContext()->createTexture(&params, texDesc, cacheId, 0, 0);
44 if (NULL == texture) {
45 return NULL;
bsalomon848faf02014-07-11 10:01:02 -070046 }
joshualittbd769d02014-09-04 08:56:46 -070047 }
joshualitt07a25532014-10-07 08:05:21 -070048 return texture->asRenderTarget();
bsalomon@google.com91207482013-02-12 21:45:24 +000049}
50
joshualitt249af152014-09-15 11:41:13 -070051// TODO clean this up, we have to do this to test geometry processors but there has got to be
52// a better way. In the mean time, we actually fill out these generic vertex attribs below with
53// the correct vertex attribs from the GP. We have to ensure, however, we don't try to add more
joshualitt07a25532014-10-07 08:05:21 -070054// than two attributes. In addition, we 'pad' the below array with GPs up to 6 entries, 4 fixed
55// function vertex attributes and 2 GP custom attributes.
56GrVertexAttrib kGenericVertexAttribs[] = {
joshualitt249af152014-09-15 11:41:13 -070057 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
joshualittb0a8a372014-09-23 09:50:21 -070058 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding },
joshualitt07a25532014-10-07 08:05:21 -070059 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding },
60 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding },
61 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding },
joshualittb0a8a372014-09-23 09:50:21 -070062 { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }
joshualitt249af152014-09-15 11:41:13 -070063};
64
65/*
66 * convert sl type to vertexattrib type, not a complete implementation, only use for debugging
67 */
joshualitt07a25532014-10-07 08:05:21 -070068static GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) {
joshualitt249af152014-09-15 11:41:13 -070069 switch (type) {
70 case kFloat_GrSLType:
71 return kFloat_GrVertexAttribType;
72 case kVec2f_GrSLType:
73 return kVec2f_GrVertexAttribType;
74 case kVec3f_GrSLType:
75 return kVec3f_GrVertexAttribType;
76 case kVec4f_GrSLType:
77 return kVec4f_GrVertexAttribType;
78 default:
79 SkFAIL("Type isn't convertible");
80 return kFloat_GrVertexAttribType;
81 }
82}
joshualitt07a25532014-10-07 08:05:21 -070083// end test hack
joshualitt249af152014-09-15 11:41:13 -070084
joshualitt07a25532014-10-07 08:05:21 -070085static void setup_random_ff_attribute(GrVertexAttribBinding binding, GrVertexAttribType type,
86 SkRandom* random, int* attribIndex, int* runningStride) {
87 if (random->nextBool()) {
88 kGenericVertexAttribs[*attribIndex].fType = type;
89 kGenericVertexAttribs[*attribIndex].fOffset = *runningStride;
90 kGenericVertexAttribs[*attribIndex].fBinding = binding;
91 *runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[(*attribIndex)++].fType);
92 }
93}
94
95static void set_random_gp(GrGpuGL* gpu, SkRandom* random, GrTexture* dummyTextures[]) {
96 GrProgramElementRef<const GrGeometryProcessor> gp(
97 GrProcessorTestFactory<GrGeometryProcessor>::CreateStage(random,
98 gpu->getContext(),
99 *gpu->caps(),
100 dummyTextures));
101 SkASSERT(gp);
102
103 // we have to set dummy vertex attributes, first we setup the fixed function attributes
104 // always leave the position attribute untouched in the array
105 int attribIndex = 1;
106 int runningStride = GrVertexAttribTypeSize(kGenericVertexAttribs[0].fType);
107
108 // local coords
109 setup_random_ff_attribute(kLocalCoord_GrVertexAttribBinding, kVec2f_GrVertexAttribType,
110 random, &attribIndex, &runningStride);
111
112 // color
113 setup_random_ff_attribute(kColor_GrVertexAttribBinding, kVec4f_GrVertexAttribType,
114 random, &attribIndex, &runningStride);
115
116 // coverage
117 setup_random_ff_attribute(kCoverage_GrVertexAttribBinding, kVec4f_GrVertexAttribType,
118 random, &attribIndex, &runningStride);
119
120 // Update the geometry processor attributes
121 const GrGeometryProcessor::VertexAttribArray& v = gp->getVertexAttribs();
122 int numGPAttribs = v.count();
123 SkASSERT(numGPAttribs <= GrGeometryProcessor::kMaxVertexAttribs &&
124 GrGeometryProcessor::kMaxVertexAttribs == 2);
125
126 // we actually can't overflow if kMaxVertexAttribs == 2, but GCC 4.8 wants more proof
127 int maxIndex = SK_ARRAY_COUNT(kGenericVertexAttribs);
128 for (int i = 0; i < numGPAttribs && i + attribIndex < maxIndex; i++) {
129 kGenericVertexAttribs[i + attribIndex].fType =
130 convert_sltype_to_attribtype(v[i].getType());
131 kGenericVertexAttribs[i + attribIndex].fOffset = runningStride;
132 kGenericVertexAttribs[i + attribIndex].fBinding = kGeometryProcessor_GrVertexAttribBinding;
133 runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[i + attribIndex].fType);
134 }
135
136 // update the vertex attributes with the ds
137 GrDrawState* ds = gpu->drawState();
138 ds->setVertexAttribs<kGenericVertexAttribs>(attribIndex + numGPAttribs, runningStride);
139 ds->setGeometryProcessor(gp);
140}
141
142static void set_random_color_coverage_stages(GrGpuGL* gpu,
143 int maxStages,
144 bool usePathRendering,
145 SkRandom* random,
146 GrTexture* dummyTextures[]) {
147 int numProcs = random->nextULessThan(maxStages + 1);
148 int numColorProcs = random->nextULessThan(numProcs + 1);
149
150 int currTextureCoordSet = 0;
151 for (int s = 0; s < numProcs;) {
152 GrProgramElementRef<GrFragmentProcessor> fp(
153 GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(random,
154 gpu->getContext(),
155 *gpu->caps(),
156 dummyTextures));
157 SkASSERT(fp);
158
159 // don't add dst color reads to coverage stage
160 if (s >= numColorProcs && fp->willReadDstColor()) {
161 continue;
162 }
163
164 // If adding this effect would exceed the max texture coord set count then generate a
165 // new random effect.
166 if (usePathRendering && gpu->glPathRendering()->texturingMode() ==
167 GrGLPathRendering::FixedFunction_TexturingMode) {;
168 int numTransforms = fp->numTransforms();
169 if (currTextureCoordSet + numTransforms >
170 gpu->glCaps().maxFixedFunctionTextureCoords()) {
171 continue;
172 }
173 currTextureCoordSet += numTransforms;
174 }
175
176 // finally add the stage to the correct pipeline in the drawstate
177 GrDrawState* ds = gpu->drawState();
178 if (s < numColorProcs) {
179 ds->addColorProcessor(fp);
180 } else {
181 ds->addCoverageProcessor(fp);
182 }
183 ++s;
184 }
185}
186
187// There are only a few cases of random colors which interest us
188enum ColorMode {
189 kAllOnes_ColorMode,
190 kAllZeros_ColorMode,
191 kAlphaOne_ColorMode,
192 kRandom_ColorMode,
193 kLast_ColorMode = kRandom_ColorMode
194};
195
196static void set_random_color(GrGpuGL* gpu, SkRandom* random) {
197 ColorMode colorMode = ColorMode(random->nextULessThan(kLast_ColorMode + 1));
198 GrColor color;
199 switch (colorMode) {
200 case kAllOnes_ColorMode:
201 color = GrColorPackRGBA(0xFF, 0xFF, 0xFF, 0xFF);
202 break;
203 case kAllZeros_ColorMode:
204 color = GrColorPackRGBA(0, 0, 0, 0);
205 break;
206 case kAlphaOne_ColorMode:
207 color = GrColorPackRGBA(random->nextULessThan(256),
208 random->nextULessThan(256),
209 random->nextULessThan(256),
210 0xFF);
211 break;
212 case kRandom_ColorMode:
213 uint8_t alpha = random->nextULessThan(256);
214 color = GrColorPackRGBA(random->nextRangeU(0, alpha),
215 random->nextRangeU(0, alpha),
216 random->nextRangeU(0, alpha),
217 alpha);
218 break;
219 }
220 GrColorIsPMAssert(color);
221 gpu->drawState()->setColor(color);
222}
223
224// There are only a few cases of random coverages which interest us
225enum CoverageMode {
226 kZero_CoverageMode,
227 kFF_CoverageMode,
228 kRandom_CoverageMode,
229 kLast_CoverageMode = kRandom_CoverageMode
230};
231
232static void set_random_coverage(GrGpuGL* gpu, SkRandom* random) {
233 CoverageMode coverageMode = CoverageMode(random->nextULessThan(kLast_CoverageMode + 1));
234 uint8_t coverage;
235 switch (coverageMode) {
236 case kZero_CoverageMode:
237 coverage = 0;
238 break;
239 case kFF_CoverageMode:
240 coverage = 0xFF;
241 break;
242 case kRandom_CoverageMode:
243 coverage = uint8_t(random->nextU());
244 break;
245 }
246 gpu->drawState()->setCoverage(coverage);
247}
248
249static void set_random_hints(GrGpuGL* gpu, SkRandom* random) {
250 for (int i = 1; i <= GrDrawState::kLast_Hint; i <<= 1) {
251 gpu->drawState()->setHint(GrDrawState::Hints(i), random->nextBool());
252 }
253}
254
255static void set_random_state(GrGpuGL* gpu, SkRandom* random) {
256 int state = 0;
257 for (int i = 1; i <= GrDrawState::kLastPublicStateBit; i <<= 1) {
258 state |= random->nextBool() * i;
259 }
260 gpu->drawState()->enableState(state);
261}
262
263// this function will randomly pick non-self referencing blend modes
264static void set_random_blend_func(GrGpuGL* gpu, SkRandom* random) {
265 GrBlendCoeff src;
266 do {
267 src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff));
268 } while (GrBlendCoeffRefsSrc(src));
269
270 GrBlendCoeff dst;
271 do {
272 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff));
273 } while (GrBlendCoeffRefsDst(dst));
274
275 gpu->drawState()->setBlendFunc(src, dst);
276}
277
278// right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()'
279static void set_random_stencil(GrGpuGL* gpu, SkRandom* random) {
280 GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil,
281 kReplace_StencilOp,
282 kReplace_StencilOp,
283 kAlways_StencilFunc,
284 0xffff,
285 0xffff,
286 0xffff);
287 GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil,
288 kKeep_StencilOp,
289 kKeep_StencilOp,
290 kNever_StencilFunc,
291 0xffff,
292 0xffff,
293 0xffff);
294
295 if (random->nextBool()) {
296 gpu->drawState()->setStencil(kDoesWriteStencil);
297 } else {
298 gpu->drawState()->setStencil(kDoesNotWriteStencil);
299 }
300}
joshualitt249af152014-09-15 11:41:13 -0700301
bsalomon@google.com042a2862013-02-04 18:39:24 +0000302bool GrGpuGL::programUnitTest(int maxStages) {
joshualitt07a25532014-10-07 08:05:21 -0700303 // setup dummy textures
bsalomon@google.comd4726202012-08-03 14:34:46 +0000304 GrTextureDesc dummyDesc;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000305 dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit;
bsalomon@google.comfec0bc32013-02-07 14:43:04 +0000306 dummyDesc.fConfig = kSkia8888_GrPixelConfig;
bsalomon@google.comd4726202012-08-03 14:34:46 +0000307 dummyDesc.fWidth = 34;
308 dummyDesc.fHeight = 18;
309 SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0));
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000310 dummyDesc.fFlags = kNone_GrTextureFlags;
bsalomon@google.comd4726202012-08-03 14:34:46 +0000311 dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
312 dummyDesc.fWidth = 16;
313 dummyDesc.fHeight = 22;
314 SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0));
315
bsalomone904c092014-07-17 10:50:59 -0700316 if (!dummyTexture1 || ! dummyTexture2) {
joshualitt07a25532014-10-07 08:05:21 -0700317 SkDebugf("Could not allocate dummy textures");
bsalomone904c092014-07-17 10:50:59 -0700318 return false;
319 }
320
joshualitt07a25532014-10-07 08:05:21 -0700321 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
322
323 // Setup texture cache id key
324 const GrCacheID::Domain glProgramsDomain = GrCacheID::GenerateDomain();
325 GrCacheID::Key key;
326 memset(&key, 0, sizeof(key));
327 key.fData32[0] = kRenderTargetWidth;
328 key.fData32[1] = kRenderTargetHeight;
329 GrCacheID glProgramsCacheID(glProgramsDomain, key);
330
331 // setup clip
332 SkRect screen =
333 SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), SkIntToScalar(kRenderTargetHeight));
334
335 SkClipStack stack;
336 stack.clipDevRect(screen, SkRegion::kReplace_Op, false);
337
338 // wrap the SkClipStack in a GrClipData
339 GrClipData clipData;
340 clipData.fClipStack = &stack;
341 this->setClip(&clipData);
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000342
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000343 SkRandom random;
joshualitt07a25532014-10-07 08:05:21 -0700344 static const int NUM_TESTS = 512;
345 for (int t = 0; t < NUM_TESTS;) {
346 // setup random render target(can fail)
347 GrRenderTarget* rtPtr = random_render_target(this, glProgramsCacheID, &random);
348 if (!rtPtr) {
349 SkDebugf("Could not allocate render target");
350 return false;
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000351 }
joshualitt07a25532014-10-07 08:05:21 -0700352 GrTGpuResourceRef<GrRenderTarget> rt(SkRef(rtPtr), GrIORef::kWrite_IOType);
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000353
joshualitt07a25532014-10-07 08:05:21 -0700354 GrDrawState* ds = this->drawState();
355 ds->setRenderTarget(rt.get());
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000356
joshualitt07a25532014-10-07 08:05:21 -0700357 // if path rendering we have to setup a couple of things like the draw type
egdanielae444962014-09-22 12:29:52 -0700358 bool usePathRendering = this->glCaps().pathRenderingSupport() && random.nextBool();
egdanielc0648242014-09-22 13:17:02 -0700359
egdanielae444962014-09-22 12:29:52 -0700360 GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType :
361 GrGpu::kDrawPoints_DrawType;
commit-bot@chromium.org8e919ad2013-10-21 14:48:23 +0000362
joshualitt07a25532014-10-07 08:05:21 -0700363 // twiddle drawstate knobs randomly
egdanielae444962014-09-22 12:29:52 -0700364 bool hasGeometryProcessor = usePathRendering ? false : random.nextBool();
joshualittbd769d02014-09-04 08:56:46 -0700365 if (hasGeometryProcessor) {
joshualitt07a25532014-10-07 08:05:21 -0700366 set_random_gp(this, &random, dummyTextures);
joshualittbd769d02014-09-04 08:56:46 -0700367 }
joshualitt07a25532014-10-07 08:05:21 -0700368 set_random_color_coverage_stages(this, maxStages, usePathRendering, &random, dummyTextures);
369 set_random_color(this, &random);
370 set_random_coverage(this, &random);
371 set_random_hints(this, &random);
372 set_random_state(this, &random);
373 set_random_blend_func(this, &random);
374 set_random_stencil(this, &random);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000375
joshualitt07a25532014-10-07 08:05:21 -0700376 // create optimized draw state, setup readDst texture if required, and build a descriptor
377 // and program. ODS creation can fail, so we have to check
378 SkAutoTUnref<GrOptDrawState> ods(GrOptDrawState::Create(this->getDrawState(),
379 *this->caps(),
380 drawType));
381 if (!ods.get()) {
382 ds->reset();
383 continue;
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000384 }
joshualitt07a25532014-10-07 08:05:21 -0700385 const GrGeometryStage* geometryProcessor = NULL;
386 SkSTArray<8, const GrFragmentStage*, true> colorStages;
387 SkSTArray<8, const GrFragmentStage*, true> coverageStages;
388 GrGLProgramDesc desc;
389 GrDeviceCoordTexture dstCopy;
390
391 if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) {
392 SkDebugf("Couldn't setup dst read texture");
bsalomon848faf02014-07-11 10:01:02 -0700393 return false;
394 }
joshualitt07a25532014-10-07 08:05:21 -0700395 if (!GrGLProgramDesc::Build(*ods,
396 drawType,
397 ods->getSrcBlendCoeff(),
398 ods->getDstBlendCoeff(),
399 this,
400 dstCopy.texture() ? &dstCopy : NULL,
401 &geometryProcessor,
402 &colorStages,
403 &coverageStages,
404 &desc)) {
405 SkDebugf("Failed to generate GL program descriptor");
406 return false;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000407 }
joshualitt07a25532014-10-07 08:05:21 -0700408 SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
409 *ods,
410 desc,
411 geometryProcessor,
412 colorStages.begin(),
413 coverageStages.begin()));
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000414 if (NULL == program.get()) {
joshualitt07a25532014-10-07 08:05:21 -0700415 SkDebugf("Failed to create program!");
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000416 return false;
417 }
joshualitt249af152014-09-15 11:41:13 -0700418
419 // We have to reset the drawstate because we might have added a gp
joshualitt07a25532014-10-07 08:05:21 -0700420 ds->reset();
421
422 // because occasionally optimized drawstate creation will fail for valid reasons, we only
423 // want to increment on success
424 ++t;
bsalomon@google.comc3841b92012-08-02 18:11:43 +0000425 }
426 return true;
427}
bsalomon@google.coma8e686e2011-08-16 15:45:58 +0000428
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +0000429DEF_GPUTEST(GLPrograms, reporter, factory) {
bsalomon@google.com67b915d2013-02-04 16:13:32 +0000430 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
431 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type));
bsalomon49f085d2014-09-05 13:34:00 -0700432 if (context) {
bsalomon@google.com042a2862013-02-04 18:39:24 +0000433 GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000434 int maxStages = 6;
bsalomon@google.com042a2862013-02-04 18:39:24 +0000435#if SK_ANGLE
436 // Some long shaders run out of temporary registers in the D3D compiler on ANGLE.
437 if (type == GrContextFactory::kANGLE_GLContextType) {
438 maxStages = 3;
439 }
440#endif
441 REPORTER_ASSERT(reporter, gpu->programUnitTest(maxStages));
bsalomon@google.com67b915d2013-02-04 16:13:32 +0000442 }
443 }
bsalomon@google.coma8e686e2011-08-16 15:45:58 +0000444}
445
rmistry@google.comd6176b02012-08-23 18:14:13 +0000446// This is evil evil evil. The linker may throw away whole translation units as dead code if it
bsalomon@google.com67e78c92012-10-17 13:36:14 +0000447// thinks none of the functions are called. It will do this even if there are static initializers
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000448// in the unit that could pass pointers to functions from the unit out to other translation units!
449// We force some of the effects that would otherwise be discarded to link here.
450
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000451#include "SkAlphaThresholdFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +0000452#include "SkColorMatrixFilter.h"
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000453#include "SkLightingImageFilter.h"
bsalomon@google.com82aa7482012-08-13 14:22:17 +0000454#include "SkMagnifierImageFilter.h"
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000455
456void forceLinking();
457
458void forceLinking() {
459 SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0);
commit-bot@chromium.org9109e182014-01-07 16:04:01 +0000460 SkAlphaThresholdFilter::Create(SkRegion(), .5f, .5f);
reed9fa60da2014-08-21 07:59:51 -0700461 SkAutoTUnref<SkImageFilter> mag(SkMagnifierImageFilter::Create(
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000462 SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1));
bsalomon@google.comadc65362013-01-28 14:26:09 +0000463 GrConfigConversionEffect::Create(NULL,
464 false,
465 GrConfigConversionEffect::kNone_PMConversion,
466 SkMatrix::I());
bsalomon@google.com67e78c92012-10-17 13:36:14 +0000467 SkScalar matrix[20];
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000468 SkAutoTUnref<SkColorMatrixFilter> cmf(SkColorMatrixFilter::Create(matrix));
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000469}
470
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000471#endif