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
This commit is contained in:
robertphillips@google.com 2012-06-27 20:44:52 +00:00
parent eca2dfb002
commit 58b20215f6
6 changed files with 248 additions and 220 deletions

View File

@ -269,6 +269,8 @@
'../src/gpu/GrStringBuilder.h', '../src/gpu/GrStringBuilder.h',
'../src/gpu/GrTBSearch.h', '../src/gpu/GrTBSearch.h',
'../src/gpu/GrTDArray.h', '../src/gpu/GrTDArray.h',
'../src/gpu/GrSWMaskHelper.cpp',
'../src/gpu/GrSWMaskHelper.h',
'../src/gpu/GrSoftwarePathRenderer.cpp', '../src/gpu/GrSoftwarePathRenderer.cpp',
'../src/gpu/GrSoftwarePathRenderer.h', '../src/gpu/GrSoftwarePathRenderer.h',
'../src/gpu/GrSurface.cpp', '../src/gpu/GrSurface.cpp',

View File

@ -15,9 +15,7 @@
#include "SkRasterClip.h" #include "SkRasterClip.h"
#include "GrAAConvexPathRenderer.h" #include "GrAAConvexPathRenderer.h"
#include "GrAAHairLinePathRenderer.h" #include "GrAAHairLinePathRenderer.h"
#include "GrSWMaskHelper.h"
// TODO: move GrSWMaskHelper out of GrSoftwarePathRender.h & remove this include
#include "GrSoftwarePathRenderer.h"
//#define GR_AA_CLIP 1 //#define GR_AA_CLIP 1
//#define GR_SW_CLIP 1 //#define GR_SW_CLIP 1

181
src/gpu/GrSWMaskHelper.cpp Normal file
View File

@ -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());
}

63
src/gpu/GrSWMaskHelper.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrSWMaskHelper_DEFINED
#define GrSWMaskHelper_DEFINED
#include "GrColor.h"
#include "GrMatrix.h"
#include "GrNoncopyable.h"
#include "SkBitmap.h"
#include "SkDraw.h"
#include "SkRasterClip.h"
#include "SkRegion.h"
class GrAutoScratchTexture;
class GrContext;
class GrTexture;
class SkPath;
/**
* The GrSWMaskHelper helps generate clip masks using the software rendering
* path.
*/
class GrSWMaskHelper : public GrNoncopyable {
public:
GrSWMaskHelper(GrContext* context)
: fContext(context) {
}
void draw(const GrRect& clientRect, SkRegion::Op op,
bool antiAlias, GrColor color);
void draw(const SkPath& clientPath, SkRegion::Op op,
GrPathFill fill, bool antiAlias, GrColor color);
bool init(const GrIRect& pathDevBounds,
const GrPoint* translate,
bool useMatrix);
bool getTexture(GrAutoScratchTexture* tex);
void toTexture(GrTexture* texture, bool clearToWhite);
void clear(GrColor color) {
fBM.eraseColor(color);
}
protected:
private:
GrContext* fContext;
GrMatrix fMatrix;
SkBitmap fBM;
SkDraw fDraw;
SkRasterClip fRasterClip;
typedef GrNoncopyable INHERITED;
};
#endif GrSWMaskHelper_DEFINED

View File

@ -7,13 +7,8 @@
*/ */
#include "GrSoftwarePathRenderer.h" #include "GrSoftwarePathRenderer.h"
#include "GrPaint.h"
#include "SkPaint.h"
#include "GrRenderTarget.h"
#include "GrContext.h" #include "GrContext.h"
#include "SkDraw.h" #include "GrSWMaskHelper.h"
#include "SkRasterClip.h"
#include "GrGpu.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path, bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
@ -35,23 +30,6 @@ bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
namespace { namespace {
////////////////////////////////////////////////////////////////////////////////
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;
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// gets device coord bounds of path (not considering the fill) and clip. The // gets device coord bounds of path (not considering the fill) and clip. The
// path bounds will be a subset of the clip bounds. returns false if // path bounds will be a subset of the clip bounds. returns false if
@ -98,157 +76,6 @@ bool get_path_and_clip_bounds(const GrDrawTarget* target,
return true; return true;
} }
/*
* 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];
}
}
/**
* 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());
}
namespace {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/** /**
* sw rasterizes path to A8 mask using the context's matrix and uploads to a * sw rasterizes path to A8 mask using the context's matrix and uploads to a

View File

@ -11,52 +11,9 @@
#include "GrPathRenderer.h" #include "GrPathRenderer.h"
#include "SkDraw.h"
#include "SkRasterClip.h"
class GrContext; class GrContext;
class GrAutoScratchTexture; class GrAutoScratchTexture;
/**
* The GrSWMaskHelper helps generate clip masks using the software rendering
* path.
*/
class GrSWMaskHelper : public GrNoncopyable {
public:
GrSWMaskHelper(GrContext* context)
: fContext(context) {
}
void draw(const GrRect& clientRect, SkRegion::Op op,
bool antiAlias, GrColor color);
void draw(const SkPath& clientPath, SkRegion::Op op,
GrPathFill fill, bool antiAlias, GrColor color);
bool init(const GrIRect& pathDevBounds,
const GrPoint* translate,
bool useMatrix);
bool getTexture(GrAutoScratchTexture* tex);
void toTexture(GrTexture* texture, bool clearToWhite);
void clear(GrColor color) {
fBM.eraseColor(color);
}
protected:
private:
GrContext* fContext;
GrMatrix fMatrix;
SkBitmap fBM;
SkDraw fDraw;
SkRasterClip fRasterClip;
typedef GrPathRenderer INHERITED;
};
/** /**
* This class uses the software side to render a path to an SkBitmap and * This class uses the software side to render a path to an SkBitmap and
* then uploads the result to the gpu * then uploads the result to the gpu