blob: c14c7856a995fbf2c0844f4c9569485bdbb87f96 [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:
30 virtual SkString onShortName() SK_OVERRIDE {
31 return SkString("xfermodes3");
32 }
33
34 virtual SkISize onISize() SK_OVERRIDE {
35 return make_isize(630, 620);
36 }
37
38 virtual void onDrawBackground(SkCanvas* canvas) SK_OVERRIDE {
39 SkPaint bgPaint;
40 bgPaint.setColor(0xFF70D0E0);
41 canvas->drawPaint(bgPaint);
42 }
43
44 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
45 canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
46
47 SkPaint labelP;
48 labelP.setAntiAlias(true);
49
50 static const SkColor kSolidColors[] = {
51 SK_ColorTRANSPARENT,
52 SK_ColorBLUE,
53 0x80808000
54 };
55
56 static const SkColor kBmpAlphas[] = {
57 0xff,
58 0x80,
59 };
60
61 SkAutoTUnref<SkCanvas> tempCanvas(this->possiblyCreateTempCanvas(canvas, kSize, kSize));
62
63 int test = 0;
64 int x = 0, y = 0;
65 for (size_t m = 0; m <= SkXfermode::kLastMode; ++m) {
66 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(m);
67 canvas->drawText(SkXfermode::ModeName(mode),
68 strlen(SkXfermode::ModeName(mode)),
69 SkIntToScalar(x),
70 SkIntToScalar(y + kSize + 3) + labelP.getTextSize(),
71 labelP);
72 for (size_t c = 0; c < SK_ARRAY_COUNT(kSolidColors); ++c) {
73 SkPaint modePaint;
74 modePaint.setXfermodeMode(mode);
75 modePaint.setColor(kSolidColors[c]);
76
77 this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempCanvas.get());
78
79 ++test;
80 x += kSize + 10;
81 if (!(test % kTestsPerRow)) {
82 x = 0;
83 y += kSize + 30;
84 }
85 }
86 for (size_t a = 0; a < SK_ARRAY_COUNT(kBmpAlphas); ++a) {
87 SkPaint modePaint;
88 modePaint.setXfermodeMode(mode);
89 modePaint.setAlpha(kBmpAlphas[a]);
90 modePaint.setShader(fBmpShader);
91
92 this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempCanvas.get());
93
94 ++test;
95 x += kSize + 10;
96 if (!(test % kTestsPerRow)) {
97 x = 0;
98 y += kSize + 30;
99 }
100 }
101 }
102 }
103
104private:
105 /**
106 * GrContext has optimizations around full rendertarget draws that can be replaced with clears.
107 * We are trying to test those. We could use saveLayer() to create small SkGpuDevices but
108 * saveLayer() uses the texture cache. This means that the actual render target may be larger
109 * than the layer. Because the clip will contain the layer's bounds, no draws will be full-RT.
110 * So when running on a GPU canvas we explicitly create a temporary canvas using a texture with
111 * dimensions exactly matching the layer size.
112 */
113 SkCanvas* possiblyCreateTempCanvas(SkCanvas* baseCanvas, int w, int h) {
114 SkCanvas* tempCanvas = NULL;
115#if SK_SUPPORT_GPU
116 GrRenderTarget* rt = baseCanvas->getDevice()->accessRenderTarget();
117 if (NULL != rt) {
118 GrContext* context = rt->getContext();
119 GrTextureDesc desc;
120 desc.fWidth = w;
121 desc.fHeight = h;
122 desc.fConfig = rt->config();
123 desc.fFlags = kRenderTarget_GrTextureFlagBit;
124 SkAutoTUnref<GrSurface> surface(context->createUncachedTexture(desc, NULL, 0));
125 SkAutoTUnref<SkDevice> device(SkGpuDevice::Create(surface.get()));
126 if (NULL != device.get()) {
127 tempCanvas = SkNEW_ARGS(SkCanvas, (device.get()));
128 }
129 }
130#endif
131 return tempCanvas;
132 }
133
134 void drawMode(SkCanvas* canvas,
135 int x, int y, int w, int h,
136 const SkPaint& modePaint, SkCanvas* layerCanvas) {
137 canvas->save();
138
139 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
140
141 SkRect r = SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h));
142
143 SkCanvas* modeCanvas;
144 if (NULL == layerCanvas) {
145 canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
146 modeCanvas = canvas;
147 } else {
148 modeCanvas = layerCanvas;
149 }
150
151 SkPaint bgPaint;
152 bgPaint.setAntiAlias(false);
153 bgPaint.setShader(fBGShader);
154 modeCanvas->drawRect(r, bgPaint);
155 modeCanvas->drawRect(r, modePaint);
156 modeCanvas = NULL;
157
158 if (NULL == layerCanvas) {
159 canvas->restore();
160 } else {
161 SkBitmap bitmap = layerCanvas->getDevice()->accessBitmap(false);
162 canvas->drawBitmap(bitmap, 0, 0);
163 }
164
165 r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
166 SkPaint borderPaint;
167 borderPaint.setStyle(SkPaint::kStroke_Style);
168 canvas->drawRect(r, borderPaint);
169
170 canvas->restore();
171 }
172
173 virtual void onOnceBeforeDraw() SK_OVERRIDE {
174 static const uint32_t kCheckData[] = {
175 SkPackARGB32(0xFF, 0x40, 0x40, 0x40),
176 SkPackARGB32(0xFF, 0xD0, 0xD0, 0xD0),
177 SkPackARGB32(0xFF, 0xD0, 0xD0, 0xD0),
178 SkPackARGB32(0xFF, 0x40, 0x40, 0x40)
179 };
180 SkBitmap bg;
181 bg.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
182 bg.allocPixels();
183 SkAutoLockPixels bgAlp(bg);
184 memcpy(bg.getPixels(), kCheckData, sizeof(kCheckData));
185 bg.setIsOpaque(true);
186
187 fBGShader.reset(SkShader::CreateBitmapShader(bg,
188 SkShader::kRepeat_TileMode,
189 SkShader::kRepeat_TileMode));
190 SkMatrix lm;
191 lm.setScale(SkIntToScalar(kCheckSize), SkIntToScalar(kCheckSize));
192 fBGShader->setLocalMatrix(lm);
193
194 SkPaint bmpPaint;
195 static const SkPoint kCenter = { SkIntToScalar(kSize) / 2, SkIntToScalar(kSize) / 2 };
196 static const SkColor kColors[] = { SK_ColorTRANSPARENT, 0x80800000,
197 0xF020F060, SK_ColorWHITE };
198 bmpPaint.setShader(SkGradientShader::CreateRadial(kCenter,
199 3 * SkIntToScalar(kSize) / 4,
200 kColors,
201 NULL,
202 SK_ARRAY_COUNT(kColors),
203 SkShader::kRepeat_TileMode))->unref();
204
205 SkBitmap bmp;
206 bmp.setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize);
207 bmp.allocPixels();
208 SkCanvas bmpCanvas(bmp);
209
210 bmpCanvas.clear(SK_ColorTRANSPARENT);
211 SkRect rect = { SkIntToScalar(kSize) / 8, SkIntToScalar(kSize) / 8,
212 7 * SkIntToScalar(kSize) / 8, 7 * SkIntToScalar(kSize) / 8};
213 bmpCanvas.drawRect(rect, bmpPaint);
214
215 fBmpShader.reset(SkShader::CreateBitmapShader(bmp,
216 SkShader::kClamp_TileMode,
217 SkShader::kClamp_TileMode));
218 }
219
220 enum {
221 kCheckSize = 8,
222 kSize = 30,
223 kTestsPerRow = 15,
224 };
225
226 SkAutoTUnref<SkShader> fBGShader;
227 SkAutoTUnref<SkShader> fBmpShader;
228
229 typedef GM INHERITED;
230};
231
232//////////////////////////////////////////////////////////////////////////////
233
234DEF_GM(return new Xfermodes3GM;)
235
236}