aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--expectations/gm/ignored-tests.txt13
-rw-r--r--src/gpu/GrDrawTarget.cpp55
-rw-r--r--src/gpu/GrDrawTarget.h21
-rw-r--r--src/gpu/GrGpu.cpp79
-rw-r--r--src/gpu/GrGpu.h9
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp8
-rw-r--r--src/gpu/GrInOrderDrawBuffer.h20
-rw-r--r--src/gpu/GrPathRendering.h20
-rw-r--r--src/gpu/GrStencilAndCoverPathRenderer.cpp53
-rw-r--r--src/gpu/GrStencilAndCoverTextContext.cpp2
-rw-r--r--src/gpu/gl/GrGLPathRendering.cpp141
-rw-r--r--src/gpu/gl/GrGLPathRendering.h8
-rw-r--r--src/gpu/gl/GrGpuGL.cpp6
13 files changed, 222 insertions, 213 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index 63d6a8490d..31d30d23d5 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -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
+
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 11abb57691..2f25272e31 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -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() {
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 7d8a03ce71..4545f74d25 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -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;
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 4b1c35ad4e..2f4f0a68c8 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -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() {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 7c90ee4702..0e2ec88b8c 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -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();
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index e7d0f8377d..61c3e0c21d 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -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);
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 7b9a926cf4..e6971a9e47 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -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,
diff --git a/src/gpu/GrPathRendering.h b/src/gpu/GrPathRendering.h
index 26cfa110ce..cd42206f43 100644
--- a/src/gpu/GrPathRendering.h
+++ b/src/gpu/GrPathRendering.h
@@ -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() { }
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index 5f55c1a214..6ed4b9e61c 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -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;
}
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index b53ff797fa..94a6c2e528 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -413,7 +413,7 @@ void GrStencilAndCoverTextContext::flush() {
}
fDrawTarget->drawPaths(fGlyphs, fIndexBuffer, fPendingGlyphCount,
- fTransformBuffer, fTransformType, SkPath::kWinding_FillType);
+ fTransformBuffer, fTransformType, GrPathRendering::kWinding_FillType);
fPendingGlyphCount = 0;
}
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
index 26584bc808..66b129e876 100644
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -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);
+ 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);
- GL_CALL(StencilFillPath(id, fillMode, writeMask));
+
+ 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, SkPath::FillType fill) {
+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(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 (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;
}
}
diff --git a/src/gpu/gl/GrGLPathRendering.h b/src/gpu/gl/GrGLPathRendering.h
index 5133506a42..f314563688 100644
--- a/src/gpu/gl/GrGLPathRendering.h
+++ b/src/gpu/gl/GrGLPathRendering.h
@@ -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,
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index a00333ddab..9d08f641eb 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -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));