aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl/GrGpuGL.cpp
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-25 11:59:40 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-25 11:59:40 +0000
commit9b62aa156bcf1db6f11af9302bf8bb8ef2567142 (patch)
treedae7097b678bfcd382993b53ba9808ae9438aa57 /src/gpu/gl/GrGpuGL.cpp
parent5c260f41af0af0d6bbfa9268664ac361a5ddc1e0 (diff)
Make it possible to draw multiple paths at once to a draw target
Add interface to draw multiple paths in a single "command" to a draw target. Implement this interface in GrGpuGL with NVPR "instanced" calls. The instanced calls accept list of paths and list of transformations as their parameters. The transformations are at this moment expected to be 2d affine transformations, as the functions are called only for text rendering. This will be used when drawing fonts. Later it can be maybe be used in GrInOrderDrawBuffer to aggregate many draw calls into one instanced draw call, similar to drawing rects. R=jvanverth@google.com, bsalomon@google.com Author: kkinnunen@nvidia.com Review URL: https://codereview.chromium.org/209413006 git-svn-id: http://skia.googlecode.com/svn/trunk@13930 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/gl/GrGpuGL.cpp')
-rw-r--r--src/gpu/gl/GrGpuGL.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 5fb268863b..0aa072cd84 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1695,6 +1695,99 @@ void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) {
}
}
+void GrGpuGL::onGpuDrawPaths(size_t pathCount, const GrPath** paths,
+ const SkMatrix* transforms,
+ SkPath::FillType fill,
+ SkStrokeRec::Style stroke) {
+ SkASSERT(this->caps()->pathRenderingSupport());
+ SkASSERT(NULL != this->drawState()->getRenderTarget());
+ SkASSERT(NULL != this->drawState()->getRenderTarget()->getStencilBuffer());
+ SkASSERT(!fCurrentProgram->hasVertexShader());
+ SkASSERT(stroke != SkStrokeRec::kHairline_Style);
+
+ SkAutoMalloc pathData(pathCount * sizeof(GrGLuint));
+ SkAutoMalloc transformData(pathCount * sizeof(GrGLfloat) * 6);
+ GrGLfloat* transformValues =
+ reinterpret_cast<GrGLfloat*>(transformData.get());
+ GrGLuint* pathIDs = reinterpret_cast<GrGLuint*>(pathData.get());
+
+ for (size_t i = 0; i < pathCount; ++i) {
+ SkASSERT(transforms[i].asAffine(NULL));
+ const SkMatrix& m = transforms[i];
+ transformValues[i * 6] = m.getScaleX();
+ transformValues[i * 6 + 1] = m.getSkewY();
+ transformValues[i * 6 + 2] = m.getSkewX();
+ transformValues[i * 6 + 3] = m.getScaleY();
+ transformValues[i * 6 + 4] = m.getTranslateX();
+ transformValues[i * 6 + 5] = m.getTranslateY();
+ pathIDs[i] = static_cast<const GrGLPath*>(paths[i])->pathID();
+ }
+
+ 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);
+
+ bool doFill = stroke == SkStrokeRec::kFill_Style
+ || stroke == SkStrokeRec::kStrokeAndFill_Style;
+ bool doStroke = stroke == SkStrokeRec::kStroke_Style
+ || stroke == SkStrokeRec::kStrokeAndFill_Style;
+
+ if (doFill) {
+ GL_CALL(StencilFillPathInstanced(pathCount, GR_GL_UNSIGNED_INT,
+ pathIDs, 0,
+ fillMode, writeMask,
+ GR_GL_AFFINE_2D, transformValues));
+ }
+ if (doStroke) {
+ GL_CALL(StencilStrokePathInstanced(pathCount, GR_GL_UNSIGNED_INT,
+ pathIDs, 0,
+ 0xffff, writeMask,
+ GR_GL_AFFINE_2D, transformValues));
+ }
+
+ if (nonInvertedFill == fill) {
+ if (doStroke) {
+ GL_CALL(CoverStrokePathInstanced(
+ pathCount, GR_GL_UNSIGNED_INT, pathIDs, 0,
+ GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ GR_GL_AFFINE_2D, transformValues));
+ } else {
+ GL_CALL(CoverFillPathInstanced(
+ pathCount, GR_GL_UNSIGNED_INT, pathIDs, 0,
+ GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ GR_GL_AFFINE_2D, transformValues));
+
+ }
+ } 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) {
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
if (rt->needsResolve()) {