Chromium Code Reviews| Index: gm/xfermodes3.cpp |
| diff --git a/gm/xfermodes3.cpp b/gm/xfermodes3.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a4fdcd5dfa75065fd48770c6d586094a1b631f9b |
| --- /dev/null |
| +++ b/gm/xfermodes3.cpp |
| @@ -0,0 +1,236 @@ |
| + |
| +/* |
| + * Copyright 2013 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| +#include "gm.h" |
| +#include "SkBitmap.h" |
| +#include "SkGradientShader.h" |
| +#include "SkXfermode.h" |
| +#include "SkColorPriv.h" |
| + |
| +#if SK_SUPPORT_GPU |
| +#include "GrContext.h" |
| +#include "SkGpuDevice.h" |
| +#endif |
| + |
| +namespace skiagm { |
| + |
| +/** |
| + * This tests drawing device-covering rects with solid colors and bitmap shaders over a |
| + * checkerboard background using different xfermodes. |
| + */ |
| +class Xfermodes3GM : public GM { |
| +public: |
| + Xfermodes3GM() {} |
| + |
| +protected: |
| + virtual SkString onShortName() SK_OVERRIDE { |
| + return SkString("xfermodes3"); |
| + } |
| + |
| + virtual SkISize onISize() SK_OVERRIDE { |
| + return make_isize(630, 620); |
| + } |
| + |
| + virtual void onDrawBackground(SkCanvas* canvas) SK_OVERRIDE { |
| + SkPaint bgPaint; |
| + bgPaint.setColor(0xFF70D0E0); |
| + canvas->drawPaint(bgPaint); |
| + } |
| + |
| + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { |
| + canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); |
| + |
| + SkPaint labelP; |
| + labelP.setAntiAlias(true); |
| + |
| + static const SkColor kSolidColors[] = { |
| + SK_ColorTRANSPARENT, |
| + SK_ColorBLUE, |
| + 0x80808000 |
| + }; |
| + |
| + static const SkColor kBmpAlphas[] = { |
| + 0xff, |
| + 0x80, |
| + }; |
| + |
| + SkAutoTUnref<SkCanvas> tempCanvas(this->possiblyCreateTempCanvas(canvas, kSize, kSize)); |
| + |
| + int test = 0; |
| + int x = 0, y = 0; |
|
robertphillips
2013/08/07 23:16:14
++m
bsalomon
2013/08/08 21:00:37
Done.
|
| + for (size_t m = 0; m <= SkXfermode::kLastMode; m++) { |
| + SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(m); |
| + canvas->drawText(SkXfermode::ModeName(mode), |
| + strlen(SkXfermode::ModeName(mode)), |
| + SkIntToScalar(x), |
| + SkIntToScalar(y + kSize + 3) + labelP.getTextSize(), |
| + labelP); |
| + for (size_t c = 0; c < SK_ARRAY_COUNT(kSolidColors); ++c) { |
| + SkPaint modePaint; |
| + modePaint.setXfermodeMode(mode); |
| + modePaint.setColor(kSolidColors[c]); |
| + |
| + this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempCanvas.get()); |
| + |
| + ++test; |
| + x += kSize + 10; |
| + if (!(test % kTestsPerRow)) { |
| + x = 0; |
| + y += kSize + 30; |
| + } |
| + } |
| + for (size_t a = 0; a < SK_ARRAY_COUNT(kBmpAlphas); ++a) { |
| + SkPaint modePaint; |
| + modePaint.setXfermodeMode(mode); |
| + modePaint.setAlpha(kBmpAlphas[a]); |
| + modePaint.setShader(fBmpShader); |
| + |
| + this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempCanvas.get()); |
| + |
| + ++test; |
| + x += kSize + 10; |
| + if (!(test % kTestsPerRow)) { |
| + x = 0; |
| + y += kSize + 30; |
| + } |
| + } |
| + } |
| + } |
| + |
| +private: |
| + /** |
| + * GrContext has optimizations around full rendertarget draws that can be replaced with clears. |
| + * We are trying to test those. We could use saveLayer() to create small SkGpuDevices but |
| + * saveLayer() uses the texture cache. This means that the actual render target may be larger |
| + * than the layer. Because the clip will contain the layer's bounds, no draws will be full-RT. |
| + * So when running on a GPU canvas we explicitly create a temporary canvas using a texture with |
| + * dimensions exactly matching the layer size. |
| + */ |
| + SkCanvas* possiblyCreateTempCanvas(SkCanvas* baseCanvas, int w, int h) { |
| + SkCanvas* tempCanvas = NULL; |
| +#if SK_SUPPORT_GPU |
| + GrRenderTarget* rt = baseCanvas->getDevice()->accessRenderTarget(); |
| + if (NULL != rt) { |
| + GrContext* context = rt->getContext(); |
| + GrTextureDesc desc; |
| + desc.fWidth = w; |
| + desc.fHeight = h; |
| + desc.fConfig = rt->config(); |
| + desc.fFlags = kRenderTarget_GrTextureFlagBit; |
| + SkAutoTUnref<GrSurface> surface(context->createUncachedTexture(desc, NULL, 0)); |
| + SkAutoTUnref<SkDevice> device(SkGpuDevice::Create(surface.get())); |
| + if (NULL != device.get()) { |
| + tempCanvas = SkNEW_ARGS(SkCanvas, (device.get())); |
| + } |
| + } |
| +#endif |
| + return tempCanvas; |
| + } |
| + |
| + void drawMode(SkCanvas* canvas, |
| + int x, int y, int w, int h, |
|
robertphillips
2013/08/07 23:16:14
const SkPaint& ?
bsalomon
2013/08/08 21:00:37
Done.
|
| + SkPaint& modePaint, SkCanvas* layerCanvas) { |
| + canvas->save(); |
| + |
| + canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); |
| + |
| + SkRect r = SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h)); |
| + |
| + SkCanvas* modeCanvas; |
| + if (NULL == layerCanvas) { |
| + canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag); |
| + modeCanvas = canvas; |
| + } else { |
| + modeCanvas = layerCanvas; |
| + } |
| + |
| + SkPaint bgPaint; |
| + bgPaint.setAntiAlias(false); |
| + bgPaint.setShader(fBG); |
| + modeCanvas->drawRect(r, bgPaint); |
| + modeCanvas->drawRect(r, modePaint); |
| + modeCanvas = NULL; |
| + |
| + if (NULL == layerCanvas) { |
| + canvas->restore(); |
| + } else { |
| + SkBitmap bitmap = layerCanvas->getDevice()->accessBitmap(false); |
| + canvas->drawBitmap(bitmap, 0, 0); |
| + } |
| + |
| + r.inset(-SK_ScalarHalf, -SK_ScalarHalf); |
| + SkPaint borderPaint; |
| + borderPaint.setStyle(SkPaint::kStroke_Style); |
| + canvas->drawRect(r, borderPaint); |
| + |
| + canvas->restore(); |
| + } |
| + |
| + virtual void onOnceBeforeDraw() SK_OVERRIDE { |
| + static const uint32_t kCheckData[] = { |
| + SkPackARGB32(0xFF, 0x40, 0x40, 0x40), |
| + SkPackARGB32(0xFF, 0xD0, 0xD0, 0xD0), |
| + SkPackARGB32(0xFF, 0xD0, 0xD0, 0xD0), |
| + SkPackARGB32(0xFF, 0x40, 0x40, 0x40) |
| + }; |
| + SkBitmap bg; |
| + bg.setConfig(SkBitmap::kARGB_8888_Config, 2, 2); |
| + bg.allocPixels(); |
| + SkAutoLockPixels bgAlp(bg); |
| + memcpy(bg.getPixels(), kCheckData, sizeof(kCheckData)); |
| + bg.setIsOpaque(true); |
| + |
| + fBG.reset(SkShader::CreateBitmapShader(bg, |
| + SkShader::kRepeat_TileMode, |
| + SkShader::kRepeat_TileMode)); |
| + SkMatrix lm; |
| + lm.setScale(SkIntToScalar(kCheckSize), SkIntToScalar(kCheckSize)); |
| + fBG->setLocalMatrix(lm); |
| + |
| + SkBitmap bmp; |
| + bmp.setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize); |
| + bmp.allocPixels(); |
| + |
| + SkPaint bmpPaint; |
| + static const SkPoint kCenter = { SkIntToScalar(kSize) / 2, SkIntToScalar(kSize) / 2 }; |
| + static const SkColor kColors[] = { SK_ColorTRANSPARENT, 0x80800000, |
| + 0xF020F060, SK_ColorWHITE }; |
| + bmpPaint.setShader(SkGradientShader::CreateRadial(kCenter, |
| + 3 * SkIntToScalar(kSize) / 4, |
| + kColors, |
| + NULL, |
| + SK_ARRAY_COUNT(kColors), |
| + SkShader::kRepeat_TileMode))->unref(); |
|
robertphillips
2013/08/07 23:16:14
Move creation & alloc of bmp to right before use i
bsalomon
2013/08/08 21:00:37
Done.
|
| + SkCanvas bmpCanvas(bmp); |
| + bmpCanvas.clear(SK_ColorTRANSPARENT); |
| + SkRect rect = { SkIntToScalar(kSize) / 8, SkIntToScalar(kSize) / 8, |
| + 7 * SkIntToScalar(kSize) / 8, 7 * SkIntToScalar(kSize) / 8}; |
| + bmpCanvas.drawRect(rect, bmpPaint); |
| + |
|
robertphillips
2013/08/07 23:16:14
Is there a better name then fBmpShader? fGradShade
bsalomon
2013/08/08 21:00:37
It is a bmp shader. I'm testing drawing a screen f
|
| + fBmpShader.reset(SkShader::CreateBitmapShader(bmp, |
| + SkShader::kClamp_TileMode, |
| + SkShader::kClamp_TileMode)); |
| + } |
| + |
| + enum { |
| + kCheckSize = 8, |
| + kSize = 30, |
| + kTestsPerRow = 15, |
| + }; |
| + |
|
robertphillips
2013/08/07 23:16:14
fBGShader?
bsalomon
2013/08/08 21:00:37
Done.
|
| + SkAutoTUnref<SkShader> fBG; |
| + SkAutoTUnref<SkShader> fBmpShader; |
| + |
| + typedef GM INHERITED; |
| +}; |
| + |
| +////////////////////////////////////////////////////////////////////////////// |
| + |
|
robertphillips
2013/08/07 23:16:14
DEF_GM?
|
| +static GM* MyFactory(void*) { return new Xfermodes3GM; } |
| +static GMRegistry reg(MyFactory); |
| + |
| +} |