Beginning to refactor nvpr code

BUG=skia:

Review URL: https://codereview.chromium.org/687563008
This commit is contained in:
joshualitt 2014-10-31 13:56:50 -07:00 committed by Commit bot
parent 2faa228435
commit 92e496f96a
13 changed files with 232 additions and 223 deletions

View File

@ -47,3 +47,16 @@ dropshadowimagefilter
# senorblanco https://codereview.chromium.org/637283009/
# quality improvements to imagemagnifier GM
imagemagnifier
#joshualitt rebase tonight
rrect_clip_bw
multipicturedraw_rrectclip_tiled
multipicturedraw_rrectclip_simple
filltypespersp
convex_poly_clip
complexclip2_path_bw
complexclip2_rrect_bw
complexclip_bw_layer
complexclip_bw
circular-clips

View File

@ -527,28 +527,20 @@ void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
}
}
void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) {
void GrDrawTarget::stencilPath(const GrPath* path, GrPathRendering::FillType fill) {
// TODO: extract portions of checkDraw that are relevant to path stenciling.
SkASSERT(path);
SkASSERT(this->caps()->pathRenderingSupport());
SkASSERT(!SkPath::IsInverseFillType(fill));
this->onStencilPath(path, fill);
}
void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
void GrDrawTarget::drawPath(const GrPath* path, GrPathRendering::FillType fill) {
// TODO: extract portions of checkDraw that are relevant to path rendering.
SkASSERT(path);
SkASSERT(this->caps()->pathRenderingSupport());
const GrDrawState* drawState = &getDrawState();
SkRect devBounds;
if (SkPath::IsInverseFillType(fill)) {
devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()),
SkIntToScalar(drawState->getRenderTarget()->height()));
} else {
devBounds = path->getBounds();
}
SkMatrix viewM = drawState->getViewMatrix();
SkRect devBounds = path->getBounds();
SkMatrix viewM = this->drawState()->getViewMatrix();
viewM.mapRect(&devBounds);
GrDeviceCoordTexture dstCopy;
@ -562,7 +554,7 @@ void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
void GrDrawTarget::drawPaths(const GrPathRange* pathRange,
const uint32_t indices[], int count,
const float transforms[], PathTransformType transformsType,
SkPath::FillType fill) {
GrPathRendering::FillType fill) {
SkASSERT(this->caps()->pathRenderingSupport());
SkASSERT(pathRange);
SkASSERT(indices);
@ -724,43 +716,6 @@ void GrDrawTarget::onDrawRect(const SkRect& rect,
void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
}
static const GrStencilSettings& winding_path_stencil_settings() {
GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
kIncClamp_StencilOp,
kIncClamp_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xFFFF, 0xFFFF, 0xFFFF);
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
}
static const GrStencilSettings& even_odd_path_stencil_settings() {
GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
kInvert_StencilOp,
kInvert_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xFFFF, 0xFFFF, 0xFFFF);
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
}
void GrDrawTarget::getPathStencilSettingsForFillType(SkPath::FillType fill,
GrStencilSettings* outStencilSettings) {
switch (fill) {
default:
SkFAIL("Unexpected path fill.");
/* fallthrough */;
case SkPath::kWinding_FillType:
case SkPath::kInverseWinding_FillType:
*outStencilSettings = winding_path_stencil_settings();
break;
case SkPath::kEvenOdd_FillType:
case SkPath::kInverseEvenOdd_FillType:
*outStencilSettings = even_odd_path_stencil_settings();
break;
}
this->getClipMaskManager()->adjustPathStencilParams(outStencilSettings);
}
////////////////////////////////////////////////////////////////////////////////
GrDrawTarget::AutoStateRestore::AutoStateRestore() {

View File

@ -315,15 +315,16 @@ public:
/**
* Draws path into the stencil buffer. The fill must be either even/odd or
* winding (not inverse or hairline). It will respect the HW antialias flag
* on the draw state (if possible in the 3D API).
* on the draw state (if possible in the 3D API). Note, we will never have an inverse fill
* with stencil path
*/
void stencilPath(const GrPath*, SkPath::FillType fill);
void stencilPath(const GrPath*, GrPathRendering::FillType fill);
/**
* Draws a path. Fill must not be a hairline. It will respect the HW
* antialias flag on the draw state (if possible in the 3D API).
*/
void drawPath(const GrPath*, SkPath::FillType fill);
void drawPath(const GrPath*, GrPathRendering::FillType fill);
/**
* Draws many paths. It will respect the HW
@ -340,7 +341,7 @@ public:
void drawPaths(const GrPathRange* pathRange,
const uint32_t indices[], int count,
const float transforms[], PathTransformType transformsType,
SkPath::FillType fill);
GrPathRendering::FillType fill);
/**
* Helper function for drawing rects. It performs a geometry src push and pop
@ -490,7 +491,7 @@ public:
/**
* For subclass internal use to invoke a call to onDrawPath().
*/
void executeDrawPath(const GrPath* path, SkPath::FillType fill,
void executeDrawPath(const GrPath* path, GrPathRendering::FillType fill,
const GrDeviceCoordTexture* dstCopy) {
this->onDrawPath(path, fill, dstCopy);
}
@ -501,13 +502,11 @@ public:
void executeDrawPaths(const GrPathRange* pathRange,
const uint32_t indices[], int count,
const float transforms[], PathTransformType transformsType,
SkPath::FillType fill,
GrPathRendering::FillType fill,
const GrDeviceCoordTexture* dstCopy) {
this->onDrawPaths(pathRange, indices, count, transforms, transformsType, fill, dstCopy);
}
void getPathStencilSettingsForFillType(SkPath::FillType, GrStencilSettings*);
////////////////////////////////////////////////////////////////////////////
/**
@ -898,13 +897,13 @@ private:
const SkRect* localRect,
const SkMatrix* localMatrix);
virtual void onStencilPath(const GrPath*, SkPath::FillType) = 0;
virtual void onDrawPath(const GrPath*, SkPath::FillType,
virtual void onStencilPath(const GrPath*, GrPathRendering::FillType) = 0;
virtual void onDrawPath(const GrPath*, GrPathRendering::FillType,
const GrDeviceCoordTexture* dstCopy) = 0;
virtual void onDrawPaths(const GrPathRange*,
const uint32_t indices[], int count,
const float transforms[], PathTransformType,
SkPath::FillType, const GrDeviceCoordTexture*) = 0;
GrPathRendering::FillType, const GrDeviceCoordTexture*) = 0;
virtual void didAddGpuTraceMarker() = 0;
virtual void didRemoveGpuTraceMarker() = 0;

View File

@ -275,13 +275,13 @@ const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
bool GrGpu::setupClipAndFlushState(DrawType type,
const GrDeviceCoordTexture* dstCopy,
const SkRect* devBounds,
GrDrawState::AutoRestoreEffects* are) {
GrDrawState::AutoRestoreEffects* are,
GrDrawState::AutoRestoreStencil* ars) {
GrClipMaskManager::ScissorState scissorState;
GrDrawState::AutoRestoreStencil ars;
if (!fClipMaskManager.setupClipping(this->getClip(),
devBounds,
are,
&ars,
ars,
&scissorState)) {
return false;
}
@ -325,56 +325,109 @@ void GrGpu::geometrySourceWillPop(const GeometrySrcState& restoredState) {
void GrGpu::onDraw(const DrawInfo& info) {
this->handleDirtyContext();
GrDrawState::AutoRestoreEffects are;
GrDrawState::AutoRestoreStencil ars;
if (!this->setupClipAndFlushState(PrimTypeToDrawType(info.primitiveType()),
info.getDstCopy(),
info.getDevBounds(),
&are)) {
&are,
&ars)) {
return;
}
this->onGpuDraw(info);
}
void GrGpu::onStencilPath(const GrPath* path, SkPath::FillType fill) {
// TODO hack
static const GrStencilSettings& winding_path_stencil_settings() {
GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
kIncClamp_StencilOp,
kIncClamp_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xFFFF, 0xFFFF, 0xFFFF);
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
}
static const GrStencilSettings& even_odd_path_stencil_settings() {
GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
kInvert_StencilOp,
kInvert_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xFFFF, 0xFFFF, 0xFFFF);
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
}
static void get_path_stencil_settings_for_filltype(GrPathRendering::FillType fill,
GrStencilSettings* outStencilSettings) {
switch (fill) {
default:
SkFAIL("Unexpected path fill.");
case GrPathRendering::kWinding_FillType:
*outStencilSettings = winding_path_stencil_settings();
break;
case GrPathRendering::kEvenOdd_FillType:
*outStencilSettings = even_odd_path_stencil_settings();
break;
}
}
void GrGpu::onStencilPath(const GrPath* path, GrPathRendering::FillType fill) {
this->handleDirtyContext();
GrDrawState::AutoRestoreEffects are;
if (!this->setupClipAndFlushState(kStencilPath_DrawType, NULL, NULL, &are)) {
GrDrawState::AutoRestoreStencil ars;
if (!this->setupClipAndFlushState(kStencilPath_DrawType, NULL, NULL, &are, &ars)) {
return;
}
this->pathRendering()->stencilPath(path, fill);
GrStencilSettings stencilSettings;
get_path_stencil_settings_for_filltype(fill, &stencilSettings);
fClipMaskManager.adjustPathStencilParams(&stencilSettings);
this->pathRendering()->stencilPath(path, stencilSettings);
}
void GrGpu::onDrawPath(const GrPath* path, SkPath::FillType fill,
void GrGpu::onDrawPath(const GrPath* path, GrPathRendering::FillType fill,
const GrDeviceCoordTexture* dstCopy) {
this->handleDirtyContext();
drawState()->setDefaultVertexAttribs();
GrDrawState::AutoRestoreEffects are;
if (!this->setupClipAndFlushState(kDrawPath_DrawType, dstCopy, NULL, &are)) {
GrDrawState::AutoRestoreStencil ars;
if (!this->setupClipAndFlushState(kDrawPath_DrawType, dstCopy, NULL, &are, &ars)) {
return;
}
this->pathRendering()->drawPath(path, fill);
GrStencilSettings stencilSettings;
get_path_stencil_settings_for_filltype(fill, &stencilSettings);
fClipMaskManager.adjustPathStencilParams(&stencilSettings);
this->pathRendering()->drawPath(path, stencilSettings);
}
void GrGpu::onDrawPaths(const GrPathRange* pathRange,
const uint32_t indices[], int count,
const float transforms[], PathTransformType transformsType,
SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
GrPathRendering::FillType fill, const GrDeviceCoordTexture* dstCopy) {
this->handleDirtyContext();
drawState()->setDefaultVertexAttribs();
GrDrawState::AutoRestoreEffects are;
if (!this->setupClipAndFlushState(kDrawPaths_DrawType, dstCopy, NULL, &are)) {
GrDrawState::AutoRestoreStencil ars;
if (!this->setupClipAndFlushState(kDrawPaths_DrawType, dstCopy, NULL, &are, &ars)) {
return;
}
GrStencilSettings stencilSettings;
get_path_stencil_settings_for_filltype(fill, &stencilSettings);
fClipMaskManager.adjustPathStencilParams(&stencilSettings);
pathRange->willDrawPaths(indices, count);
this->pathRendering()->drawPaths(pathRange, indices, count, transforms, transformsType, fill);
this->pathRendering()->drawPaths(pathRange, indices, count, transforms, transformsType,
stencilSettings);
}
void GrGpu::finalizeReservedVertices() {

View File

@ -335,7 +335,8 @@ protected:
bool setupClipAndFlushState(DrawType,
const GrDeviceCoordTexture* dstCopy,
const SkRect* devBounds,
GrDrawState::AutoRestoreEffects*);
GrDrawState::AutoRestoreEffects*,
GrDrawState::AutoRestoreStencil*);
// Functions used to map clip-respecting stencil tests into normal
// stencil funcs supported by GPUs.
@ -452,13 +453,13 @@ private:
// GrDrawTarget overrides
virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
virtual void onStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
virtual void onDrawPath(const GrPath*, SkPath::FillType,
virtual void onStencilPath(const GrPath*, GrPathRendering::FillType) SK_OVERRIDE;
virtual void onDrawPath(const GrPath*, GrPathRendering::FillType,
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
virtual void onDrawPaths(const GrPathRange*,
const uint32_t indices[], int count,
const float transforms[], PathTransformType,
SkPath::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
GrPathRendering::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
// readies the pools to provide vertex/index data.
void prepareVertexPool();

View File

@ -361,7 +361,7 @@ void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
}
}
void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, SkPath::FillType fill) {
void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, GrPathRendering::FillType fill) {
this->recordClipIfNecessary();
// Only compare the subset of GrDrawState relevant to path stenciling?
this->recordStateIfNecessary();
@ -371,7 +371,8 @@ void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, SkPath::FillType fil
}
void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
GrPathRendering::FillType fill,
const GrDeviceCoordTexture* dstCopy) {
this->recordClipIfNecessary();
// TODO: Only compare the subset of GrDrawState relevant to path covering?
this->recordStateIfNecessary();
@ -386,7 +387,8 @@ void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
const uint32_t indices[], int count,
const float transforms[], PathTransformType transformsType,
SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
GrPathRendering::FillType fill,
const GrDeviceCoordTexture* dstCopy) {
SkASSERT(pathRange);
SkASSERT(indices);
SkASSERT(transforms);

View File

@ -139,7 +139,7 @@ private:
virtual void execute(GrClipTarget*);
SkPath::FillType fFill;
GrPathRendering::FillType fFill;
private:
GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
@ -152,8 +152,8 @@ private:
virtual void execute(GrClipTarget*);
SkPath::FillType fFill;
GrDeviceCoordTexture fDstCopy;
GrPathRendering::FillType fFill;
GrDeviceCoordTexture fDstCopy;
private:
GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
@ -168,10 +168,10 @@ private:
virtual void execute(GrClipTarget*);
size_t fCount;
PathTransformType fTransformsType;
SkPath::FillType fFill;
GrDeviceCoordTexture fDstCopy;
size_t fCount;
PathTransformType fTransformsType;
GrPathRendering::FillType fFill;
GrDeviceCoordTexture fDstCopy;
private:
GrPendingIOResource<const GrPathRange, kRead_GrIOType> fPathRange;
@ -257,13 +257,13 @@ private:
const SkRect* localRect,
const SkMatrix* localMatrix) SK_OVERRIDE;
virtual void onStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
virtual void onDrawPath(const GrPath*, SkPath::FillType,
virtual void onStencilPath(const GrPath*, GrPathRendering::FillType) SK_OVERRIDE;
virtual void onDrawPath(const GrPath*, GrPathRendering::FillType,
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
virtual void onDrawPaths(const GrPathRange*,
const uint32_t indices[], int count,
const float transforms[], PathTransformType,
SkPath::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
GrPathRendering::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
virtual bool onReserveVertexSpace(size_t vertexSize,
int vertexCount,

View File

@ -16,6 +16,7 @@ class SkDescriptor;
class SkTypeface;
class GrPath;
class GrGpu;
class GrStencilSettings;
/**
* Abstract class wrapping HW path rendering API.
@ -33,6 +34,18 @@ class GrPathRendering {
public:
virtual ~GrPathRendering() { }
// No native support for inverse at this time
enum FillType {
/** Specifies that "inside" is computed by a non-zero sum of signed
edge crossings
*/
kWinding_FillType,
/** Specifies that "inside" is computed by an odd number of edge
crossings
*/
kEvenOdd_FillType,
};
enum PathTransformType {
kNone_PathTransformType, //!< []
kTranslateX_PathTransformType, //!< [kMTransX]
@ -111,10 +124,11 @@ public:
*/
virtual GrPathRange* createGlyphs(const SkTypeface*, const SkDescriptor*, const SkStrokeRec&) = 0;
virtual void stencilPath(const GrPath*, SkPath::FillType) = 0;
virtual void drawPath(const GrPath*, SkPath::FillType) = 0;
virtual void stencilPath(const GrPath*, const GrStencilSettings&) = 0;
virtual void drawPath(const GrPath*, const GrStencilSettings&) = 0;
virtual void drawPaths(const GrPathRange*, const uint32_t indices[], int count,
const float transforms[], PathTransformType, SkPath::FillType) = 0;
const float transforms[], PathTransformType,
const GrStencilSettings&) = 0;
protected:
GrPathRendering() { }

View File

@ -14,6 +14,22 @@
#include "GrPath.h"
#include "SkStrokeRec.h"
/*
* For now paths only natively support winding and even odd fill types
*/
static GrPathRendering::FillType convert_skpath_filltype(SkPath::FillType fill) {
switch (fill) {
default:
SkFAIL("Incomplete Switch\n");
case SkPath::kWinding_FillType:
case SkPath::kInverseWinding_FillType:
return GrPathRendering::kWinding_FillType;
case SkPath::kEvenOdd_FillType:
case SkPath::kInverseEvenOdd_FillType:
return GrPathRendering::kEvenOdd_FillType;
}
}
GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
SkASSERT(context);
SkASSERT(context->getGpu());
@ -44,10 +60,10 @@ bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path,
target->getDrawState().getStencil().isDisabled();
}
GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport(
const SkPath&,
const SkStrokeRec& ,
const GrDrawTarget*) const {
GrPathRenderer::StencilSupport
GrStencilAndCoverPathRenderer::onGetStencilSupport(const SkPath&,
const SkStrokeRec& ,
const GrDrawTarget*) const {
return GrPathRenderer::kStencilOnly_StencilSupport;
}
@ -67,7 +83,7 @@ void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path,
GrDrawTarget* target) {
SkASSERT(!path.isInverseFillType());
SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
target->stencilPath(p, path.getFillType());
target->stencilPath(p, convert_skpath_filltype(path.getFillType()));
}
bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
@ -94,7 +110,27 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
0x0000,
0xffff);
*drawState->stencil() = kInvertedStencilPass;
drawState->setStencil(kInvertedStencilPass);
// fake inverse with a stencil and cover
target->stencilPath(p, convert_skpath_filltype(path.getFillType()));
GrDrawState::AutoViewMatrixRestore avmr;
SkRect bounds = SkRect::MakeLTRB(0, 0,
SkIntToScalar(drawState->getRenderTarget()->width()),
SkIntToScalar(drawState->getRenderTarget()->height()));
SkMatrix vmi;
// mapRect through persp matrix may not be correct
if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
bounds.outset(bloat, bloat);
} else {
avmr.setIdentity(drawState);
}
target->drawSimpleRect(bounds);
} else {
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
kZero_StencilOp,
@ -104,11 +140,10 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
0x0000,
0xffff);
*drawState->stencil() = kStencilPass;
drawState->setStencil(kStencilPass);
target->drawPath(p, convert_skpath_filltype(path.getFillType()));
}
target->drawPath(p, path.getFillType());
target->drawState()->stencil()->setDisabled();
return true;
}

View File

@ -413,7 +413,7 @@ void GrStencilAndCoverTextContext::flush() {
}
fDrawTarget->drawPaths(fGlyphs, fIndexBuffer, fPendingGlyphCount,
fTransformBuffer, fTransformType, SkPath::kWinding_FillType);
fTransformBuffer, fTransformType, GrPathRendering::kWinding_FillType);
fPendingGlyphCount = 0;
}

View File

@ -152,147 +152,88 @@ GrPathRange* GrGLPathRendering::createGlyphs(const SkTypeface* typeface,
return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize, stroke));
}
void GrGLPathRendering::stencilPath(const GrPath* path, SkPath::FillType fill) {
void GrGLPathRendering::stencilPath(const GrPath* path, const GrStencilSettings& stencilSettings) {
GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
SkASSERT(fGpu->drawState()->getRenderTarget());
SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
this->flushPathStencilSettings(fill);
SkASSERT(!fHWPathStencilSettings.isTwoSided());
GrGLenum fillMode =
gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
GL_CALL(StencilFillPath(id, fillMode, writeMask));
}
void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) {
GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
SkASSERT(fGpu->drawState()->getRenderTarget());
SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
this->flushPathStencilSettings(fill);
this->flushPathStencilSettings(stencilSettings);
SkASSERT(!fHWPathStencilSettings.isTwoSided());
const SkStrokeRec& stroke = path->getStroke();
SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill);
GrGLenum fillMode =
gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
GL_CALL(StencilFillPath(id, fillMode, writeMask));
}
if (stroke.needToApply()) {
GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
}
}
void GrGLPathRendering::drawPath(const GrPath* path, const GrStencilSettings& stencilSettings) {
GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
SkASSERT(fGpu->drawState()->getRenderTarget());
SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
this->flushPathStencilSettings(stencilSettings);
SkASSERT(!fHWPathStencilSettings.isTwoSided());
const SkStrokeRec& stroke = path->getStroke();
GrGLenum fillMode =
gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
if (nonInvertedFill == fill) {
if (stroke.needToApply()) {
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
GL_CALL(StencilFillPath(id, fillMode, writeMask));
}
this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
} else {
this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
}
} else {
if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
if (stroke.needToApply()) {
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
GL_CALL(StencilFillPath(id, fillMode, writeMask));
}
if (stroke.needToApply()) {
GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
}
GrDrawState* drawState = fGpu->drawState();
GrDrawState::AutoViewMatrixRestore avmr;
SkRect bounds = SkRect::MakeLTRB(0, 0,
SkIntToScalar(drawState->getRenderTarget()->width()),
SkIntToScalar(drawState->getRenderTarget()->height()));
SkMatrix vmi;
// mapRect through persp matrix may not be correct
if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
bounds.outset(bloat, bloat);
} else {
avmr.setIdentity(drawState);
}
fGpu->drawSimpleRect(bounds);
this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
} else {
this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
}
}
void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t indices[], int count,
const float transforms[], PathTransformType transformsType,
SkPath::FillType fill) {
const GrStencilSettings& stencilSettings) {
SkASSERT(fGpu->caps()->pathRenderingSupport());
SkASSERT(fGpu->drawState()->getRenderTarget());
SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
this->flushPathStencilSettings(fill);
this->flushPathStencilSettings(stencilSettings);
SkASSERT(!fHWPathStencilSettings.isTwoSided());
const SkStrokeRec& stroke = pathRange->getStroke();
SkPath::FillType nonInvertedFill =
SkPath::ConvertToNonInverseFillType(fill);
GrGLenum fillMode =
gr_stencil_op_to_gl_path_rendering_fill_mode(
fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
GrGLint writeMask =
fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
if (nonInvertedFill == fill) {
if (stroke.needToApply()) {
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
GL_CALL(StencilFillPathInstanced(
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
writeMask, gXformType2GLType[transformsType],
transforms));
}
this->stencilThenCoverStrokePathInstanced(
count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
gXformType2GLType[transformsType], transforms);
} else {
this->stencilThenCoverFillPathInstanced(
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
gXformType2GLType[transformsType], transforms);
}
} else {
if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
if (stroke.needToApply()) {
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
GL_CALL(StencilFillPathInstanced(
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
writeMask, gXformType2GLType[transformsType],
transforms));
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
writeMask, gXformType2GLType[transformsType],
transforms));
}
if (stroke.needToApply()) {
GL_CALL(StencilStrokePathInstanced(
count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
writeMask, gXformType2GLType[transformsType],
transforms));
}
GrDrawState* drawState = fGpu->drawState();
GrDrawState::AutoViewMatrixRestore avmr;
SkRect bounds = SkRect::MakeLTRB(0, 0,
SkIntToScalar(drawState->getRenderTarget()->width()),
SkIntToScalar(drawState->getRenderTarget()->height()));
SkMatrix vmi;
// mapRect through persp matrix may not be correct
if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
bounds.outset(bloat, bloat);
} else {
avmr.setIdentity(drawState);
}
fGpu->drawSimpleRect(bounds);
this->stencilThenCoverStrokePathInstanced(
count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
gXformType2GLType[transformsType], transforms);
} else {
this->stencilThenCoverFillPathInstanced(
count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
gXformType2GLType[transformsType], transforms);
}
}
@ -466,18 +407,16 @@ void GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
fPathNameAllocator->free(path);
}
void GrGLPathRendering::flushPathStencilSettings(SkPath::FillType fill) {
GrStencilSettings pathStencilSettings;
fGpu->getPathStencilSettingsForFillType(fill, &pathStencilSettings);
if (fHWPathStencilSettings != pathStencilSettings) {
void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stencilSettings) {
if (fHWPathStencilSettings != stencilSettings) {
// Just the func, ref, and mask is set here. The op and write mask are params to the call
// that draws the path to the SB (glStencilFillPath)
GrGLenum func =
GrToGLStencilFunc(pathStencilSettings.func(GrStencilSettings::kFront_Face));
GL_CALL(PathStencilFunc(func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
pathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
GrToGLStencilFunc(stencilSettings.func(GrStencilSettings::kFront_Face));
GL_CALL(PathStencilFunc(func, stencilSettings.funcRef(GrStencilSettings::kFront_Face),
stencilSettings.funcMask(GrStencilSettings::kFront_Face)));
fHWPathStencilSettings = pathStencilSettings;
fHWPathStencilSettings = stencilSettings;
}
}

View File

@ -39,11 +39,11 @@ public:
virtual GrPathRange* createGlyphs(const SkTypeface*,
const SkDescriptor*,
const SkStrokeRec&) SK_OVERRIDE;
virtual void stencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
virtual void drawPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
virtual void stencilPath(const GrPath*, const GrStencilSettings&) SK_OVERRIDE;
virtual void drawPath(const GrPath*, const GrStencilSettings&) SK_OVERRIDE;
virtual void drawPaths(const GrPathRange*, const uint32_t indices[], int count,
const float transforms[], PathTransformType,
SkPath::FillType) SK_OVERRIDE;
const GrStencilSettings&) SK_OVERRIDE;
/* Called when the 3D context state is unknown. */
void resetContext();
@ -107,7 +107,7 @@ private:
};
const Caps& caps() const { return fCaps; }
void flushPathStencilSettings(SkPath::FillType fill);
void flushPathStencilSettings(const GrStencilSettings&);
// NV_path_rendering v1.2
void stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,

View File

@ -1871,6 +1871,7 @@ void set_gl_stencil(const GrGLInterface* gl,
}
void GrGpuGL::flushStencil(const GrStencilSettings& stencilSettings, DrawType type) {
// TODO figure out why we need to flush stencil settings on path draws at all
if (kStencilPath_DrawType != type && fHWStencilSettings != stencilSettings) {
if (stencilSettings.isDisabled()) {
if (kNo_TriState != fHWStencilTestEnabled) {
@ -1917,10 +1918,7 @@ void GrGpuGL::flushAAState(const GrOptDrawState& optState, DrawType type) {
const GrRenderTarget* rt = optState.getRenderTarget();
if (kGL_GrGLStandard == this->glStandard()) {
if (RT_HAS_MSAA) {
// FIXME: GL_NV_pr doesn't seem to like MSAA disabled. The paths
// convex hulls of each segment appear to get filled.
bool enableMSAA = kStencilPath_DrawType == type ||
optState.isHWAntialiasState();
bool enableMSAA = optState.isHWAntialiasState();
if (enableMSAA) {
if (kYes_TriState != fMSAAEnabled) {
GL_CALL(Enable(GR_GL_MULTISAMPLE));