Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Unified Diff: src/gpu/gl/GrGpuGL.cpp

Issue 22686002: Implement path cover with nv_path_rendering (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Omission with non-inverted path bounds fixed Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/gpu/gl/GrGpuGL.cpp
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 4f4bb0f93f51c40af99e37a361f822e2267892cf..b4111950c1ab6276a744c7df69cfa3967efa534d 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -356,6 +356,10 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
fHWStencilTestEnabled = kUnknown_TriState;
}
+ if (resetBits & kPathRendering_GrGLBackendState && this->glCaps().pathRenderingSupport()) {
+ fHWPathStencilSettings.invalidate();
+ }
+
// Vertex
if (resetBits & kVertex_GrGLBackendState) {
fHWGeometryState.invalidate();
@@ -1270,7 +1274,7 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
}
GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) {
- SkASSERT(this->caps()->pathStencilingSupport());
+ SkASSERT(this->caps()->pathRenderingSupport());
return SkNEW_ARGS(GrGLPath, (this, inPath));
}
@@ -1680,62 +1684,93 @@ const GrStencilSettings& even_odd_nv_path_stencil_settings() {
kOnes16, kOnes16, kOnes16);
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
}
+GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
+ switch (op) {
+ default:
+ GrCrash("Unexpected path fill.");
+ /* fallthrough */;
+ case kIncClamp_StencilOp:
+ return GR_GL_COUNT_UP;
+ case kInvert_StencilOp:
+ return GR_GL_INVERT;
+ }
+}
}
-void GrGpuGL::setStencilPathSettings(const GrPath&,
- SkPath::FillType fill,
- GrStencilSettings* settings) {
+const GrStencilSettings& GrGpuGL::getPathStencilSettingsForFillType(SkPath::FillType fill) {
switch (fill) {
- case SkPath::kEvenOdd_FillType:
- *settings = even_odd_nv_path_stencil_settings();
- return;
- case SkPath::kWinding_FillType:
- *settings = winding_nv_path_stencil_settings();
- return;
default:
GrCrash("Unexpected path fill.");
+ /* fallthrough */;
+ case SkPath::kWinding_FillType:
+ case SkPath::kInverseWinding_FillType:
+ return winding_nv_path_stencil_settings();
+ case SkPath::kEvenOdd_FillType:
+ case SkPath::kInverseEvenOdd_FillType:
+ return even_odd_nv_path_stencil_settings();
}
}
void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) {
- SkASSERT(this->caps()->pathStencilingSupport());
+ SkASSERT(this->caps()->pathRenderingSupport());
GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
GrDrawState* drawState = this->drawState();
SkASSERT(NULL != drawState->getRenderTarget());
- if (NULL == drawState->getRenderTarget()->getStencilBuffer()) {
- return;
- }
+ SkASSERT(NULL != drawState->getRenderTarget()->getStencilBuffer());
// Decide how to manipulate the stencil buffer based on the fill rule.
- // Also, assert that the stencil settings we set in setStencilPathSettings
- // are present.
- SkASSERT(!fStencilSettings.isTwoSided());
- GrGLenum fillMode;
- switch (fill) {
- case SkPath::kWinding_FillType:
- fillMode = GR_GL_COUNT_UP;
- SkASSERT(kIncClamp_StencilOp ==
- fStencilSettings.passOp(GrStencilSettings::kFront_Face));
- SkASSERT(kIncClamp_StencilOp ==
- fStencilSettings.failOp(GrStencilSettings::kFront_Face));
- break;
- case SkPath::kEvenOdd_FillType:
- fillMode = GR_GL_INVERT;
- SkASSERT(kInvert_StencilOp ==
- fStencilSettings.passOp(GrStencilSettings::kFront_Face));
- SkASSERT(kInvert_StencilOp ==
- fStencilSettings.failOp(GrStencilSettings::kFront_Face));
- break;
- default:
- // Only the above two fill rules are allowed.
- GrCrash("Unexpected path fill.");
- return; // suppress unused var warning.
- }
- GrGLint writeMask = fStencilSettings.writeMask(GrStencilSettings::kFront_Face);
+ SkASSERT(!fPathStencilSettings.isTwoSided());
+
+ GrGLenum fillMode =
+ gr_stencil_op_to_gl_path_rendering_fill_mode(fPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
+ GrGLint writeMask = fPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
GL_CALL(StencilFillPath(id, fillMode, writeMask));
}
+void GrGpuGL::onGpuFillPath(const GrPath* path, SkPath::FillType fill) {
+ SkASSERT(this->caps()->pathRenderingSupport());
+
+ GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
+ GrDrawState* drawState = this->drawState();
+ SkASSERT(NULL != drawState->getRenderTarget());
+ SkASSERT(NULL != drawState->getRenderTarget()->getStencilBuffer());
+
+ SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill);
+ SkASSERT(!fPathStencilSettings.isTwoSided());
+ GrGLenum fillMode =
+ gr_stencil_op_to_gl_path_rendering_fill_mode(fPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
+ GrGLint writeMask = fPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
+ GL_CALL(StencilFillPath(id, fillMode, writeMask));
+
+ if (!fCurrentProgram->hasVertexShader() && nonInvertedFill == fill) {
+ GL_CALL(CoverFillPath(id, GR_GL_BOUNDING_BOX));
+ } else {
+ GrDrawState::AutoViewMatrixRestore avmr;
+ SkRect bounds;
+ if (nonInvertedFill == fill) {
+ bounds = path->getBounds();
+ } else {
+ 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().getMaxStretch() * SK_ScalarHalf;
+ bounds.outset(bloat, bloat);
+ } else {
+ avmr.setIdentity(drawState);
+ }
+ }
+
+ this->drawSimpleRect(bounds, NULL);
+ }
+}
+
void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
if (rt->needsResolve()) {
@@ -1857,16 +1892,21 @@ void set_gl_stencil(const GrGLInterface* gl,
}
void GrGpuGL::flushStencil(DrawType type) {
- if (kStencilPath_DrawType == type) {
- SkASSERT(!fStencilSettings.isTwoSided());
+ if ((kStencilPath_DrawType == type || kFillPath_DrawType == type) &&
+ fHWPathStencilSettings != fPathStencilSettings) {
+
// 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 =
- gr_to_gl_stencil_func(fStencilSettings.func(GrStencilSettings::kFront_Face));
+ gr_to_gl_stencil_func(fPathStencilSettings.func(GrStencilSettings::kFront_Face));
GL_CALL(PathStencilFunc(func,
- fStencilSettings.funcRef(GrStencilSettings::kFront_Face),
- fStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
- } else if (fHWStencilSettings != fStencilSettings) {
+ fPathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
+ fPathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
+
+ fHWPathStencilSettings = fPathStencilSettings;
+ }
+
+ if (kStencilPath_DrawType != type && fHWStencilSettings != fStencilSettings) {
if (fStencilSettings.isDisabled()) {
if (kNo_TriState != fHWStencilTestEnabled) {
GL_CALL(Disable(GR_GL_STENCIL_TEST));
« src/gpu/GrGpu.cpp ('K') | « src/gpu/gl/GrGpuGL.h ('k') | src/gpu/gl/GrGpuGL_program.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698