From d9d5385791b9ab47cd482b7d8370336e36867e0e Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Wed, 2 May 2012 13:55:06 +0000 Subject: Added GM test to stress test the texture unit/sampler allocation http://codereview.appspot.com/6134058/ git-svn-id: http://skia.googlecode.com/svn/trunk@3814 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/samplerstress.cpp | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 gm/samplerstress.cpp (limited to 'gm/samplerstress.cpp') diff --git a/gm/samplerstress.cpp b/gm/samplerstress.cpp new file mode 100644 index 0000000000..64abeeccdd --- /dev/null +++ b/gm/samplerstress.cpp @@ -0,0 +1,229 @@ +/* + * Copyright 2012 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 "SkCanvas.h" +#include "SkShader.h" +#include "SkMaskFilter.h" + +namespace skiagm { + + +/** + * Simple MaskFilter that creates a screen door stipple pattern + */ +class SkStippleMaskFilter : public SkMaskFilter { +public: + SkStippleMaskFilter() : INHERITED() { + } + + virtual ~SkStippleMaskFilter() { + } + + virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, + SkIPoint* margin) SK_OVERRIDE { + + if (src.fFormat != SkMask::kA8_Format) { + return false; + } + + dst->fBounds = src.fBounds; + dst->fRowBytes = dst->fBounds.width(); + dst->fFormat = SkMask::kA8_Format; + dst->fImage = NULL; + + if (NULL != src.fImage) { + size_t dstSize = dst->computeImageSize(); + if (0 == dstSize) { + return false; // too big to allocate, abort + } + + dst->fImage = SkMask::AllocImage(dstSize); + + uint8_t* srcScanLine = src.fImage; + uint8_t* scanline = dst->fImage; + + for (int y = 0; y < src.fBounds.height(); ++y) { + for (int x = 0; x < src.fBounds.width(); ++x) { + SkASSERT(unsigned int(scanline - dst->fImage) < dstSize); + scanline[x] = srcScanLine[x] && ((x+y) % 2) ? 0xFF : 0x00; + } + scanline += dst->fRowBytes; + srcScanLine += src.fRowBytes; + } + } + + return true; + } + + static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { + return SkNEW(SkStippleMaskFilter); + } + + virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {} + + // getFactory is from SkFlattenable + virtual Factory getFactory() SK_OVERRIDE { + return CreateProc; + } + + // getFormat is from SkMaskFilter + virtual SkMask::Format getFormat() SK_OVERRIDE { + return SkMask::kA8_Format; + } +protected: + +private: + typedef SkMaskFilter INHERITED; +}; + +/** + * Stress test the samplers by rendering a textured glyph with a mask and + * an AA clip + */ +class SamplerStressGM : public GM { +public: + SamplerStressGM() + : fTextureCreated(false) + , fShader(NULL) + , fMaskFilter(NULL) { + } + + virtual ~SamplerStressGM() { + } + +protected: + virtual SkString onShortName() { + return SkString("samplerstress"); + } + + virtual SkISize onISize() { + return make_isize(640, 480); + } + + /** + * Create a red & green stripes on black texture + */ + void createTexture() { + if (fTextureCreated) { + return; + } + + static const int xSize = 16; + static const int ySize = 16; + + fTexture.setConfig(SkBitmap::kARGB_8888_Config, + xSize, + ySize, + xSize*sizeof(SkColor)); + + fTexture.allocPixels(); + fTexture.lockPixels(); + SkPMColor* addr = fTexture.getAddr32(0, 0); + + for (int y = 0; y < ySize; ++y) { + for (int x = 0; x < xSize; ++x) { + addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorBLACK); + + if ((y % 5) == 0) { + addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorRED); + } + if ((x % 7) == 0) { + addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorGREEN); + } + } + } + + fTexture.unlockPixels(); + + fTextureCreated = true; + } + + void createShader() { + if (NULL != fShader.get()) { + return; + } + + createTexture(); + + fShader.reset(SkShader::CreateBitmapShader(fTexture, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode)); + } + + void createMaskFilter() { + if (NULL != fMaskFilter.get()) { + return; + } + + fMaskFilter.reset(SkNEW(SkStippleMaskFilter)); + } + + virtual void onDraw(SkCanvas* canvas) { + + createShader(); + createMaskFilter(); + + canvas->save(); + + // draw a letter "M" with a green & red striped texture and a + // stipple mask with a round rect soft clip + SkPaint paint; + paint.setAntiAlias(true); + paint.setTextSize(72); + paint.setShader(fShader.get()); + paint.setMaskFilter(fMaskFilter.get()); + + SkRect temp; + temp.set(SkIntToScalar(115), + SkIntToScalar(75), + SkIntToScalar(144), + SkIntToScalar(110)); + + SkPath path; + path.addRoundRect(temp, SkIntToScalar(5), SkIntToScalar(5)); + + canvas->clipPath(path, SkRegion::kReplace_Op, true); // AA is on + + canvas->drawText("M", 1, + SkIntToScalar(100), SkIntToScalar(100), + paint); + + canvas->restore(); + + // Now draw stroked versions of the "M" and the round rect so we can + // see what is going on + SkPaint paint2; + paint2.setColor(SK_ColorBLACK); + paint2.setAntiAlias(true); + paint2.setTextSize(72); + paint2.setStyle(SkPaint::kStroke_Style); + paint2.setStrokeWidth(1); + canvas->drawText("M", 1, + SkIntToScalar(100), SkIntToScalar(100), + paint2); + + paint2.setColor(SK_ColorGRAY); + + canvas->drawPath(path, paint2); + } + +private: + SkBitmap fTexture; + bool fTextureCreated; + SkAutoTUnref fShader; + SkAutoTUnref fMaskFilter; + + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new SamplerStressGM; } +static GMRegistry reg(MyFactory); + +} -- cgit v1.2.3