aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-10-09 14:11:33 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-10-09 14:11:33 +0000
commitc4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854 (patch)
tree305c63cae824c4d5ae904a7c19c9785f601a7b72 /src/gpu/gl
parent6ec1abf21e752abcca33ce3f95e31bc9ac9bb9eb (diff)
Implement filling a path with nv_path_rendering cover
Implement filling a path with nv_path_rendering cover functionality. The nv_path_rendering cover can be used if the fill is non-inverted and the draw operation does not require use of vertex shaders. Moves code for the inverted fill from GrStencilAndCoverPathRenderer down to GrGpuGL. R=bsalomon@google.com, markkilgard@gmail.com, cdalton@nvidia.com Author: kkinnunen@nvidia.com Review URL: https://codereview.chromium.org/22686002 git-svn-id: http://skia.googlecode.com/svn/trunk@11667 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/gl')
-rw-r--r--src/gpu/gl/GrGLCaps.cpp4
-rw-r--r--src/gpu/gl/GrGLProgram.cpp2
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp6
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp2
-rw-r--r--src/gpu/gl/GrGpuGL.cpp191
-rw-r--r--src/gpu/gl/GrGpuGL.h7
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp3
7 files changed, 113 insertions, 102 deletions
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index aac97361f8..17a4743b67 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -302,8 +302,8 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
// attachment, hence this min:
fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
- fPathStencilingSupport = GR_GL_USE_NV_PATH_RENDERING &&
- ctxInfo.hasExtension("GL_NV_path_rendering");
+ fPathRenderingSupport = GR_GL_USE_NV_PATH_RENDERING &&
+ ctxInfo.hasExtension("GL_NV_path_rendering");
fDstReadInShaderSupport = kNone_FBFetchType != fFBFetchType;
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 1ca61e3748..a69333f437 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -52,7 +52,7 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
if (fDesc.getHeader().fHasVertexCode ||
!fGpu->glCaps().fixedFunctionSupport() ||
- !fGpu->glCaps().pathStencilingSupport()) {
+ !fGpu->glCaps().pathRenderingSupport()) {
GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 8b731fbc2c..f9728ff556 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -122,11 +122,13 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fExperimentalGS = false;
#endif
#endif
+ bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport();
+
if (colorIsTransBlack) {
header->fColorInput = kTransBlack_ColorInput;
} else if (colorIsSolidWhite) {
header->fColorInput = kSolidWhite_ColorInput;
- } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
+ } else if (defaultToUniformInputs && !requiresColorAttrib) {
header->fColorInput = kUniform_ColorInput;
} else {
header->fColorInput = kAttribute_ColorInput;
@@ -139,7 +141,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fCoverageInput = kTransBlack_ColorInput;
} else if (covIsSolidWhite) {
header->fCoverageInput = kSolidWhite_ColorInput;
- } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
+ } else if (defaultToUniformInputs && !requiresCoverageAttrib) {
header->fCoverageInput = kUniform_ColorInput;
} else {
header->fCoverageInput = kAttribute_ColorInput;
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 00fefe1305..eb7cfa72f4 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -930,7 +930,7 @@ GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu,
SkASSERT(!desc.getHeader().fHasVertexCode);
SkASSERT(gpu->glCaps().fixedFunctionSupport());
- SkASSERT(gpu->glCaps().pathStencilingSupport());
+ SkASSERT(gpu->glCaps().pathRenderingSupport());
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
}
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 18165d9ca3..113866759e 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -365,26 +365,30 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
fHWBoundRenderTarget = NULL;
}
- if (resetBits & kFixedFunction_GrGLBackendState && this->glCaps().fixedFunctionSupport()) {
-
- fHWProjectionMatrixState.invalidate();
- // we don't use the model view matrix.
- GL_CALL(MatrixMode(GR_GL_MODELVIEW));
- GL_CALL(LoadIdentity());
-
- for (int i = 0; i < this->glCaps().maxFixedFunctionTextureCoords(); ++i) {
- GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + i));
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_S));
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_T));
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_Q));
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_R));
- if (this->caps()->pathStencilingSupport()) {
- GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ if (resetBits & (kFixedFunction_GrGLBackendState | kPathRendering_GrGLBackendState)) {
+ if (this->glCaps().fixedFunctionSupport()) {
+ fHWProjectionMatrixState.invalidate();
+ // we don't use the model view matrix.
+ GL_CALL(MatrixMode(GR_GL_MODELVIEW));
+ GL_CALL(LoadIdentity());
+
+ for (int i = 0; i < this->glCaps().maxFixedFunctionTextureCoords(); ++i) {
+ GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + i));
+ GL_CALL(Disable(GR_GL_TEXTURE_GEN_S));
+ GL_CALL(Disable(GR_GL_TEXTURE_GEN_T));
+ GL_CALL(Disable(GR_GL_TEXTURE_GEN_Q));
+ GL_CALL(Disable(GR_GL_TEXTURE_GEN_R));
+ if (this->caps()->pathRenderingSupport()) {
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ }
+ fHWTexGenSettings[i].fMode = GR_GL_NONE;
+ fHWTexGenSettings[i].fNumComponents = 0;
}
- fHWTexGenSettings[i].fMode = GR_GL_NONE;
- fHWTexGenSettings[i].fNumComponents = 0;
+ fHWActiveTexGenSets = 0;
+ }
+ if (this->caps()->pathRenderingSupport()) {
+ fHWPathStencilSettings.invalidate();
}
- fHWActiveTexGenSets = 0;
}
// we assume these values
@@ -1273,7 +1277,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));
}
@@ -1666,79 +1670,75 @@ void GrGpuGL::onGpuDraw(const DrawInfo& info) {
#endif
}
-namespace {
-
-static const uint16_t kOnes16 = static_cast<uint16_t>(~0);
-const GrStencilSettings& winding_nv_path_stencil_settings() {
- GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
- kIncClamp_StencilOp,
- kIncClamp_StencilOp,
- kAlwaysIfInClip_StencilFunc,
- kOnes16, kOnes16, kOnes16);
- return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
-}
-const GrStencilSettings& even_odd_nv_path_stencil_settings() {
- GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
- kInvert_StencilOp,
- kInvert_StencilOp,
- kAlwaysIfInClip_StencilFunc,
- kOnes16, kOnes16, kOnes16);
- return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
-}
-}
-
-void GrGpuGL::setStencilPathSettings(const GrPath&,
- SkPath::FillType fill,
- GrStencilSettings* settings) {
- 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;
+static 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::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 != this->drawState()->getRenderTarget());
+ SkASSERT(NULL != this->drawState()->getRenderTarget()->getStencilBuffer());
+
+ flushPathStencilSettings(fill);
// 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(!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 GrGpuGL::onGpuFillPath(const GrPath* path, SkPath::FillType fill) {
+ SkASSERT(this->caps()->pathRenderingSupport());
+
+ GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
+ SkASSERT(NULL != this->drawState()->getRenderTarget());
+ SkASSERT(NULL != this->drawState()->getRenderTarget()->getStencilBuffer());
+ SkASSERT(!fCurrentProgram->hasVertexShader());
+
+ flushPathStencilSettings(fill);
+
+ SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(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));
+
+ if (nonInvertedFill == fill) {
+ GL_CALL(CoverFillPath(id, GR_GL_BOUNDING_BOX));
+ } else {
+ GrDrawState* drawState = this->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().getMaxStretch() * SK_ScalarHalf;
+ bounds.outset(bloat, bloat);
+ } else {
+ avmr.setIdentity(drawState);
+ }
+
+ this->drawSimpleRect(bounds, NULL);
+ }
}
void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
@@ -1862,16 +1862,7 @@ void set_gl_stencil(const GrGLInterface* gl,
}
void GrGpuGL::flushStencil(DrawType type) {
- if (kStencilPath_DrawType == type) {
- SkASSERT(!fStencilSettings.isTwoSided());
- // 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));
- GL_CALL(PathStencilFunc(func,
- fStencilSettings.funcRef(GrStencilSettings::kFront_Face),
- fStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
- } else if (fHWStencilSettings != fStencilSettings) {
+ if (kStencilPath_DrawType != type && fHWStencilSettings != fStencilSettings) {
if (fStencilSettings.isDisabled()) {
if (kNo_TriState != fHWStencilTestEnabled) {
GL_CALL(Disable(GR_GL_STENCIL_TEST));
@@ -1961,6 +1952,22 @@ void GrGpuGL::flushAAState(DrawType type) {
}
}
+void GrGpuGL::flushPathStencilSettings(SkPath::FillType fill) {
+ GrStencilSettings pathStencilSettings;
+ this->getPathStencilSettingsForFillType(fill, &pathStencilSettings);
+ if (fHWPathStencilSettings != pathStencilSettings) {
+ // 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(pathStencilSettings.func(GrStencilSettings::kFront_Face));
+ GL_CALL(PathStencilFunc(func,
+ pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
+ pathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
+
+ fHWPathStencilSettings = pathStencilSettings;
+ }
+}
+
void GrGpuGL::flushBlend(bool isLines,
GrBlendCoeff srcCoeff,
GrBlendCoeff dstCoeff) {
@@ -2148,7 +2155,7 @@ void GrGpuGL::enableTexGen(int unitIdx,
const GrGLfloat* coefficients) {
SkASSERT(this->glCaps().fixedFunctionSupport());
- SkASSERT(this->caps()->pathStencilingSupport());
+ SkASSERT(this->caps()->pathRenderingSupport());
SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
if (GR_GL_OBJECT_LINEAR == fHWTexGenSettings[unitIdx].fMode &&
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index a59654a0f8..a945e54c99 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -151,11 +151,8 @@ private:
virtual void onGpuDraw(const DrawInfo&) SK_OVERRIDE;
- virtual void setStencilPathSettings(const GrPath&,
- SkPath::FillType,
- GrStencilSettings* settings)
- SK_OVERRIDE;
virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
+ virtual void onGpuFillPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
virtual void clearStencil() SK_OVERRIDE;
virtual void clearStencilClip(const SkIRect& rect,
@@ -245,6 +242,7 @@ private:
void flushRenderTarget(const SkIRect* bound);
void flushStencil(DrawType);
void flushAAState(DrawType);
+ void flushPathStencilSettings(SkPath::FillType fill);
bool configToGLFormats(GrPixelConfig config,
bool getSizedInternal,
@@ -434,6 +432,7 @@ private:
GrStencilSettings fHWStencilSettings;
TriState fHWStencilTestEnabled;
+ GrStencilSettings fHWPathStencilSettings;
GrDrawState::DrawFace fHWDrawFace;
TriState fHWWriteToColor;
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 92eed8d9bb..f3b566c209 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -252,6 +252,9 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
SkDEBUGFAIL("Failed to create program!");
return false;
}
+
+ SkASSERT(kFillPath_DrawType != type || !fCurrentProgram->hasVertexShader());
+
fCurrentProgram.get()->ref();
GrGLuint programID = fCurrentProgram->programID();