OLD | NEW |
(Empty) | |
| 1 |
| 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 |
| 19 namespace 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 */ |
| 25 class Xfermodes3GM : public GM { |
| 26 public: |
| 27 Xfermodes3GM() {} |
| 28 |
| 29 protected: |
| 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 |
| 104 private: |
| 105 /** |
| 106 * GrContext has optimizations around full rendertarget draws that can be re
placed with clears. |
| 107 * We are trying to test those. We could use saveLayer() to create small SkG
puDevices but |
| 108 * saveLayer() uses the texture cache. This means that the actual render tar
get may be larger |
| 109 * than the layer. Because the clip will contain the layer's bounds, no draw
s will be full-RT. |
| 110 * So when running on a GPU canvas we explicitly create a temporary canvas u
sing 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(kSiz
e) / 4, |
| 200 kColors, |
| 201 NULL, |
| 202 SK_ARRAY_COUNT(kColors
), |
| 203 SkShader::kRepeat_Tile
Mode))->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 |
| 234 DEF_GM(return new Xfermodes3GM;) |
| 235 |
| 236 } |
OLD | NEW |