blob: 4466b1ce0472f3212bd1442f20aa16ecb82869d5 [file] [log] [blame]
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +00001
2/*
3 * Copyright 2013 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#include "gm.h"
9#include "SkBitmap.h"
10#include "SkGradientShader.h"
11#include "SkXfermode.h"
12#include "SkColorPriv.h"
13
14#if SK_SUPPORT_GPU
15#include "GrContext.h"
16#include "SkGpuDevice.h"
17#endif
18
19namespace skiagm {
20
21/**
22 * This tests drawing device-covering rects with solid colors and bitmap shaders over a
23 * checkerboard background using different xfermodes.
24 */
25class Xfermodes3GM : public GM {
26public:
27 Xfermodes3GM() {}
28
29protected:
mtklein36352bf2015-03-25 18:17:31 -070030 SkString onShortName() override {
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000031 return SkString("xfermodes3");
32 }
33
mtklein36352bf2015-03-25 18:17:31 -070034 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -070035 return SkISize::Make(630, 1215);
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000036 }
37
mtklein36352bf2015-03-25 18:17:31 -070038 void onDrawBackground(SkCanvas* canvas) override {
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000039 SkPaint bgPaint;
caryclark4ec1ac62015-07-21 07:42:45 -070040 bgPaint.setColor(sk_tool_utils::color_to_565(0xFF70D0E0));
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000041 canvas->drawPaint(bgPaint);
42 }
43
mtklein36352bf2015-03-25 18:17:31 -070044 void onDraw(SkCanvas* canvas) override {
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000045 canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
46
47 SkPaint labelP;
48 labelP.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -070049 sk_tool_utils::set_portable_typeface(&labelP);
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000050
51 static const SkColor kSolidColors[] = {
52 SK_ColorTRANSPARENT,
53 SK_ColorBLUE,
54 0x80808000
55 };
56
57 static const SkColor kBmpAlphas[] = {
58 0xff,
59 0x80,
60 };
61
62 SkAutoTUnref<SkCanvas> tempCanvas(this->possiblyCreateTempCanvas(canvas, kSize, kSize));
63
64 int test = 0;
65 int x = 0, y = 0;
commit-bot@chromium.orgde1559c2013-08-14 19:20:45 +000066 static const struct { SkPaint::Style fStyle; SkScalar fWidth; } kStrokes[] = {
67 {SkPaint::kFill_Style, 0},
68 {SkPaint::kStroke_Style, SkIntToScalar(kSize) / 2},
69 };
70 for (size_t s = 0; s < SK_ARRAY_COUNT(kStrokes); ++s) {
71 for (size_t m = 0; m <= SkXfermode::kLastMode; ++m) {
72 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(m);
73 canvas->drawText(SkXfermode::ModeName(mode),
74 strlen(SkXfermode::ModeName(mode)),
75 SkIntToScalar(x),
76 SkIntToScalar(y + kSize + 3) + labelP.getTextSize(),
77 labelP);
78 for (size_t c = 0; c < SK_ARRAY_COUNT(kSolidColors); ++c) {
79 SkPaint modePaint;
80 modePaint.setXfermodeMode(mode);
81 modePaint.setColor(kSolidColors[c]);
82 modePaint.setStyle(kStrokes[s].fStyle);
83 modePaint.setStrokeWidth(kStrokes[s].fWidth);
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000084
commit-bot@chromium.orgde1559c2013-08-14 19:20:45 +000085 this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempCanvas.get());
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000086
commit-bot@chromium.orgde1559c2013-08-14 19:20:45 +000087 ++test;
88 x += kSize + 10;
89 if (!(test % kTestsPerRow)) {
90 x = 0;
91 y += kSize + 30;
92 }
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +000093 }
commit-bot@chromium.orgde1559c2013-08-14 19:20:45 +000094 for (size_t a = 0; a < SK_ARRAY_COUNT(kBmpAlphas); ++a) {
95 SkPaint modePaint;
96 modePaint.setXfermodeMode(mode);
97 modePaint.setAlpha(kBmpAlphas[a]);
98 modePaint.setShader(fBmpShader);
99 modePaint.setStyle(kStrokes[s].fStyle);
100 modePaint.setStrokeWidth(kStrokes[s].fWidth);
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000101
commit-bot@chromium.orgde1559c2013-08-14 19:20:45 +0000102 this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempCanvas.get());
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000103
commit-bot@chromium.orgde1559c2013-08-14 19:20:45 +0000104 ++test;
105 x += kSize + 10;
106 if (!(test % kTestsPerRow)) {
107 x = 0;
108 y += kSize + 30;
109 }
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000110 }
111 }
112 }
113 }
114
115private:
116 /**
117 * GrContext has optimizations around full rendertarget draws that can be replaced with clears.
118 * We are trying to test those. We could use saveLayer() to create small SkGpuDevices but
119 * saveLayer() uses the texture cache. This means that the actual render target may be larger
120 * than the layer. Because the clip will contain the layer's bounds, no draws will be full-RT.
121 * So when running on a GPU canvas we explicitly create a temporary canvas using a texture with
122 * dimensions exactly matching the layer size.
123 */
124 SkCanvas* possiblyCreateTempCanvas(SkCanvas* baseCanvas, int w, int h) {
halcanary96fcdcc2015-08-27 07:41:13 -0700125 SkCanvas* tempCanvas = nullptr;
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000126#if SK_SUPPORT_GPU
reed52d9ac62014-06-30 09:05:34 -0700127 GrContext* context = baseCanvas->getGrContext();
bsalomonafe30052015-01-16 07:32:33 -0800128 SkImageInfo baseInfo = baseCanvas->imageInfo();
129 SkImageInfo info = SkImageInfo::Make(w, h, baseInfo.colorType(), baseInfo.alphaType(),
130 baseInfo.profileType());
131 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted,
halcanary96fcdcc2015-08-27 07:41:13 -0700132 info, 0, nullptr));
bsalomonafe30052015-01-16 07:32:33 -0800133 if (surface) {
134 tempCanvas = SkRef(surface->getCanvas());
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000135 }
136#endif
137 return tempCanvas;
138 }
139
140 void drawMode(SkCanvas* canvas,
141 int x, int y, int w, int h,
142 const SkPaint& modePaint, SkCanvas* layerCanvas) {
143 canvas->save();
144
145 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
146
147 SkRect r = SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h));
148
149 SkCanvas* modeCanvas;
halcanary96fcdcc2015-08-27 07:41:13 -0700150 if (nullptr == layerCanvas) {
151 canvas->saveLayer(&r, nullptr);
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000152 modeCanvas = canvas;
153 } else {
154 modeCanvas = layerCanvas;
155 }
156
157 SkPaint bgPaint;
158 bgPaint.setAntiAlias(false);
159 bgPaint.setShader(fBGShader);
160 modeCanvas->drawRect(r, bgPaint);
161 modeCanvas->drawRect(r, modePaint);
halcanary96fcdcc2015-08-27 07:41:13 -0700162 modeCanvas = nullptr;
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000163
halcanary96fcdcc2015-08-27 07:41:13 -0700164 if (nullptr == layerCanvas) {
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000165 canvas->restore();
166 } else {
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000167 SkAutoROCanvasPixels ropixels(layerCanvas);
168 SkBitmap bitmap;
169 if (ropixels.asROBitmap(&bitmap)) {
170 canvas->drawBitmap(bitmap, 0, 0);
171 }
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000172 }
173
174 r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
175 SkPaint borderPaint;
176 borderPaint.setStyle(SkPaint::kStroke_Style);
177 canvas->drawRect(r, borderPaint);
178
179 canvas->restore();
180 }
181
mtklein36352bf2015-03-25 18:17:31 -0700182 void onOnceBeforeDraw() override {
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000183 static const uint32_t kCheckData[] = {
caryclark4ec1ac62015-07-21 07:42:45 -0700184 SkPackARGB32(0xFF, 0x42, 0x41, 0x42),
185 SkPackARGB32(0xFF, 0xD6, 0xD3, 0xD6),
186 SkPackARGB32(0xFF, 0xD6, 0xD3, 0xD6),
187 SkPackARGB32(0xFF, 0x42, 0x41, 0x42)
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000188 };
189 SkBitmap bg;
reed@google.comeb9a46c2014-01-25 16:46:20 +0000190 bg.allocN32Pixels(2, 2, true);
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000191 SkAutoLockPixels bgAlp(bg);
192 memcpy(bg.getPixels(), kCheckData, sizeof(kCheckData));
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000193
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000194 SkMatrix lm;
195 lm.setScale(SkIntToScalar(kCheckSize), SkIntToScalar(kCheckSize));
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000196 fBGShader.reset(SkShader::CreateBitmapShader(bg,
197 SkShader::kRepeat_TileMode,
198 SkShader::kRepeat_TileMode,
199 &lm));
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000200
201 SkPaint bmpPaint;
202 static const SkPoint kCenter = { SkIntToScalar(kSize) / 2, SkIntToScalar(kSize) / 2 };
203 static const SkColor kColors[] = { SK_ColorTRANSPARENT, 0x80800000,
204 0xF020F060, SK_ColorWHITE };
205 bmpPaint.setShader(SkGradientShader::CreateRadial(kCenter,
206 3 * SkIntToScalar(kSize) / 4,
207 kColors,
halcanary96fcdcc2015-08-27 07:41:13 -0700208 nullptr,
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000209 SK_ARRAY_COUNT(kColors),
210 SkShader::kRepeat_TileMode))->unref();
211
212 SkBitmap bmp;
reed@google.comeb9a46c2014-01-25 16:46:20 +0000213 bmp.allocN32Pixels(kSize, kSize);
commit-bot@chromium.org103f2d02013-08-08 21:13:38 +0000214 SkCanvas bmpCanvas(bmp);
215
216 bmpCanvas.clear(SK_ColorTRANSPARENT);
217 SkRect rect = { SkIntToScalar(kSize) / 8, SkIntToScalar(kSize) / 8,
218 7 * SkIntToScalar(kSize) / 8, 7 * SkIntToScalar(kSize) / 8};
219 bmpCanvas.drawRect(rect, bmpPaint);
220
221 fBmpShader.reset(SkShader::CreateBitmapShader(bmp,
222 SkShader::kClamp_TileMode,
223 SkShader::kClamp_TileMode));
224 }
225
226 enum {
227 kCheckSize = 8,
228 kSize = 30,
229 kTestsPerRow = 15,
230 };
231
232 SkAutoTUnref<SkShader> fBGShader;
233 SkAutoTUnref<SkShader> fBmpShader;
234
235 typedef GM INHERITED;
236};
237
238//////////////////////////////////////////////////////////////////////////////
239
240DEF_GM(return new Xfermodes3GM;)
241
242}