From 58b20215f6d88b7e1cacae0b76226fced5109293 Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Wed, 27 Jun 2012 20:44:52 +0000 Subject: Split GrSWMaskHelper into its own files http://codereview.appspot.com/6350046/ git-svn-id: http://skia.googlecode.com/svn/trunk@4380 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrSWMaskHelper.cpp | 181 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/gpu/GrSWMaskHelper.cpp (limited to 'src/gpu/GrSWMaskHelper.cpp') diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp new file mode 100644 index 0000000000..f67336fe6c --- /dev/null +++ b/src/gpu/GrSWMaskHelper.cpp @@ -0,0 +1,181 @@ +/* + * 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 "GrSWMaskHelper.h" +#include "GrDrawState.h" +#include "GrGpu.h" + +// TODO: try to remove this #include +#include "GrContext.h" + +namespace { +/* + * Convert a boolean operation into a transfer mode code + */ +SkXfermode::Mode op_to_mode(SkRegion::Op op) { + + static const SkXfermode::Mode modeMap[] = { + SkXfermode::kDstOut_Mode, // kDifference_Op + SkXfermode::kMultiply_Mode, // kIntersect_Op + SkXfermode::kSrcOver_Mode, // kUnion_Op + SkXfermode::kXor_Mode, // kXOR_Op + SkXfermode::kClear_Mode, // kReverseDifference_Op + SkXfermode::kSrc_Mode, // kReplace_Op + }; + + return modeMap[op]; +} + +//////////////////////////////////////////////////////////////////////////////// +SkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) { + switch (fill) { + case kWinding_GrPathFill: + return SkPath::kWinding_FillType; + case kEvenOdd_GrPathFill: + return SkPath::kEvenOdd_FillType; + case kInverseWinding_GrPathFill: + return SkPath::kInverseWinding_FillType; + case kInverseEvenOdd_GrPathFill: + return SkPath::kInverseEvenOdd_FillType; + default: + GrCrash("Unexpected fill."); + return SkPath::kWinding_FillType; + } +} + +} + +/** + * Draw a single rect element of the clip stack into the accumulation bitmap + */ +void GrSWMaskHelper::draw(const GrRect& clientRect, SkRegion::Op op, + bool antiAlias, GrColor color) { + SkPaint paint; + + SkXfermode* mode = SkXfermode::Create(op_to_mode(op)); + + paint.setXfermode(mode); + paint.setAntiAlias(antiAlias); + paint.setColor(color); + + fDraw.drawRect(clientRect, paint); + + SkSafeUnref(mode); +} + +/** + * Draw a single path element of the clip stack into the accumulation bitmap + */ +void GrSWMaskHelper::draw(const SkPath& clientPath, SkRegion::Op op, + GrPathFill fill, bool antiAlias, GrColor color) { + + SkPaint paint; + SkPath tmpPath; + const SkPath* pathToDraw = &clientPath; + if (kHairLine_GrPathFill == fill) { + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(SK_Scalar1); + } else { + paint.setStyle(SkPaint::kFill_Style); + SkPath::FillType skfill = gr_fill_to_sk_fill(fill); + if (skfill != pathToDraw->getFillType()) { + tmpPath = *pathToDraw; + tmpPath.setFillType(skfill); + pathToDraw = &tmpPath; + } + } + SkXfermode* mode = SkXfermode::Create(op_to_mode(op)); + + paint.setXfermode(mode); + paint.setAntiAlias(antiAlias); + paint.setColor(color); + + fDraw.drawPath(*pathToDraw, paint); + + SkSafeUnref(mode); +} + +bool GrSWMaskHelper::init(const GrIRect& pathDevBounds, + const GrPoint* translate, + bool useMatrix) { + if (useMatrix) { + fMatrix = fContext->getMatrix(); + } else { + fMatrix.setIdentity(); + } + + if (NULL != translate) { + fMatrix.postTranslate(translate->fX, translate->fY); + } + + fMatrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1, + -pathDevBounds.fTop * SK_Scalar1); + GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(), + pathDevBounds.height()); + + fBM.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom); + if (!fBM.allocPixels()) { + return false; + } + sk_bzero(fBM.getPixels(), fBM.getSafeSize()); + + sk_bzero(&fDraw, sizeof(fDraw)); + fRasterClip.setRect(bounds); + fDraw.fRC = &fRasterClip; + fDraw.fClip = &fRasterClip.bwRgn(); + fDraw.fMatrix = &fMatrix; + fDraw.fBitmap = &fBM; + return true; +} + +/** + * Get a texture (from the texture cache) of the correct size & format + */ +bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* tex) { + GrTextureDesc desc; + desc.fWidth = fBM.width(); + desc.fHeight = fBM.height(); + desc.fConfig = kAlpha_8_GrPixelConfig; + + tex->set(fContext, desc); + GrTexture* texture = tex->texture(); + + if (NULL == texture) { + return false; + } + + return true; +} + +/** + * Move the result of the software mask generation back to the gpu + */ +void GrSWMaskHelper::toTexture(GrTexture *texture, bool clearToWhite) { + SkAutoLockPixels alp(fBM); + + // The destination texture is almost always larger than "fBM". Clear + // it appropriately so we don't get mask artifacts outside of the path's + // bounding box + + // "texture" needs to be installed as the render target for the clear + // and the texture upload but cannot remain the render target upon + // returned. Callers typically use it as a texture and it would then + // be both source and dest. + GrDrawState::AutoRenderTargetRestore artr(fContext->getGpu()->drawState(), + texture->asRenderTarget()); + + if (clearToWhite) { + fContext->getGpu()->clear(NULL, SK_ColorWHITE); + } else { + fContext->getGpu()->clear(NULL, 0x00000000); + } + + texture->writePixels(0, 0, fBM.width(), fBM.height(), + kAlpha_8_GrPixelConfig, + fBM.getPixels(), fBM.rowBytes()); +} + -- cgit v1.2.3