blob: 2b179a0a1fc639680b4a2eea6d5115a848cb2fd3 [file] [log] [blame]
bsalomonb0ae6492014-12-29 07:05:27 -08001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9#if SK_SUPPORT_GPU
10#include "GrFragmentProcessor.h"
11#include "GrCoordTransform.h"
bsalomon87ba62e2015-09-22 06:41:59 -070012#include "effects/GrXfermodeFragmentProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -080013#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080014#include "glsl/GrGLSLFragmentShaderBuilder.h"
15#include "glsl/GrGLSLProgramBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070016#include "glsl/GrGLSLProgramDataManager.h"
bsalomonb0ae6492014-12-29 07:05:27 -080017#include "Resources.h"
mtklein36a364a2015-01-07 08:02:28 -080018#include "SkReadBuffer.h"
bsalomonb0ae6492014-12-29 07:05:27 -080019#include "SkShader.h"
20#include "SkStream.h"
21#include "SkTypeface.h"
mtklein36a364a2015-01-07 08:02:28 -080022#include "SkWriteBuffer.h"
bsalomonb0ae6492014-12-29 07:05:27 -080023
24namespace skiagm {
25
26///////////////////////////////////////////////////////////////////////////////
27
28class DCShader : public SkShader {
29public:
30 DCShader(const SkMatrix& matrix) : fDeviceMatrix(matrix) {}
31
mtklein36a364a2015-01-07 08:02:28 -080032 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DCShader);
33
mtklein36352bf2015-03-25 18:17:31 -070034 void flatten(SkWriteBuffer& buf) const override {
mtklein36a364a2015-01-07 08:02:28 -080035 buf.writeMatrix(fDeviceMatrix);
36 }
bsalomonb0ae6492014-12-29 07:05:27 -080037
bungeman06ca8ec2016-06-09 08:01:03 -070038 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*,
bsalomonc21b09e2015-08-28 18:46:56 -070039 const SkMatrix& viewM,
40 const SkMatrix* localMatrix,
brianosman982eb7f2016-06-06 13:10:58 -070041 SkFilterQuality,
42 SkSourceGammaTreatment) const override;
robertphillips42dbfa82015-01-26 06:08:52 -080043
44#ifndef SK_IGNORE_TO_STRING
mtklein36352bf2015-03-25 18:17:31 -070045 void toString(SkString* str) const override {
robertphillips42dbfa82015-01-26 06:08:52 -080046 str->appendf("DCShader: ()");
47 }
48#endif
49
bsalomonb0ae6492014-12-29 07:05:27 -080050private:
51 const SkMatrix fDeviceMatrix;
52};
53
reed60c9b582016-04-03 09:11:13 -070054sk_sp<SkFlattenable> DCShader::CreateProc(SkReadBuffer& buf) {
mtklein36a364a2015-01-07 08:02:28 -080055 SkMatrix matrix;
56 buf.readMatrix(&matrix);
reed60c9b582016-04-03 09:11:13 -070057 return sk_make_sp<DCShader>(matrix);
mtklein36a364a2015-01-07 08:02:28 -080058}
59
bsalomonb0ae6492014-12-29 07:05:27 -080060class DCFP : public GrFragmentProcessor {
61public:
bsalomon4a339522015-10-06 08:40:50 -070062 DCFP(const SkMatrix& m) : fDeviceTransform(kDevice_GrCoordSet, m) {
bsalomonb0ae6492014-12-29 07:05:27 -080063 this->addCoordTransform(&fDeviceTransform);
64 this->initClassID<DCFP>();
65 }
66
egdaniel57d3b032015-11-13 11:57:27 -080067 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -080068 class DCGLFP : public GrGLSLFragmentProcessor {
wangyix7c157a92015-07-22 15:08:53 -070069 void emitCode(EmitArgs& args) override {
egdaniel4ca2e602015-11-18 08:01:26 -080070 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
71 fragBuilder->codeAppendf("vec2 c = %s;",
72 fragBuilder->ensureFSCoords2D(args.fCoords, 0).c_str());
73 fragBuilder->codeAppend("vec2 r = mod(c, vec2(20.0));");
74 fragBuilder->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5,"
75 "0.5*cos((c.x + c.y) / 15.0) + 0.5,"
76 "(r.x + r.y) / 20.0,"
77 "distance(r, vec2(15.0)) / 20.0 + 0.2);");
78 fragBuilder->codeAppendf("color.rgb *= color.a;"
79 "%s = color * %s;",
80 args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
bsalomonb0ae6492014-12-29 07:05:27 -080081 }
egdaniel018fb622015-10-28 07:26:40 -070082 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override {}
bsalomonb0ae6492014-12-29 07:05:27 -080083 };
halcanary385fe4d2015-08-26 13:07:48 -070084 return new DCGLFP;
bsalomonb0ae6492014-12-29 07:05:27 -080085 }
86
mtklein36352bf2015-03-25 18:17:31 -070087 const char* name() const override { return "DCFP"; }
bsalomonb0ae6492014-12-29 07:05:27 -080088
mtklein36352bf2015-03-25 18:17:31 -070089 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
bsalomonb0ae6492014-12-29 07:05:27 -080090 inout->mulByUnknownFourComponents();
91 }
92
93private:
egdaniel57d3b032015-11-13 11:57:27 -080094 void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
95 GrProcessorKeyBuilder* b) const override {}
wangyix4b3050b2015-08-04 07:59:37 -070096
mtklein36352bf2015-03-25 18:17:31 -070097 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
bsalomonb0ae6492014-12-29 07:05:27 -080098
99 GrCoordTransform fDeviceTransform;
100};
101
bungeman06ca8ec2016-06-09 08:01:03 -0700102sk_sp<GrFragmentProcessor> DCShader::asFragmentProcessor(GrContext*,
bsalomon4a339522015-10-06 08:40:50 -0700103 const SkMatrix& viewM,
104 const SkMatrix* localMatrix,
brianosman982eb7f2016-06-06 13:10:58 -0700105 SkFilterQuality,
106 SkSourceGammaTreatment) const {
bungeman06ca8ec2016-06-09 08:01:03 -0700107 sk_sp<GrFragmentProcessor> inner(new DCFP(fDeviceMatrix));
108 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
bsalomonb0ae6492014-12-29 07:05:27 -0800109}
110
111class DCShaderGM : public GM {
112public:
113 DCShaderGM() {
caryclark65cdba62015-06-15 06:51:08 -0700114 this->setBGColor(sk_tool_utils::color_to_565(0xFFAABBCC));
bsalomonb0ae6492014-12-29 07:05:27 -0800115 }
116
mtklein36352bf2015-03-25 18:17:31 -0700117 ~DCShaderGM() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800118 for (int i = 0; i < fPrims.count(); ++i) {
halcanary385fe4d2015-08-26 13:07:48 -0700119 delete fPrims[i];
bsalomonb0ae6492014-12-29 07:05:27 -0800120 }
121 }
122
123protected:
bsalomonb0ae6492014-12-29 07:05:27 -0800124
mtklein36352bf2015-03-25 18:17:31 -0700125 SkString onShortName() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800126 return SkString("dcshader");
127 }
128
mtklein36352bf2015-03-25 18:17:31 -0700129 SkISize onISize() override { return SkISize::Make(1000, 900); }
bsalomonb0ae6492014-12-29 07:05:27 -0800130
mtklein36352bf2015-03-25 18:17:31 -0700131 void onOnceBeforeDraw() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800132 struct Rect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700133 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800134 SkRect rect = SkRect::MakeXYWH(0, 0, 50, 50);
135 canvas->drawRect(rect, paint);
136 return rect;
137 }
138 };
139
140 struct Circle : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700141 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800142 static const SkScalar radius = 25;
143 canvas->drawCircle(radius, radius, radius, paint);
144 return SkRect::MakeXYWH(0, 0, 2 * radius, 2 * radius);
145 }
146 };
147
148 struct RRect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700149 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800150 SkRRect rrect;
151 rrect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 10, 10);
152 canvas->drawRRect(rrect, paint);
153 return rrect.getBounds();
154 }
155 };
156
157 struct DRRect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700158 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800159 SkRRect outerRRect;
160 outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 5, 5);
161 SkRRect innerRRect;
162 innerRRect.setRectXY(SkRect::MakeXYWH(5, 8, 35, 30), 8, 3);
163 canvas->drawDRRect(outerRRect, innerRRect, paint);
164 return outerRRect.getBounds();
165 }
166 };
167 struct Path : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700168 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800169 SkPath path;
170 path.addCircle(15, 15, 10);
171 path.addOval(SkRect::MakeXYWH(2, 2, 22, 37));
172 path.setFillType(SkPath::kEvenOdd_FillType);
173 canvas->drawPath(path, paint);
174 return path.getBounds();
175 }
176 };
177
178 struct Points : public Prim {
179 Points(SkCanvas::PointMode mode) : fMode(mode) {}
180
mtklein36352bf2015-03-25 18:17:31 -0700181 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800182 SkRandom random;
183 SkPoint points[500];
184 SkRect bounds = SkRect::MakeWH(50, 50);
185 int count = SkToInt(SK_ARRAY_COUNT(points));
186 if (SkCanvas::kPoints_PointMode != fMode) {
187 count = SkTMin(count, 10);
188 }
189 for (int p = 0; p < count; ++p) {
190 points[p].fX = random.nextUScalar1() * bounds.width();
191 points[p].fY = random.nextUScalar1() * bounds.width();
192 }
193 canvas->drawPoints(fMode, count, points, paint);
194 return bounds;
195 }
196 SkCanvas::PointMode fMode;
197 };
198
199 struct Text : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700200 SkRect draw(SkCanvas* canvas, const SkPaint& origPaint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800201 SkPaint paint = origPaint;
202 paint.setTextSize(30.f);
203 this->setFont(&paint);
204 const char* text = this->text();
205 static const SkVector offset = SkVector::Make(10, 10);
206 canvas->drawText(text, strlen(text), offset.fX, offset.fY, paint);
207 SkRect bounds;
208 paint.measureText(text, strlen(text), &bounds);
209 bounds.offset(offset);
210 return bounds;
211 }
212
213 virtual void setFont(SkPaint* paint) {
caryclark1818acb2015-07-24 12:09:25 -0700214 sk_tool_utils::set_portable_typeface(paint);
bsalomonb0ae6492014-12-29 07:05:27 -0800215 }
216
217 virtual const char* text() const { return "Hello, Skia!"; }
218 };
219
halcanary385fe4d2015-08-26 13:07:48 -0700220 fPrims.push_back(new Rect);
221 fPrims.push_back(new Circle);
222 fPrims.push_back(new RRect);
223 fPrims.push_back(new DRRect);
224 fPrims.push_back(new Path);
225 fPrims.push_back(new Points(SkCanvas::kPoints_PointMode));
226 fPrims.push_back(new Points(SkCanvas::kLines_PointMode));
227 fPrims.push_back(new Points(SkCanvas::kPolygon_PointMode));
228 fPrims.push_back(new Text);
bsalomonb0ae6492014-12-29 07:05:27 -0800229 }
230
mtklein36352bf2015-03-25 18:17:31 -0700231 void onDraw(SkCanvas* canvas) override {
bsalomonb62da802015-01-31 07:51:14 -0800232 // This GM exists to test a specific feature of the GPU backend. It does not work with the
233 // sw rasterizer, tile modes, etc.
halcanary96fcdcc2015-08-27 07:41:13 -0700234 if (nullptr == canvas->getGrContext()) {
halcanary2a243382015-09-09 08:16:41 -0700235 skiagm::GM::DrawGpuOnlyMessage(canvas);
bsalomonb62da802015-01-31 07:51:14 -0800236 return;
237 }
bsalomonb0ae6492014-12-29 07:05:27 -0800238 SkPaint paint;
239 SkTArray<SkMatrix> devMats;
240 devMats.push_back().reset();
241 devMats.push_back().setRotate(45, 500, 500);
242 devMats.push_back().setRotate(-30, 200, 200);
reed3f43f8a2015-01-20 19:58:36 -0800243 devMats.back().setPerspX(-SK_Scalar1 / 2000);
244 devMats.back().setPerspY(SK_Scalar1 / 1000);
bsalomonb0ae6492014-12-29 07:05:27 -0800245
246
247 SkTArray<SkMatrix> viewMats;
248 viewMats.push_back().setScale(0.75f, 0.75f);
249 viewMats.push_back().setRotate(45, 50, 50);
250 viewMats.back().postScale(0.5f, 1.1f);
251
252 canvas->translate(10, 20);
253 canvas->save();
254 SkScalar tx = 0, maxTy = 0;
255 static const SkScalar kW = 900;
256
257 for (int aa = 0; aa < 2; ++aa) {
258 for (int i = 0; i < fPrims.count(); ++i) {
259 for (int j = 0; j < devMats.count(); ++j) {
260 for (int k = 0; k < viewMats.count(); ++k) {
reedfe630452016-03-25 09:08:00 -0700261 paint.setShader(sk_make_sp<DCShader>(devMats[j]));
bsalomonb0ae6492014-12-29 07:05:27 -0800262 paint.setAntiAlias(SkToBool(aa));
263 canvas->save();
264 canvas->concat(viewMats[k]);
265 SkRect bounds = fPrims[i]->draw(canvas, paint);
266 canvas->restore();
267 viewMats[k].mapRect(&bounds);
268 // add margins
269 bounds.fRight += 20;
270 bounds.fBottom += 20;
271 canvas->translate(bounds.fRight, 0);
272 tx += bounds.fRight;
273 maxTy = SkTMax(bounds.fBottom, maxTy);
274 if (tx > kW) {
275 tx = 0;
276 canvas->restore();
277 canvas->translate(0, maxTy);
278 canvas->save();
279 maxTy = 0;
280 }
281 }
282 }
283 }
284 }
285 canvas->restore();
286 }
287
288private:
289 struct Prim {
290 virtual ~Prim() {}
291 virtual SkRect draw(SkCanvas*, const SkPaint&) = 0;
292 };
293
294 SkTArray<Prim*> fPrims;
295
296 typedef GM INHERITED;
297};
298
halcanary385fe4d2015-08-26 13:07:48 -0700299DEF_GM(return new DCShaderGM;)
bsalomonb0ae6492014-12-29 07:05:27 -0800300}
301#endif