blob: 3ed6dc1296657197b642671e4ad6674cff09b0d3 [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
bungeman06ca8ec2016-06-09 08:01:03 -070039 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*,
bsalomonc21b09e2015-08-28 18:46:56 -070040 const SkMatrix& viewM,
41 const SkMatrix* localMatrix,
brianosman982eb7f2016-06-06 13:10:58 -070042 SkFilterQuality,
43 SkSourceGammaTreatment) const override;
robertphillips42dbfa82015-01-26 06:08:52 -080044
45#ifndef SK_IGNORE_TO_STRING
mtklein36352bf2015-03-25 18:17:31 -070046 void toString(SkString* str) const override {
robertphillips42dbfa82015-01-26 06:08:52 -080047 str->appendf("DCShader: ()");
48 }
49#endif
50
bsalomonb0ae6492014-12-29 07:05:27 -080051private:
52 const SkMatrix fDeviceMatrix;
53};
54
reed60c9b582016-04-03 09:11:13 -070055sk_sp<SkFlattenable> DCShader::CreateProc(SkReadBuffer& buf) {
mtklein36a364a2015-01-07 08:02:28 -080056 SkMatrix matrix;
57 buf.readMatrix(&matrix);
reed60c9b582016-04-03 09:11:13 -070058 return sk_make_sp<DCShader>(matrix);
mtklein36a364a2015-01-07 08:02:28 -080059}
60
bsalomonb0ae6492014-12-29 07:05:27 -080061class DCFP : public GrFragmentProcessor {
62public:
bsalomon4a339522015-10-06 08:40:50 -070063 DCFP(const SkMatrix& m) : fDeviceTransform(kDevice_GrCoordSet, m) {
bsalomonb0ae6492014-12-29 07:05:27 -080064 this->addCoordTransform(&fDeviceTransform);
65 this->initClassID<DCFP>();
66 }
67
egdaniel57d3b032015-11-13 11:57:27 -080068 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -080069 class DCGLFP : public GrGLSLFragmentProcessor {
wangyix7c157a92015-07-22 15:08:53 -070070 void emitCode(EmitArgs& args) override {
egdaniel4ca2e602015-11-18 08:01:26 -080071 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
72 fragBuilder->codeAppendf("vec2 c = %s;",
73 fragBuilder->ensureFSCoords2D(args.fCoords, 0).c_str());
74 fragBuilder->codeAppend("vec2 r = mod(c, vec2(20.0));");
75 fragBuilder->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5,"
76 "0.5*cos((c.x + c.y) / 15.0) + 0.5,"
77 "(r.x + r.y) / 20.0,"
78 "distance(r, vec2(15.0)) / 20.0 + 0.2);");
79 fragBuilder->codeAppendf("color.rgb *= color.a;"
80 "%s = color * %s;",
81 args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
bsalomonb0ae6492014-12-29 07:05:27 -080082 }
egdaniel018fb622015-10-28 07:26:40 -070083 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override {}
bsalomonb0ae6492014-12-29 07:05:27 -080084 };
halcanary385fe4d2015-08-26 13:07:48 -070085 return new DCGLFP;
bsalomonb0ae6492014-12-29 07:05:27 -080086 }
87
mtklein36352bf2015-03-25 18:17:31 -070088 const char* name() const override { return "DCFP"; }
bsalomonb0ae6492014-12-29 07:05:27 -080089
mtklein36352bf2015-03-25 18:17:31 -070090 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
bsalomonb0ae6492014-12-29 07:05:27 -080091 inout->mulByUnknownFourComponents();
92 }
93
94private:
egdaniel57d3b032015-11-13 11:57:27 -080095 void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
96 GrProcessorKeyBuilder* b) const override {}
wangyix4b3050b2015-08-04 07:59:37 -070097
mtklein36352bf2015-03-25 18:17:31 -070098 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
bsalomonb0ae6492014-12-29 07:05:27 -080099
100 GrCoordTransform fDeviceTransform;
101};
102
bungeman06ca8ec2016-06-09 08:01:03 -0700103sk_sp<GrFragmentProcessor> DCShader::asFragmentProcessor(GrContext*,
bsalomon4a339522015-10-06 08:40:50 -0700104 const SkMatrix& viewM,
105 const SkMatrix* localMatrix,
brianosman982eb7f2016-06-06 13:10:58 -0700106 SkFilterQuality,
107 SkSourceGammaTreatment) const {
bungeman06ca8ec2016-06-09 08:01:03 -0700108 sk_sp<GrFragmentProcessor> inner(new DCFP(fDeviceMatrix));
109 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
bsalomonb0ae6492014-12-29 07:05:27 -0800110}
111
112class DCShaderGM : public GM {
113public:
114 DCShaderGM() {
caryclark65cdba62015-06-15 06:51:08 -0700115 this->setBGColor(sk_tool_utils::color_to_565(0xFFAABBCC));
bsalomonb0ae6492014-12-29 07:05:27 -0800116 }
117
mtklein36352bf2015-03-25 18:17:31 -0700118 ~DCShaderGM() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800119 for (int i = 0; i < fPrims.count(); ++i) {
halcanary385fe4d2015-08-26 13:07:48 -0700120 delete fPrims[i];
bsalomonb0ae6492014-12-29 07:05:27 -0800121 }
122 }
123
124protected:
bsalomonb0ae6492014-12-29 07:05:27 -0800125
mtklein36352bf2015-03-25 18:17:31 -0700126 SkString onShortName() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800127 return SkString("dcshader");
128 }
129
mtklein36352bf2015-03-25 18:17:31 -0700130 SkISize onISize() override { return SkISize::Make(1000, 900); }
bsalomonb0ae6492014-12-29 07:05:27 -0800131
mtklein36352bf2015-03-25 18:17:31 -0700132 void onOnceBeforeDraw() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800133 struct Rect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700134 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800135 SkRect rect = SkRect::MakeXYWH(0, 0, 50, 50);
136 canvas->drawRect(rect, paint);
137 return rect;
138 }
139 };
140
141 struct Circle : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700142 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800143 static const SkScalar radius = 25;
144 canvas->drawCircle(radius, radius, radius, paint);
145 return SkRect::MakeXYWH(0, 0, 2 * radius, 2 * radius);
146 }
147 };
148
149 struct RRect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700150 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800151 SkRRect rrect;
152 rrect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 10, 10);
153 canvas->drawRRect(rrect, paint);
154 return rrect.getBounds();
155 }
156 };
157
158 struct DRRect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700159 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800160 SkRRect outerRRect;
161 outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 5, 5);
162 SkRRect innerRRect;
163 innerRRect.setRectXY(SkRect::MakeXYWH(5, 8, 35, 30), 8, 3);
164 canvas->drawDRRect(outerRRect, innerRRect, paint);
165 return outerRRect.getBounds();
166 }
167 };
168 struct Path : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700169 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800170 SkPath path;
171 path.addCircle(15, 15, 10);
172 path.addOval(SkRect::MakeXYWH(2, 2, 22, 37));
173 path.setFillType(SkPath::kEvenOdd_FillType);
174 canvas->drawPath(path, paint);
175 return path.getBounds();
176 }
177 };
178
179 struct Points : public Prim {
180 Points(SkCanvas::PointMode mode) : fMode(mode) {}
181
mtklein36352bf2015-03-25 18:17:31 -0700182 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800183 SkRandom random;
184 SkPoint points[500];
185 SkRect bounds = SkRect::MakeWH(50, 50);
186 int count = SkToInt(SK_ARRAY_COUNT(points));
187 if (SkCanvas::kPoints_PointMode != fMode) {
188 count = SkTMin(count, 10);
189 }
190 for (int p = 0; p < count; ++p) {
191 points[p].fX = random.nextUScalar1() * bounds.width();
192 points[p].fY = random.nextUScalar1() * bounds.width();
193 }
194 canvas->drawPoints(fMode, count, points, paint);
195 return bounds;
196 }
197 SkCanvas::PointMode fMode;
198 };
199
200 struct Text : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700201 SkRect draw(SkCanvas* canvas, const SkPaint& origPaint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800202 SkPaint paint = origPaint;
203 paint.setTextSize(30.f);
204 this->setFont(&paint);
205 const char* text = this->text();
206 static const SkVector offset = SkVector::Make(10, 10);
207 canvas->drawText(text, strlen(text), offset.fX, offset.fY, paint);
208 SkRect bounds;
209 paint.measureText(text, strlen(text), &bounds);
210 bounds.offset(offset);
211 return bounds;
212 }
213
214 virtual void setFont(SkPaint* paint) {
caryclark1818acb2015-07-24 12:09:25 -0700215 sk_tool_utils::set_portable_typeface(paint);
bsalomonb0ae6492014-12-29 07:05:27 -0800216 }
217
218 virtual const char* text() const { return "Hello, Skia!"; }
219 };
220
halcanary385fe4d2015-08-26 13:07:48 -0700221 fPrims.push_back(new Rect);
222 fPrims.push_back(new Circle);
223 fPrims.push_back(new RRect);
224 fPrims.push_back(new DRRect);
225 fPrims.push_back(new Path);
226 fPrims.push_back(new Points(SkCanvas::kPoints_PointMode));
227 fPrims.push_back(new Points(SkCanvas::kLines_PointMode));
228 fPrims.push_back(new Points(SkCanvas::kPolygon_PointMode));
229 fPrims.push_back(new Text);
bsalomonb0ae6492014-12-29 07:05:27 -0800230 }
231
mtklein36352bf2015-03-25 18:17:31 -0700232 void onDraw(SkCanvas* canvas) override {
bsalomonb62da802015-01-31 07:51:14 -0800233 // This GM exists to test a specific feature of the GPU backend. It does not work with the
234 // sw rasterizer, tile modes, etc.
halcanary96fcdcc2015-08-27 07:41:13 -0700235 if (nullptr == canvas->getGrContext()) {
halcanary2a243382015-09-09 08:16:41 -0700236 skiagm::GM::DrawGpuOnlyMessage(canvas);
bsalomonb62da802015-01-31 07:51:14 -0800237 return;
238 }
bsalomonb0ae6492014-12-29 07:05:27 -0800239 SkPaint paint;
240 SkTArray<SkMatrix> devMats;
241 devMats.push_back().reset();
242 devMats.push_back().setRotate(45, 500, 500);
243 devMats.push_back().setRotate(-30, 200, 200);
reed3f43f8a2015-01-20 19:58:36 -0800244 devMats.back().setPerspX(-SK_Scalar1 / 2000);
245 devMats.back().setPerspY(SK_Scalar1 / 1000);
bsalomonb0ae6492014-12-29 07:05:27 -0800246
247
248 SkTArray<SkMatrix> viewMats;
249 viewMats.push_back().setScale(0.75f, 0.75f);
250 viewMats.push_back().setRotate(45, 50, 50);
251 viewMats.back().postScale(0.5f, 1.1f);
252
253 canvas->translate(10, 20);
254 canvas->save();
255 SkScalar tx = 0, maxTy = 0;
256 static const SkScalar kW = 900;
257
258 for (int aa = 0; aa < 2; ++aa) {
259 for (int i = 0; i < fPrims.count(); ++i) {
260 for (int j = 0; j < devMats.count(); ++j) {
261 for (int k = 0; k < viewMats.count(); ++k) {
reedfe630452016-03-25 09:08:00 -0700262 paint.setShader(sk_make_sp<DCShader>(devMats[j]));
bsalomonb0ae6492014-12-29 07:05:27 -0800263 paint.setAntiAlias(SkToBool(aa));
264 canvas->save();
265 canvas->concat(viewMats[k]);
266 SkRect bounds = fPrims[i]->draw(canvas, paint);
267 canvas->restore();
268 viewMats[k].mapRect(&bounds);
269 // add margins
270 bounds.fRight += 20;
271 bounds.fBottom += 20;
272 canvas->translate(bounds.fRight, 0);
273 tx += bounds.fRight;
274 maxTy = SkTMax(bounds.fBottom, maxTy);
275 if (tx > kW) {
276 tx = 0;
277 canvas->restore();
278 canvas->translate(0, maxTy);
279 canvas->save();
280 maxTy = 0;
281 }
282 }
283 }
284 }
285 }
286 canvas->restore();
287 }
288
289private:
290 struct Prim {
291 virtual ~Prim() {}
292 virtual SkRect draw(SkCanvas*, const SkPaint&) = 0;
293 };
294
295 SkTArray<Prim*> fPrims;
296
297 typedef GM INHERITED;
298};
299
halcanary385fe4d2015-08-26 13:07:48 -0700300DEF_GM(return new DCShaderGM;)
bsalomonb0ae6492014-12-29 07:05:27 -0800301}
302#endif