blob: 967ff6bf95d25ba81ea9de2e57e674f306c73b1b [file] [log] [blame]
bsalomonb0ae6492014-12-29 07:05:27 -08001
2/*
3 * Copyright 2014 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
9#include "gm.h"
10#if SK_SUPPORT_GPU
11#include "GrFragmentProcessor.h"
12#include "GrCoordTransform.h"
bsalomon87ba62e2015-09-22 06:41:59 -070013#include "effects/GrXfermodeFragmentProcessor.h"
bsalomonb0ae6492014-12-29 07:05:27 -080014#include "gl/GrGLProcessor.h"
15#include "gl/builders/GrGLProgramBuilder.h"
16#include "Resources.h"
mtklein36a364a2015-01-07 08:02:28 -080017#include "SkReadBuffer.h"
bsalomonb0ae6492014-12-29 07:05:27 -080018#include "SkShader.h"
19#include "SkStream.h"
20#include "SkTypeface.h"
mtklein36a364a2015-01-07 08:02:28 -080021#include "SkWriteBuffer.h"
bsalomonb0ae6492014-12-29 07:05:27 -080022
23namespace skiagm {
24
25///////////////////////////////////////////////////////////////////////////////
26
27class DCShader : public SkShader {
28public:
29 DCShader(const SkMatrix& matrix) : fDeviceMatrix(matrix) {}
30
mtklein36a364a2015-01-07 08:02:28 -080031 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DCShader);
32
mtklein36352bf2015-03-25 18:17:31 -070033 void flatten(SkWriteBuffer& buf) const override {
mtklein36a364a2015-01-07 08:02:28 -080034 buf.writeMatrix(fDeviceMatrix);
35 }
bsalomonb0ae6492014-12-29 07:05:27 -080036
bsalomonc21b09e2015-08-28 18:46:56 -070037 const GrFragmentProcessor* asFragmentProcessor(GrContext*,
38 const SkMatrix& viewM,
39 const SkMatrix* localMatrix,
bsalomon4a339522015-10-06 08:40:50 -070040 SkFilterQuality) const override;
robertphillips42dbfa82015-01-26 06:08:52 -080041
42#ifndef SK_IGNORE_TO_STRING
mtklein36352bf2015-03-25 18:17:31 -070043 void toString(SkString* str) const override {
robertphillips42dbfa82015-01-26 06:08:52 -080044 str->appendf("DCShader: ()");
45 }
46#endif
47
bsalomonb0ae6492014-12-29 07:05:27 -080048private:
49 const SkMatrix fDeviceMatrix;
50};
51
mtklein36a364a2015-01-07 08:02:28 -080052SkFlattenable* DCShader::CreateProc(SkReadBuffer& buf) {
53 SkMatrix matrix;
54 buf.readMatrix(&matrix);
halcanary385fe4d2015-08-26 13:07:48 -070055 return new DCShader(matrix);
mtklein36a364a2015-01-07 08:02:28 -080056}
57
bsalomonb0ae6492014-12-29 07:05:27 -080058class DCFP : public GrFragmentProcessor {
59public:
bsalomon4a339522015-10-06 08:40:50 -070060 DCFP(const SkMatrix& m) : fDeviceTransform(kDevice_GrCoordSet, m) {
bsalomonb0ae6492014-12-29 07:05:27 -080061 this->addCoordTransform(&fDeviceTransform);
62 this->initClassID<DCFP>();
63 }
64
wangyixb1daa862015-08-18 11:29:31 -070065 GrGLFragmentProcessor* onCreateGLInstance() const override {
bsalomonb0ae6492014-12-29 07:05:27 -080066 class DCGLFP : public GrGLFragmentProcessor {
wangyix7c157a92015-07-22 15:08:53 -070067 void emitCode(EmitArgs& args) override {
68 GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder();
69 fpb->codeAppendf("vec2 c = %s;", fpb->ensureFSCoords2D(args.fCoords, 0).c_str());
bsalomonb0ae6492014-12-29 07:05:27 -080070 fpb->codeAppend("vec2 r = mod(c, vec2(20.0));");
71 fpb->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 fpb->codeAppendf("color.rgb *= color.a;"
76 "%s = color * %s;",
wangyix7c157a92015-07-22 15:08:53 -070077 args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
bsalomonb0ae6492014-12-29 07:05:27 -080078 }
wangyixb1daa862015-08-18 11:29:31 -070079 void onSetData(const GrGLProgramDataManager&, 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:
wangyix4b3050b2015-08-04 07:59:37 -070091 void onGetGLProcessorKey(const GrGLSLCaps& caps,
92 GrProcessorKeyBuilder* b) const override {}
93
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
bsalomon4a339522015-10-06 08:40:50 -070099const GrFragmentProcessor* DCShader::asFragmentProcessor(GrContext*,
100 const SkMatrix& viewM,
101 const SkMatrix* localMatrix,
102 SkFilterQuality) const {
103 SkAutoTUnref<const GrFragmentProcessor> inner(new DCFP(fDeviceMatrix));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700104 return GrFragmentProcessor::MulOutputByInputAlpha(inner);
bsalomonb0ae6492014-12-29 07:05:27 -0800105}
106
107class DCShaderGM : public GM {
108public:
109 DCShaderGM() {
caryclark65cdba62015-06-15 06:51:08 -0700110 this->setBGColor(sk_tool_utils::color_to_565(0xFFAABBCC));
bsalomonb0ae6492014-12-29 07:05:27 -0800111 }
112
mtklein36352bf2015-03-25 18:17:31 -0700113 ~DCShaderGM() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800114 for (int i = 0; i < fPrims.count(); ++i) {
halcanary385fe4d2015-08-26 13:07:48 -0700115 delete fPrims[i];
bsalomonb0ae6492014-12-29 07:05:27 -0800116 }
117 }
118
119protected:
bsalomonb0ae6492014-12-29 07:05:27 -0800120
mtklein36352bf2015-03-25 18:17:31 -0700121 SkString onShortName() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800122 return SkString("dcshader");
123 }
124
mtklein36352bf2015-03-25 18:17:31 -0700125 SkISize onISize() override { return SkISize::Make(1000, 900); }
bsalomonb0ae6492014-12-29 07:05:27 -0800126
mtklein36352bf2015-03-25 18:17:31 -0700127 void onOnceBeforeDraw() override {
bsalomonb0ae6492014-12-29 07:05:27 -0800128 struct Rect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700129 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800130 SkRect rect = SkRect::MakeXYWH(0, 0, 50, 50);
131 canvas->drawRect(rect, paint);
132 return rect;
133 }
134 };
135
136 struct Circle : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700137 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800138 static const SkScalar radius = 25;
139 canvas->drawCircle(radius, radius, radius, paint);
140 return SkRect::MakeXYWH(0, 0, 2 * radius, 2 * radius);
141 }
142 };
143
144 struct RRect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700145 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800146 SkRRect rrect;
147 rrect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 10, 10);
148 canvas->drawRRect(rrect, paint);
149 return rrect.getBounds();
150 }
151 };
152
153 struct DRRect : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700154 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800155 SkRRect outerRRect;
156 outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 5, 5);
157 SkRRect innerRRect;
158 innerRRect.setRectXY(SkRect::MakeXYWH(5, 8, 35, 30), 8, 3);
159 canvas->drawDRRect(outerRRect, innerRRect, paint);
160 return outerRRect.getBounds();
161 }
162 };
163 struct Path : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700164 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800165 SkPath path;
166 path.addCircle(15, 15, 10);
167 path.addOval(SkRect::MakeXYWH(2, 2, 22, 37));
168 path.setFillType(SkPath::kEvenOdd_FillType);
169 canvas->drawPath(path, paint);
170 return path.getBounds();
171 }
172 };
173
174 struct Points : public Prim {
175 Points(SkCanvas::PointMode mode) : fMode(mode) {}
176
mtklein36352bf2015-03-25 18:17:31 -0700177 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800178 SkRandom random;
179 SkPoint points[500];
180 SkRect bounds = SkRect::MakeWH(50, 50);
181 int count = SkToInt(SK_ARRAY_COUNT(points));
182 if (SkCanvas::kPoints_PointMode != fMode) {
183 count = SkTMin(count, 10);
184 }
185 for (int p = 0; p < count; ++p) {
186 points[p].fX = random.nextUScalar1() * bounds.width();
187 points[p].fY = random.nextUScalar1() * bounds.width();
188 }
189 canvas->drawPoints(fMode, count, points, paint);
190 return bounds;
191 }
192 SkCanvas::PointMode fMode;
193 };
194
195 struct Text : public Prim {
mtklein36352bf2015-03-25 18:17:31 -0700196 SkRect draw(SkCanvas* canvas, const SkPaint& origPaint) override {
bsalomonb0ae6492014-12-29 07:05:27 -0800197 SkPaint paint = origPaint;
198 paint.setTextSize(30.f);
199 this->setFont(&paint);
200 const char* text = this->text();
201 static const SkVector offset = SkVector::Make(10, 10);
202 canvas->drawText(text, strlen(text), offset.fX, offset.fY, paint);
203 SkRect bounds;
204 paint.measureText(text, strlen(text), &bounds);
205 bounds.offset(offset);
206 return bounds;
207 }
208
209 virtual void setFont(SkPaint* paint) {
caryclark1818acb2015-07-24 12:09:25 -0700210 sk_tool_utils::set_portable_typeface(paint);
bsalomonb0ae6492014-12-29 07:05:27 -0800211 }
212
213 virtual const char* text() const { return "Hello, Skia!"; }
214 };
215
halcanary385fe4d2015-08-26 13:07:48 -0700216 fPrims.push_back(new Rect);
217 fPrims.push_back(new Circle);
218 fPrims.push_back(new RRect);
219 fPrims.push_back(new DRRect);
220 fPrims.push_back(new Path);
221 fPrims.push_back(new Points(SkCanvas::kPoints_PointMode));
222 fPrims.push_back(new Points(SkCanvas::kLines_PointMode));
223 fPrims.push_back(new Points(SkCanvas::kPolygon_PointMode));
224 fPrims.push_back(new Text);
bsalomonb0ae6492014-12-29 07:05:27 -0800225 }
226
mtklein36352bf2015-03-25 18:17:31 -0700227 void onDraw(SkCanvas* canvas) override {
bsalomonb62da802015-01-31 07:51:14 -0800228 // This GM exists to test a specific feature of the GPU backend. It does not work with the
229 // sw rasterizer, tile modes, etc.
halcanary96fcdcc2015-08-27 07:41:13 -0700230 if (nullptr == canvas->getGrContext()) {
halcanary2a243382015-09-09 08:16:41 -0700231 skiagm::GM::DrawGpuOnlyMessage(canvas);
bsalomonb62da802015-01-31 07:51:14 -0800232 return;
233 }
bsalomonb0ae6492014-12-29 07:05:27 -0800234 SkPaint paint;
235 SkTArray<SkMatrix> devMats;
236 devMats.push_back().reset();
237 devMats.push_back().setRotate(45, 500, 500);
238 devMats.push_back().setRotate(-30, 200, 200);
reed3f43f8a2015-01-20 19:58:36 -0800239 devMats.back().setPerspX(-SK_Scalar1 / 2000);
240 devMats.back().setPerspY(SK_Scalar1 / 1000);
bsalomonb0ae6492014-12-29 07:05:27 -0800241
242
243 SkTArray<SkMatrix> viewMats;
244 viewMats.push_back().setScale(0.75f, 0.75f);
245 viewMats.push_back().setRotate(45, 50, 50);
246 viewMats.back().postScale(0.5f, 1.1f);
247
248 canvas->translate(10, 20);
249 canvas->save();
250 SkScalar tx = 0, maxTy = 0;
251 static const SkScalar kW = 900;
252
253 for (int aa = 0; aa < 2; ++aa) {
254 for (int i = 0; i < fPrims.count(); ++i) {
255 for (int j = 0; j < devMats.count(); ++j) {
256 for (int k = 0; k < viewMats.count(); ++k) {
halcanary385fe4d2015-08-26 13:07:48 -0700257 paint.setShader(new DCShader(devMats[j]))->unref();
bsalomonb0ae6492014-12-29 07:05:27 -0800258 paint.setAntiAlias(SkToBool(aa));
259 canvas->save();
260 canvas->concat(viewMats[k]);
261 SkRect bounds = fPrims[i]->draw(canvas, paint);
262 canvas->restore();
263 viewMats[k].mapRect(&bounds);
264 // add margins
265 bounds.fRight += 20;
266 bounds.fBottom += 20;
267 canvas->translate(bounds.fRight, 0);
268 tx += bounds.fRight;
269 maxTy = SkTMax(bounds.fBottom, maxTy);
270 if (tx > kW) {
271 tx = 0;
272 canvas->restore();
273 canvas->translate(0, maxTy);
274 canvas->save();
275 maxTy = 0;
276 }
277 }
278 }
279 }
280 }
281 canvas->restore();
282 }
283
284private:
285 struct Prim {
286 virtual ~Prim() {}
287 virtual SkRect draw(SkCanvas*, const SkPaint&) = 0;
288 };
289
290 SkTArray<Prim*> fPrims;
291
292 typedef GM INHERITED;
293};
294
halcanary385fe4d2015-08-26 13:07:48 -0700295DEF_GM(return new DCShaderGM;)
bsalomonb0ae6492014-12-29 07:05:27 -0800296}
297#endif