1b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
2b0ae649b7ebda86ef53bf913798b809d500973edbsalomon/*
3b0ae649b7ebda86ef53bf913798b809d500973edbsalomon * Copyright 2014 Google Inc.
4b0ae649b7ebda86ef53bf913798b809d500973edbsalomon *
5b0ae649b7ebda86ef53bf913798b809d500973edbsalomon * Use of this source code is governed by a BSD-style license that can be
6b0ae649b7ebda86ef53bf913798b809d500973edbsalomon * found in the LICENSE file.
7b0ae649b7ebda86ef53bf913798b809d500973edbsalomon */
8b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
9b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "gm.h"
10b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#if SK_SUPPORT_GPU
11b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "GrFragmentProcessor.h"
12b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "GrCoordTransform.h"
13b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "gl/GrGLProcessor.h"
14b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "gl/builders/GrGLProgramBuilder.h"
15b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "Resources.h"
1636a364a846dd5cee382069430f376286fe6c3af5mtklein#include "SkReadBuffer.h"
17b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "SkShader.h"
18b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "SkStream.h"
19b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#include "SkTypeface.h"
2036a364a846dd5cee382069430f376286fe6c3af5mtklein#include "SkWriteBuffer.h"
21b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
22b0ae649b7ebda86ef53bf913798b809d500973edbsalomonnamespace skiagm {
23b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
24b0ae649b7ebda86ef53bf913798b809d500973edbsalomon///////////////////////////////////////////////////////////////////////////////
25b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
26b0ae649b7ebda86ef53bf913798b809d500973edbsalomonclass DCShader : public SkShader {
27b0ae649b7ebda86ef53bf913798b809d500973edbsalomonpublic:
28b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    DCShader(const SkMatrix& matrix) : fDeviceMatrix(matrix) {}
29b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
3036a364a846dd5cee382069430f376286fe6c3af5mtklein    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DCShader);
3136a364a846dd5cee382069430f376286fe6c3af5mtklein
3236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer& buf) const override {
3336a364a846dd5cee382069430f376286fe6c3af5mtklein        buf.writeMatrix(fDeviceMatrix);
3436a364a846dd5cee382069430f376286fe6c3af5mtklein    }
35b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
36b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& viewM,
37b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                             const SkMatrix* localMatrix, GrColor* color,
3836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                             GrFragmentProcessor** fp) const override;
3942dbfa8651861f2f686879c996aab9f9f82277ddrobertphillips
4042dbfa8651861f2f686879c996aab9f9f82277ddrobertphillips#ifndef SK_IGNORE_TO_STRING
4136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void toString(SkString* str) const override {
4242dbfa8651861f2f686879c996aab9f9f82277ddrobertphillips        str->appendf("DCShader: ()");
4342dbfa8651861f2f686879c996aab9f9f82277ddrobertphillips    }
4442dbfa8651861f2f686879c996aab9f9f82277ddrobertphillips#endif
4542dbfa8651861f2f686879c996aab9f9f82277ddrobertphillips
46b0ae649b7ebda86ef53bf913798b809d500973edbsalomonprivate:
47b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    const SkMatrix fDeviceMatrix;
48b0ae649b7ebda86ef53bf913798b809d500973edbsalomon};
49b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
5036a364a846dd5cee382069430f376286fe6c3af5mtkleinSkFlattenable* DCShader::CreateProc(SkReadBuffer& buf) {
5136a364a846dd5cee382069430f376286fe6c3af5mtklein    SkMatrix matrix;
5236a364a846dd5cee382069430f376286fe6c3af5mtklein    buf.readMatrix(&matrix);
5336a364a846dd5cee382069430f376286fe6c3af5mtklein    return SkNEW_ARGS(DCShader, (matrix));
5436a364a846dd5cee382069430f376286fe6c3af5mtklein}
5536a364a846dd5cee382069430f376286fe6c3af5mtklein
56b0ae649b7ebda86ef53bf913798b809d500973edbsalomonclass DCFP : public GrFragmentProcessor {
57b0ae649b7ebda86ef53bf913798b809d500973edbsalomonpublic:
58b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    DCFP(const SkMatrix& m) : fDeviceTransform(kDevice_GrCoordSet, m) {
59b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        this->addCoordTransform(&fDeviceTransform);
60b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        this->initClassID<DCFP>();
61b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    }
62b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
63cfc18867d982119d9dc2888bf09f1093012daaddjvanverth    void getGLProcessorKey(const GrGLSLCaps& caps,
6436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                            GrProcessorKeyBuilder* b) const override {}
65b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
6636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    GrGLFragmentProcessor* createGLInstance() const override {
67b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        class DCGLFP : public GrGLFragmentProcessor {
68b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            void emitCode(GrGLFPBuilder* builder,
69b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            const GrFragmentProcessor& fp,
70b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            const char* outputColor,
71b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            const char* inputColor,
72b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            const TransformedCoordsArray& coords,
73b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            const TextureSamplerArray& samplers) {
7429bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel                GrGLFragmentBuilder* fpb = builder->getFragmentShaderBuilder();
75b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                fpb->codeAppendf("vec2 c = %s;", fpb->ensureFSCoords2D(coords, 0).c_str());
76b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                fpb->codeAppend("vec2 r = mod(c, vec2(20.0));");
77b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                fpb->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5,"
78b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                                                    "0.5*cos((c.x + c.y) / 15.0) + 0.5,"
79b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                                                    "(r.x + r.y) / 20.0,"
80b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                                                    "distance(r, vec2(15.0)) / 20.0 + 0.2);");
81b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                fpb->codeAppendf("color.rgb *= color.a;"
82b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                                    "%s = color * %s;",
83b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                                    outputColor, GrGLSLExpr4(inputColor).c_str());
84b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
8536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            void setData(const GrGLProgramDataManager&, const GrProcessor&) override {}
86b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
87b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        return SkNEW(DCGLFP);
88b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    }
89b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
9036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "DCFP"; }
91b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
9236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
93b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        inout->mulByUnknownFourComponents();
94b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    }
95b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
96b0ae649b7ebda86ef53bf913798b809d500973edbsalomonprivate:
9736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
98b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
99b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    GrCoordTransform fDeviceTransform;
100b0ae649b7ebda86ef53bf913798b809d500973edbsalomon};
101b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
102b0ae649b7ebda86ef53bf913798b809d500973edbsalomonbool DCShader::asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& viewM,
103b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                                   const SkMatrix* localMatrix, GrColor* color,
104b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                                   GrFragmentProcessor** fp) const {
105b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    *fp = SkNEW_ARGS(DCFP, (fDeviceMatrix));
106b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    *color = GrColorPackA4(paint.getAlpha());
107b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    return true;
108b0ae649b7ebda86ef53bf913798b809d500973edbsalomon}
109b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
110b0ae649b7ebda86ef53bf913798b809d500973edbsalomonclass DCShaderGM : public GM {
111b0ae649b7ebda86ef53bf913798b809d500973edbsalomonpublic:
112b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    DCShaderGM() {
113b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        this->setBGColor(0xFFAABBCC);
114b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    }
115b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
11636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    ~DCShaderGM() override {
117b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        for (int i = 0; i < fPrims.count(); ++i) {
118b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            SkDELETE(fPrims[i]);
119b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        }
120b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    }
121b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
122b0ae649b7ebda86ef53bf913798b809d500973edbsalomonprotected:
123b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
12436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override {
125b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        return SkString("dcshader");
126b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    }
127b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
12836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override { return SkISize::Make(1000, 900); }
129b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
13036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onOnceBeforeDraw() override {
131b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        struct Rect : public Prim {
13236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
133b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkRect rect = SkRect::MakeXYWH(0, 0, 50, 50);
134b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                canvas->drawRect(rect, paint);
135b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return rect;
136b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
137b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
138b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
139b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        struct Circle : public Prim {
14036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
141b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                static const SkScalar radius = 25;
142b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                canvas->drawCircle(radius, radius, radius, paint);
143b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return SkRect::MakeXYWH(0, 0, 2 * radius, 2 * radius);
144b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
145b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
146b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
147b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        struct RRect : public Prim {
14836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
149b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkRRect rrect;
150b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                rrect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 10, 10);
151b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                canvas->drawRRect(rrect, paint);
152b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return rrect.getBounds();
153b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
154b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
155b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
156b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        struct DRRect : public Prim {
15736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
158b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkRRect outerRRect;
159b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 5, 5);
160b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkRRect innerRRect;
161b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                innerRRect.setRectXY(SkRect::MakeXYWH(5, 8, 35, 30), 8, 3);
162b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                canvas->drawDRRect(outerRRect, innerRRect, paint);
163b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return outerRRect.getBounds();
164b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
165b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
166b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        struct Path : public Prim {
16736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
168b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkPath path;
169b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                path.addCircle(15, 15, 10);
170b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                path.addOval(SkRect::MakeXYWH(2, 2, 22, 37));
171b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                path.setFillType(SkPath::kEvenOdd_FillType);
172b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                canvas->drawPath(path, paint);
173b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return path.getBounds();
174b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
175b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
176b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
177b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        struct Points : public Prim {
178b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            Points(SkCanvas::PointMode mode) : fMode(mode) {}
179b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
18036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
181b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkRandom random;
182b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkPoint points[500];
183b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkRect bounds = SkRect::MakeWH(50, 50);
184b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                int count = SkToInt(SK_ARRAY_COUNT(points));
185b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                if (SkCanvas::kPoints_PointMode != fMode) {
186b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                    count = SkTMin(count, 10);
187b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                }
188b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                for (int p = 0; p < count; ++p) {
189b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                    points[p].fX = random.nextUScalar1() * bounds.width();
190b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                    points[p].fY = random.nextUScalar1() * bounds.width();
191b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                }
192b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                canvas->drawPoints(fMode, count, points, paint);
193b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return bounds;
194b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
195b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            SkCanvas::PointMode fMode;
196b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
197b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
198b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        struct Text : public Prim {
19936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            SkRect draw(SkCanvas* canvas, const SkPaint& origPaint) override {
200b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkPaint paint = origPaint;
201b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                paint.setTextSize(30.f);
202b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                this->setFont(&paint);
203b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                const char* text = this->text();
204b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                static const SkVector offset = SkVector::Make(10, 10);
205b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                canvas->drawText(text, strlen(text), offset.fX, offset.fY, paint);
206b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                SkRect bounds;
207b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                paint.measureText(text, strlen(text), &bounds);
208b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                bounds.offset(offset);
209b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return bounds;
210b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
211b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
212b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            virtual void setFont(SkPaint* paint) {
213b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                sk_tool_utils::set_portable_typeface(paint);
214b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
215b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
216b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            virtual const char* text() const { return "Hello, Skia!"; }
217b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
218b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
219b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        struct BmpText : public Text {
22036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein           void setFont(SkPaint* paint) override {
221b0ae649b7ebda86ef53bf913798b809d500973edbsalomon               if (!fTypeface) {
2223ffa126066542590dc7430514a1174e49191b875bungeman                    fTypeface.reset(GetResourceAsTypeface("/fonts/Funkster.ttf"));
223b0ae649b7ebda86ef53bf913798b809d500973edbsalomon               }
224b0ae649b7ebda86ef53bf913798b809d500973edbsalomon               paint->setTypeface(fTypeface);
225b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
226b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
22736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein            const char* text() const override { return "Hi, Skia!"; }
228b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
229b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            SkAutoTUnref<SkTypeface> fTypeface;
230b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        };
231b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(Rect));
232b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(Circle));
233b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(RRect));
234b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(DRRect));
235b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(Path));
236b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(Points(SkCanvas::kPoints_PointMode)));
237b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(Points(SkCanvas::kLines_PointMode)));
238b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(Points(SkCanvas::kPolygon_PointMode)));
239b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(Text));
240b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        fPrims.push_back(SkNEW(BmpText));
241b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    }
242b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
24336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
244b62da80cbf6643c1944d3ebf8df233f286bd3fdebsalomon        // This GM exists to test a specific feature of the GPU backend. It does not work with the
245b62da80cbf6643c1944d3ebf8df233f286bd3fdebsalomon        // sw rasterizer, tile modes, etc.
246b62da80cbf6643c1944d3ebf8df233f286bd3fdebsalomon        if (NULL == canvas->getGrContext()) {
247b62da80cbf6643c1944d3ebf8df233f286bd3fdebsalomon            this->drawGpuOnlyMessage(canvas);
248b62da80cbf6643c1944d3ebf8df233f286bd3fdebsalomon            return;
249b62da80cbf6643c1944d3ebf8df233f286bd3fdebsalomon        }
250b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        SkPaint paint;
251b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        SkTArray<SkMatrix> devMats;
252b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        devMats.push_back().reset();
253b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        devMats.push_back().setRotate(45, 500, 500);
254b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        devMats.push_back().setRotate(-30, 200, 200);
2553f43f8ab9cd3ba0ea83f5ae0659c21f101dfca7areed        devMats.back().setPerspX(-SK_Scalar1 / 2000);
2563f43f8ab9cd3ba0ea83f5ae0659c21f101dfca7areed        devMats.back().setPerspY(SK_Scalar1 / 1000);
257b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
258b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
259b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        SkTArray<SkMatrix> viewMats;
260b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        viewMats.push_back().setScale(0.75f, 0.75f);
261b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        viewMats.push_back().setRotate(45, 50, 50);
262b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        viewMats.back().postScale(0.5f, 1.1f);
263b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
264b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        canvas->translate(10, 20);
265b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        canvas->save();
266b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        SkScalar tx = 0, maxTy = 0;
267b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        static const SkScalar kW = 900;
268b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
269b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        for (int aa = 0; aa < 2; ++aa) {
270b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            for (int i = 0; i < fPrims.count(); ++i) {
271b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                for (int j = 0; j < devMats.count(); ++j) {
272b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                    for (int k = 0; k < viewMats.count(); ++k) {
273b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        paint.setShader(SkNEW_ARGS(DCShader, (devMats[j])))->unref();
274b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        paint.setAntiAlias(SkToBool(aa));
275b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        canvas->save();
276b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        canvas->concat(viewMats[k]);
277b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        SkRect bounds = fPrims[i]->draw(canvas, paint);
278b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        canvas->restore();
279b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        viewMats[k].mapRect(&bounds);
280b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        // add margins
281b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        bounds.fRight += 20;
282b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        bounds.fBottom += 20;
283b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        canvas->translate(bounds.fRight, 0);
284b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        tx += bounds.fRight;
285b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        maxTy = SkTMax(bounds.fBottom, maxTy);
286b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        if (tx > kW) {
287b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            tx = 0;
288b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            canvas->restore();
289b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            canvas->translate(0, maxTy);
290b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            canvas->save();
291b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                            maxTy = 0;
292b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                        }
293b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                    }
294b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                }
295b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
296b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        }
297b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        canvas->restore();
298b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    }
299b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
300b0ae649b7ebda86ef53bf913798b809d500973edbsalomonprivate:
301b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    struct Prim {
302b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        virtual ~Prim() {}
303b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        virtual SkRect draw(SkCanvas*, const SkPaint&) = 0;
304b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    };
305b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
306b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    SkTArray<Prim*> fPrims;
307b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
308b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    typedef GM INHERITED;
309b0ae649b7ebda86ef53bf913798b809d500973edbsalomon};
310b0ae649b7ebda86ef53bf913798b809d500973edbsalomon
311b0ae649b7ebda86ef53bf913798b809d500973edbsalomonDEF_GM( return SkNEW(DCShaderGM); )
312b0ae649b7ebda86ef53bf913798b809d500973edbsalomon}
313b0ae649b7ebda86ef53bf913798b809d500973edbsalomon#endif
314