blob: e53f5ae8a34f088af434d11f9ae761a5fce13e21 [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"
robertphillips28a838e2016-06-23 14:07:00 -070012#include "GrInvariantOutput.h"
bsalomon87ba62e2015-09-22 06:41:59 -070013#include "effects/GrXfermodeFragmentProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -080014#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080015#include "glsl/GrGLSLFragmentShaderBuilder.h"
16#include "glsl/GrGLSLProgramBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070017#include "glsl/GrGLSLProgramDataManager.h"
bsalomonb0ae6492014-12-29 07:05:27 -080018#include "Resources.h"
mtklein36a364a2015-01-07 08:02:28 -080019#include "SkReadBuffer.h"
bsalomonb0ae6492014-12-29 07:05:27 -080020#include "SkShader.h"
21#include "SkStream.h"
22#include "SkTypeface.h"
mtklein36a364a2015-01-07 08:02:28 -080023#include "SkWriteBuffer.h"
bsalomonb0ae6492014-12-29 07:05:27 -080024
25namespace skiagm {
26
27///////////////////////////////////////////////////////////////////////////////
28
29class DCShader : public SkShader {
30public:
31 DCShader(const SkMatrix& matrix) : fDeviceMatrix(matrix) {}
32
mtklein36a364a2015-01-07 08:02:28 -080033 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DCShader);
34
mtklein36352bf2015-03-25 18:17:31 -070035 void flatten(SkWriteBuffer& buf) const override {
mtklein36a364a2015-01-07 08:02:28 -080036 buf.writeMatrix(fDeviceMatrix);
37 }
bsalomonb0ae6492014-12-29 07:05:27 -080038
brianosman839345d2016-07-22 11:04:53 -070039 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override;
robertphillips42dbfa82015-01-26 06:08:52 -080040
41#ifndef SK_IGNORE_TO_STRING
mtklein36352bf2015-03-25 18:17:31 -070042 void toString(SkString* str) const override {
robertphillips42dbfa82015-01-26 06:08:52 -080043 str->appendf("DCShader: ()");
44 }
45#endif
46
bsalomonb0ae6492014-12-29 07:05:27 -080047private:
48 const SkMatrix fDeviceMatrix;
49};
50
reed60c9b582016-04-03 09:11:13 -070051sk_sp<SkFlattenable> DCShader::CreateProc(SkReadBuffer& buf) {
mtklein36a364a2015-01-07 08:02:28 -080052 SkMatrix matrix;
53 buf.readMatrix(&matrix);
reed60c9b582016-04-03 09:11:13 -070054 return sk_make_sp<DCShader>(matrix);
mtklein36a364a2015-01-07 08:02:28 -080055}
56
bsalomonb0ae6492014-12-29 07:05:27 -080057class DCFP : public GrFragmentProcessor {
58public:
bsalomon4a339522015-10-06 08:40:50 -070059 DCFP(const SkMatrix& m) : fDeviceTransform(kDevice_GrCoordSet, m) {
bsalomonb0ae6492014-12-29 07:05:27 -080060 this->addCoordTransform(&fDeviceTransform);
61 this->initClassID<DCFP>();
62 }
63
egdaniel57d3b032015-11-13 11:57:27 -080064 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -080065 class DCGLFP : public GrGLSLFragmentProcessor {
wangyix7c157a92015-07-22 15:08:53 -070066 void emitCode(EmitArgs& args) override {
egdaniel4ca2e602015-11-18 08:01:26 -080067 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -070068 SkString coords2d = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
69 fragBuilder->codeAppendf("vec2 c = %s;", coords2d.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -080070 fragBuilder->codeAppend("vec2 r = mod(c, vec2(20.0));");
71 fragBuilder->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5,"
72 "0.5*cos((c.x + c.y) / 15.0) + 0.5,"
73 "(r.x + r.y) / 20.0,"
74 "distance(r, vec2(15.0)) / 20.0 + 0.2);");
75 fragBuilder->codeAppendf("color.rgb *= color.a;"
76 "%s = color * %s;",
77 args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
bsalomonb0ae6492014-12-29 07:05:27 -080078 }
egdaniel018fb622015-10-28 07:26:40 -070079 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override {}
bsalomonb0ae6492014-12-29 07:05:27 -080080 };
halcanary385fe4d2015-08-26 13:07:48 -070081 return new DCGLFP;
bsalomonb0ae6492014-12-29 07:05:27 -080082 }
83
mtklein36352bf2015-03-25 18:17:31 -070084 const char* name() const override { return "DCFP"; }
bsalomonb0ae6492014-12-29 07:05:27 -080085
mtklein36352bf2015-03-25 18:17:31 -070086 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
bsalomonb0ae6492014-12-29 07:05:27 -080087 inout->mulByUnknownFourComponents();
88 }
89
90private:
egdaniel57d3b032015-11-13 11:57:27 -080091 void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
92 GrProcessorKeyBuilder* b) const override {}
wangyix4b3050b2015-08-04 07:59:37 -070093
mtklein36352bf2015-03-25 18:17:31 -070094 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
bsalomonb0ae6492014-12-29 07:05:27 -080095
96 GrCoordTransform fDeviceTransform;
97};
98
brianosman839345d2016-07-22 11:04:53 -070099sk_sp<GrFragmentProcessor> DCShader::asFragmentProcessor(const AsFPArgs&) const {
bungeman06ca8ec2016-06-09 08:01:03 -0700100 sk_sp<GrFragmentProcessor> inner(new DCFP(fDeviceMatrix));
101 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
bsalomonb0ae6492014-12-29 07:05:27 -0800102}
103
104class DCShaderGM : public GM {
105public:
106 DCShaderGM() {
caryclark65cdba62015-06-15 06:51:08 -0700107 this->setBGColor(sk_tool_utils::color_to_565(0xFFAABBCC));
bsalomonb0ae6492014-12-29 07:05:27 -0800108 }
109
mtklein36352bf2015-03-25 18:17:31 -0700110 ~DCShaderGM() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800111 for (int i = 0; i < fPrims.count(); ++i) {
halcanary385fe4d2015-08-26 13:07:48 -0700112 delete fPrims[i];
bsalomonb0ae6492014-12-29 07:05:27 -0800113 }
114 }
115
116protected:
bsalomonb0ae6492014-12-29 07:05:27 -0800117
mtklein36352bf2015-03-25 18:17:31 -0700118 SkString onShortName() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800119 return SkString("dcshader");
120 }
121
mtklein36352bf2015-03-25 18:17:31 -0700122 SkISize onISize() override { return SkISize::Make(1000, 900); }
bsalomonb0ae6492014-12-29 07:05:27 -0800123
mtklein36352bf2015-03-25 18:17:31 -0700124 void onOnceBeforeDraw() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800125 struct Rect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700126 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800127 SkRect rect = SkRect::MakeXYWH(0, 0, 50, 50);
128 canvas->drawRect(rect, paint);
129 return rect;
130 }
131 };
132
133 struct Circle : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700134 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
mtkleindbfd7ab2016-09-01 11:24:54 -0700135 constexpr SkScalar radius = 25;
bsalomonb0ae6492014-12-29 07:05:27 -0800136 canvas->drawCircle(radius, radius, radius, paint);
137 return SkRect::MakeXYWH(0, 0, 2 * radius, 2 * radius);
138 }
139 };
140
141 struct RRect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700142 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800143 SkRRect rrect;
144 rrect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 10, 10);
145 canvas->drawRRect(rrect, paint);
146 return rrect.getBounds();
147 }
148 };
149
150 struct DRRect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700151 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800152 SkRRect outerRRect;
153 outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 5, 5);
154 SkRRect innerRRect;
155 innerRRect.setRectXY(SkRect::MakeXYWH(5, 8, 35, 30), 8, 3);
156 canvas->drawDRRect(outerRRect, innerRRect, paint);
157 return outerRRect.getBounds();
158 }
159 };
160 struct Path : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700161 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800162 SkPath path;
163 path.addCircle(15, 15, 10);
164 path.addOval(SkRect::MakeXYWH(2, 2, 22, 37));
165 path.setFillType(SkPath::kEvenOdd_FillType);
166 canvas->drawPath(path, paint);
167 return path.getBounds();
168 }
169 };
170
171 struct Points : public Prim {
172 Points(SkCanvas::PointMode mode) : fMode(mode) {}
173
mtklein36352bf2015-03-25 18:17:31 -0700174 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800175 SkRandom random;
176 SkPoint points[500];
177 SkRect bounds = SkRect::MakeWH(50, 50);
178 int count = SkToInt(SK_ARRAY_COUNT(points));
179 if (SkCanvas::kPoints_PointMode != fMode) {
180 count = SkTMin(count, 10);
181 }
182 for (int p = 0; p < count; ++p) {
183 points[p].fX = random.nextUScalar1() * bounds.width();
184 points[p].fY = random.nextUScalar1() * bounds.width();
185 }
186 canvas->drawPoints(fMode, count, points, paint);
187 return bounds;
188 }
189 SkCanvas::PointMode fMode;
190 };
191
192 struct Text : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700193 SkRect draw(SkCanvas* canvas, const SkPaint& origPaint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800194 SkPaint paint = origPaint;
195 paint.setTextSize(30.f);
196 this->setFont(&paint);
197 const char* text = this->text();
mtkleindbfd7ab2016-09-01 11:24:54 -0700198 const SkVector offset = SkVector::Make(10, 10);
bsalomonb0ae6492014-12-29 07:05:27 -0800199 canvas->drawText(text, strlen(text), offset.fX, offset.fY, paint);
200 SkRect bounds;
201 paint.measureText(text, strlen(text), &bounds);
202 bounds.offset(offset);
203 return bounds;
204 }
205
206 virtual void setFont(SkPaint* paint) {
caryclark1818acb2015-07-24 12:09:25 -0700207 sk_tool_utils::set_portable_typeface(paint);
bsalomonb0ae6492014-12-29 07:05:27 -0800208 }
209
210 virtual const char* text() const { return "Hello, Skia!"; }
211 };
212
halcanary385fe4d2015-08-26 13:07:48 -0700213 fPrims.push_back(new Rect);
214 fPrims.push_back(new Circle);
215 fPrims.push_back(new RRect);
216 fPrims.push_back(new DRRect);
217 fPrims.push_back(new Path);
218 fPrims.push_back(new Points(SkCanvas::kPoints_PointMode));
219 fPrims.push_back(new Points(SkCanvas::kLines_PointMode));
220 fPrims.push_back(new Points(SkCanvas::kPolygon_PointMode));
221 fPrims.push_back(new Text);
bsalomonb0ae6492014-12-29 07:05:27 -0800222 }
223
mtklein36352bf2015-03-25 18:17:31 -0700224 void onDraw(SkCanvas* canvas) override {
bsalomonb62da802015-01-31 07:51:14 -0800225 // This GM exists to test a specific feature of the GPU backend. It does not work with the
226 // sw rasterizer, tile modes, etc.
halcanary96fcdcc2015-08-27 07:41:13 -0700227 if (nullptr == canvas->getGrContext()) {
halcanary2a243382015-09-09 08:16:41 -0700228 skiagm::GM::DrawGpuOnlyMessage(canvas);
bsalomonb62da802015-01-31 07:51:14 -0800229 return;
230 }
bsalomonb0ae6492014-12-29 07:05:27 -0800231 SkPaint paint;
232 SkTArray<SkMatrix> devMats;
233 devMats.push_back().reset();
234 devMats.push_back().setRotate(45, 500, 500);
235 devMats.push_back().setRotate(-30, 200, 200);
reed3f43f8a2015-01-20 19:58:36 -0800236 devMats.back().setPerspX(-SK_Scalar1 / 2000);
237 devMats.back().setPerspY(SK_Scalar1 / 1000);
bsalomonb0ae6492014-12-29 07:05:27 -0800238
239
240 SkTArray<SkMatrix> viewMats;
241 viewMats.push_back().setScale(0.75f, 0.75f);
242 viewMats.push_back().setRotate(45, 50, 50);
243 viewMats.back().postScale(0.5f, 1.1f);
244
245 canvas->translate(10, 20);
246 canvas->save();
247 SkScalar tx = 0, maxTy = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700248 constexpr SkScalar kW = 900;
bsalomonb0ae6492014-12-29 07:05:27 -0800249
250 for (int aa = 0; aa < 2; ++aa) {
251 for (int i = 0; i < fPrims.count(); ++i) {
252 for (int j = 0; j < devMats.count(); ++j) {
253 for (int k = 0; k < viewMats.count(); ++k) {
reedfe630452016-03-25 09:08:00 -0700254 paint.setShader(sk_make_sp<DCShader>(devMats[j]));
bsalomonb0ae6492014-12-29 07:05:27 -0800255 paint.setAntiAlias(SkToBool(aa));
256 canvas->save();
257 canvas->concat(viewMats[k]);
258 SkRect bounds = fPrims[i]->draw(canvas, paint);
259 canvas->restore();
260 viewMats[k].mapRect(&bounds);
261 // add margins
262 bounds.fRight += 20;
263 bounds.fBottom += 20;
264 canvas->translate(bounds.fRight, 0);
265 tx += bounds.fRight;
266 maxTy = SkTMax(bounds.fBottom, maxTy);
267 if (tx > kW) {
268 tx = 0;
269 canvas->restore();
270 canvas->translate(0, maxTy);
271 canvas->save();
272 maxTy = 0;
273 }
274 }
275 }
276 }
277 }
278 canvas->restore();
279 }
280
281private:
282 struct Prim {
283 virtual ~Prim() {}
284 virtual SkRect draw(SkCanvas*, const SkPaint&) = 0;
285 };
286
287 SkTArray<Prim*> fPrims;
288
289 typedef GM INHERITED;
290};
291
halcanary385fe4d2015-08-26 13:07:48 -0700292DEF_GM(return new DCShaderGM;)
bsalomonb0ae6492014-12-29 07:05:27 -0800293}
294#endif