blob: 337e83e81172b3cc5b04a2aabb790741a95abd03 [file] [log] [blame]
cdaltonc7103a12014-08-11 14:05:05 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gl/GrGLPathRendering.h"
cdaltonc7103a12014-08-11 14:05:05 -07009#include "gl/GrGLNameAllocator.h"
10#include "gl/GrGLUtil.h"
kkinnunenccdaa042014-08-20 01:36:23 -070011#include "gl/GrGpuGL.h"
cdaltonc7103a12014-08-11 14:05:05 -070012
kkinnunenccdaa042014-08-20 01:36:23 -070013#include "GrGLPath.h"
14#include "GrGLPathRange.h"
15#include "GrGLPathRendering.h"
16
17#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
18#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(fGpu->glInterface(), RET, X)
19
20
21static const GrGLenum gXformType2GLType[] = {
22 GR_GL_NONE,
23 GR_GL_TRANSLATE_X,
24 GR_GL_TRANSLATE_Y,
25 GR_GL_TRANSLATE_2D,
26 GR_GL_TRANSPOSE_AFFINE_2D
27};
28
29GR_STATIC_ASSERT(0 == GrPathRendering::kNone_PathTransformType);
30GR_STATIC_ASSERT(1 == GrPathRendering::kTranslateX_PathTransformType);
31GR_STATIC_ASSERT(2 == GrPathRendering::kTranslateY_PathTransformType);
32GR_STATIC_ASSERT(3 == GrPathRendering::kTranslate_PathTransformType);
33GR_STATIC_ASSERT(4 == GrPathRendering::kAffine_PathTransformType);
34GR_STATIC_ASSERT(GrPathRendering::kAffine_PathTransformType == GrPathRendering::kLast_PathTransformType);
35
36static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
37 switch (op) {
38 default:
39 SkFAIL("Unexpected path fill.");
40 /* fallthrough */;
41 case kIncClamp_StencilOp:
42 return GR_GL_COUNT_UP;
43 case kInvert_StencilOp:
44 return GR_GL_INVERT;
45 }
46}
cdaltonc7103a12014-08-11 14:05:05 -070047
kkinnunenccdaa042014-08-20 01:36:23 -070048GrGLPathRendering::GrGLPathRendering(GrGpuGL* gpu)
49 : fGpu(gpu) {
kkinnunen5b653572014-08-20 04:13:27 -070050 const GrGLInterface* glInterface = gpu->glInterface();
51 fCaps.stencilThenCoverSupport =
52 NULL != glInterface->fFunctions.fStencilThenCoverFillPath &&
53 NULL != glInterface->fFunctions.fStencilThenCoverStrokePath &&
54 NULL != glInterface->fFunctions.fStencilThenCoverFillPathInstanced &&
55 NULL != glInterface->fFunctions.fStencilThenCoverStrokePathInstanced;
56 fCaps.fragmentInputGenSupport =
kkinnunenec56e452014-08-25 22:21:16 -070057 kGLES_GrGLStandard == glInterface->fStandard &&
kkinnunen5b653572014-08-20 04:13:27 -070058 NULL != glInterface->fFunctions.fProgramPathFragmentInputGen;
kkinnunenec56e452014-08-25 22:21:16 -070059
60 if (!fCaps.fragmentInputGenSupport) {
61 fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords());
62 }
cdaltonc7103a12014-08-11 14:05:05 -070063}
64
65GrGLPathRendering::~GrGLPathRendering() {
66}
67
68void GrGLPathRendering::abandonGpuResources() {
69 fPathNameAllocator.reset(NULL);
70}
71
kkinnunenccdaa042014-08-20 01:36:23 -070072void GrGLPathRendering::resetContext() {
73 fHWProjectionMatrixState.invalidate();
74 // we don't use the model view matrix.
kkinnunenec56e452014-08-25 22:21:16 -070075 GrGLenum matrixMode =
76 fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_MODELVIEW : GR_GL_MODELVIEW;
77 GL_CALL(MatrixLoadIdentity(matrixMode));
kkinnunenccdaa042014-08-20 01:36:23 -070078
kkinnunenec56e452014-08-25 22:21:16 -070079 if (!caps().fragmentInputGenSupport) {
80 for (int i = 0; i < fGpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
81 GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
82 fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
83 fHWPathTexGenSettings[i].fNumComponents = 0;
84 }
85 fHWActivePathTexGenSets = 0;
kkinnunenccdaa042014-08-20 01:36:23 -070086 }
kkinnunenccdaa042014-08-20 01:36:23 -070087 fHWPathStencilSettings.invalidate();
88}
89
90GrPath* GrGLPathRendering::createPath(const SkPath& inPath, const SkStrokeRec& stroke) {
91 return SkNEW_ARGS(GrGLPath, (fGpu, inPath, stroke));
92}
93
94GrPathRange* GrGLPathRendering::createPathRange(size_t size, const SkStrokeRec& stroke) {
95 return SkNEW_ARGS(GrGLPathRange, (fGpu, size, stroke));
96}
97
kkinnunen5b653572014-08-20 04:13:27 -070098void GrGLPathRendering::stencilPath(const GrPath* path, SkPath::FillType fill) {
99 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
100 SkASSERT(NULL != fGpu->drawState()->getRenderTarget());
101 SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer());
102
103 this->flushPathStencilSettings(fill);
104 SkASSERT(!fHWPathStencilSettings.isTwoSided());
105
106 GrGLenum fillMode =
107 gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
108 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
109 GL_CALL(StencilFillPath(id, fillMode, writeMask));
110}
111
112void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) {
113 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
114 SkASSERT(NULL != fGpu->drawState()->getRenderTarget());
115 SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer());
kkinnunen5b653572014-08-20 04:13:27 -0700116
117 this->flushPathStencilSettings(fill);
118 SkASSERT(!fHWPathStencilSettings.isTwoSided());
119
120 const SkStrokeRec& stroke = path->getStroke();
121
122 SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill);
123
124 GrGLenum fillMode =
125 gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
126 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
127
128 if (nonInvertedFill == fill) {
129 if (stroke.needToApply()) {
130 if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
131 GL_CALL(StencilFillPath(id, fillMode, writeMask));
132 }
133 this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
134 } else {
135 this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
136 }
137 } else {
138 if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
139 GL_CALL(StencilFillPath(id, fillMode, writeMask));
140 }
141 if (stroke.needToApply()) {
142 GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
143 }
144
145 GrDrawState* drawState = fGpu->drawState();
146 GrDrawState::AutoViewMatrixRestore avmr;
147 SkRect bounds = SkRect::MakeLTRB(0, 0,
148 SkIntToScalar(drawState->getRenderTarget()->width()),
149 SkIntToScalar(drawState->getRenderTarget()->height()));
150 SkMatrix vmi;
151 // mapRect through persp matrix may not be correct
152 if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
153 vmi.mapRect(&bounds);
154 // theoretically could set bloat = 0, instead leave it because of matrix inversion
155 // precision.
156 SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
157 bounds.outset(bloat, bloat);
158 } else {
159 avmr.setIdentity(drawState);
160 }
161
162 fGpu->drawSimpleRect(bounds);
163 }
164}
165
166void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t indices[], int count,
167 const float transforms[], PathTransformType transformsType,
168 SkPath::FillType fill) {
169 SkASSERT(fGpu->caps()->pathRenderingSupport());
170 SkASSERT(NULL != fGpu->drawState()->getRenderTarget());
171 SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer());
kkinnunen5b653572014-08-20 04:13:27 -0700172
173 GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
174
175 this->flushPathStencilSettings(fill);
176 SkASSERT(!fHWPathStencilSettings.isTwoSided());
177
178 const SkStrokeRec& stroke = pathRange->getStroke();
179
180 SkPath::FillType nonInvertedFill =
181 SkPath::ConvertToNonInverseFillType(fill);
182
183 GrGLenum fillMode =
184 gr_stencil_op_to_gl_path_rendering_fill_mode(
185 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
186 GrGLint writeMask =
187 fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
188
189 if (nonInvertedFill == fill) {
190 if (stroke.needToApply()) {
191 if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
192 GL_CALL(StencilFillPathInstanced(
193 count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
194 writeMask, gXformType2GLType[transformsType],
195 transforms));
196 }
197 this->stencilThenCoverStrokePathInstanced(
198 count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
199 GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
200 gXformType2GLType[transformsType], transforms);
201 } else {
202 this->stencilThenCoverFillPathInstanced(
203 count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
204 GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
205 gXformType2GLType[transformsType], transforms);
206 }
207 } else {
208 if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
209 GL_CALL(StencilFillPathInstanced(
210 count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
211 writeMask, gXformType2GLType[transformsType],
212 transforms));
213 }
214 if (stroke.needToApply()) {
215 GL_CALL(StencilStrokePathInstanced(
216 count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
217 writeMask, gXformType2GLType[transformsType],
218 transforms));
219 }
220
221 GrDrawState* drawState = fGpu->drawState();
222 GrDrawState::AutoViewMatrixRestore avmr;
223 SkRect bounds = SkRect::MakeLTRB(0, 0,
224 SkIntToScalar(drawState->getRenderTarget()->width()),
225 SkIntToScalar(drawState->getRenderTarget()->height()));
226 SkMatrix vmi;
227 // mapRect through persp matrix may not be correct
228 if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
229 vmi.mapRect(&bounds);
230 // theoretically could set bloat = 0, instead leave it because of matrix inversion
231 // precision.
232 SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
233 bounds.outset(bloat, bloat);
234 } else {
235 avmr.setIdentity(drawState);
236 }
237
238 fGpu->drawSimpleRect(bounds);
239 }
240}
241
kkinnunenccdaa042014-08-20 01:36:23 -0700242void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents components,
243 const GrGLfloat* coefficients) {
244 SkASSERT(components >= kS_PathTexGenComponents &&
245 components <= kSTR_PathTexGenComponents);
246 SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= unitIdx);
247
248 if (GR_GL_OBJECT_LINEAR == fHWPathTexGenSettings[unitIdx].fMode &&
249 components == fHWPathTexGenSettings[unitIdx].fNumComponents &&
250 !memcmp(coefficients, fHWPathTexGenSettings[unitIdx].fCoefficients,
251 3 * components * sizeof(GrGLfloat))) {
252 return;
253 }
254
255 fGpu->setTextureUnit(unitIdx);
256
257 fHWPathTexGenSettings[unitIdx].fNumComponents = components;
kkinnunen5b653572014-08-20 04:13:27 -0700258 GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx, GR_GL_OBJECT_LINEAR, components, coefficients));
kkinnunenccdaa042014-08-20 01:36:23 -0700259
260 memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
261 3 * components * sizeof(GrGLfloat));
262}
263
264void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents components,
265 const SkMatrix& matrix) {
266 GrGLfloat coefficients[3 * 3];
267 SkASSERT(components >= kS_PathTexGenComponents &&
268 components <= kSTR_PathTexGenComponents);
269
270 coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
271 coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
272 coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
273
274 if (components >= kST_PathTexGenComponents) {
275 coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
276 coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
277 coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
278 }
279
280 if (components >= kSTR_PathTexGenComponents) {
281 coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
282 coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
283 coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
284 }
285
286 this->enablePathTexGen(unitIdx, components, coefficients);
287}
288
289void GrGLPathRendering::flushPathTexGenSettings(int numUsedTexCoordSets) {
290 SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= numUsedTexCoordSets);
291
292 // Only write the inactive path tex gens, since active path tex gens were
293 // written when they were enabled.
294
295 SkDEBUGCODE(
296 for (int i = 0; i < numUsedTexCoordSets; i++) {
297 SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
298 }
299 );
300
301 for (int i = numUsedTexCoordSets; i < fHWActivePathTexGenSets; i++) {
302 SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
303
304 fGpu->setTextureUnit(i);
305 GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
306 fHWPathTexGenSettings[i].fNumComponents = 0;
307 }
308
309 fHWActivePathTexGenSets = numUsedTexCoordSets;
310}
311
kkinnunen5b653572014-08-20 04:13:27 -0700312void GrGLPathRendering::setProgramPathFragmentInputTransform(GrGLuint program, GrGLint location,
313 GrGLenum genMode, GrGLint components,
314 const SkMatrix& matrix) {
315 SkASSERT(caps().fragmentInputGenSupport);
316 GrGLfloat coefficients[3 * 3];
317 SkASSERT(components >= 1 && components <= 3);
kkinnunenccdaa042014-08-20 01:36:23 -0700318
kkinnunen5b653572014-08-20 04:13:27 -0700319 coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
320 coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
321 coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
kkinnunenccdaa042014-08-20 01:36:23 -0700322
kkinnunen5b653572014-08-20 04:13:27 -0700323 if (components >= 2) {
324 coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
325 coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
326 coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
kkinnunenccdaa042014-08-20 01:36:23 -0700327 }
kkinnunenccdaa042014-08-20 01:36:23 -0700328
kkinnunen5b653572014-08-20 04:13:27 -0700329 if (components >= 3) {
330 coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
331 coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
332 coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
kkinnunenccdaa042014-08-20 01:36:23 -0700333 }
kkinnunenccdaa042014-08-20 01:36:23 -0700334
kkinnunen5b653572014-08-20 04:13:27 -0700335 GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components, coefficients));
kkinnunenccdaa042014-08-20 01:36:23 -0700336}
337
338void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix,
339 const SkISize& renderTargetSize,
340 GrSurfaceOrigin renderTargetOrigin) {
341
342 SkASSERT(fGpu->glCaps().pathRenderingSupport());
343
344 if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
345 renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
346 matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
347 return;
348 }
349
350 fHWProjectionMatrixState.fViewMatrix = matrix;
351 fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
352 fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
353
354 GrGLfloat glMatrix[4 * 4];
355 fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix);
kkinnunenec56e452014-08-25 22:21:16 -0700356 GrGLenum matrixMode =
357 fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_PROJECTION : GR_GL_PROJECTION;
358 GL_CALL(MatrixLoadf(matrixMode, glMatrix));
kkinnunenccdaa042014-08-20 01:36:23 -0700359}
360
cdaltonc7103a12014-08-11 14:05:05 -0700361GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
362 if (range > 1) {
363 GrGLuint name;
364 GL_CALL_RET(name, GenPaths(range));
365 return name;
366 }
367
368 if (NULL == fPathNameAllocator.get()) {
369 static const int range = 65536;
370 GrGLuint firstName;
371 GL_CALL_RET(firstName, GenPaths(range));
372 fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
373 }
374
375 // When allocating names one at a time, pull from a client-side pool of
376 // available names in order to save a round trip to the GL server.
377 GrGLuint name = fPathNameAllocator->allocateName();
378
379 if (0 == name) {
380 // Our reserved path names are all in use. Fall back on GenPaths.
381 GL_CALL_RET(name, GenPaths(1));
382 }
383
384 return name;
385}
386
kkinnunen5b653572014-08-20 04:13:27 -0700387void GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
cdaltonc7103a12014-08-11 14:05:05 -0700388 if (range > 1) {
389 // It is not supported to delete names in ranges that were allocated
390 // individually using GrGLPathNameAllocator.
391 SkASSERT(NULL == fPathNameAllocator.get() ||
392 path + range <= fPathNameAllocator->firstName() ||
393 path >= fPathNameAllocator->endName());
394 GL_CALL(DeletePaths(path, range));
395 return;
396 }
397
398 if (NULL == fPathNameAllocator.get() ||
399 path < fPathNameAllocator->firstName() ||
400 path >= fPathNameAllocator->endName()) {
401 // If we aren't inside fPathNameAllocator's range then this name was
402 // generated by the GenPaths fallback (or else was never allocated).
403 GL_CALL(DeletePaths(path, 1));
404 return;
405 }
406
407 // Make the path empty to save memory, but don't free the name in the driver.
408 GL_CALL(PathCommands(path, 0, NULL, 0, GR_GL_FLOAT, NULL));
409 fPathNameAllocator->free(path);
410}
411
kkinnunen5b653572014-08-20 04:13:27 -0700412void GrGLPathRendering::flushPathStencilSettings(SkPath::FillType fill) {
413 GrStencilSettings pathStencilSettings;
414 fGpu->getPathStencilSettingsForFillType(fill, &pathStencilSettings);
415 if (fHWPathStencilSettings != pathStencilSettings) {
416 // Just the func, ref, and mask is set here. The op and write mask are params to the call
417 // that draws the path to the SB (glStencilFillPath)
418 GrGLenum func =
419 GrToGLStencilFunc(pathStencilSettings.func(GrStencilSettings::kFront_Face));
420 GL_CALL(PathStencilFunc(func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
421 pathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
422
423 fHWPathStencilSettings = pathStencilSettings;
424 }
cdaltonc7103a12014-08-11 14:05:05 -0700425}
426
kkinnunen5b653572014-08-20 04:13:27 -0700427inline void GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
cdaltonc7103a12014-08-11 14:05:05 -0700428 GrGLuint mask, GrGLenum coverMode) {
kkinnunen5b653572014-08-20 04:13:27 -0700429 if (caps().stencilThenCoverSupport) {
430 GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode));
431 return;
432 }
cdaltonc7103a12014-08-11 14:05:05 -0700433 GL_CALL(StencilFillPath(path, fillMode, mask));
434 GL_CALL(CoverFillPath(path, coverMode));
435}
436
kkinnunen5b653572014-08-20 04:13:27 -0700437inline void GrGLPathRendering::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
cdaltonc7103a12014-08-11 14:05:05 -0700438 GrGLuint mask, GrGLenum coverMode) {
kkinnunen5b653572014-08-20 04:13:27 -0700439 if (caps().stencilThenCoverSupport) {
440 GL_CALL(StencilThenCoverStrokePath(path, reference, mask, coverMode));
441 return;
442 }
cdaltonc7103a12014-08-11 14:05:05 -0700443 GL_CALL(StencilStrokePath(path, reference, mask));
444 GL_CALL(CoverStrokePath(path, coverMode));
445}
446
kkinnunen5b653572014-08-20 04:13:27 -0700447inline void GrGLPathRendering::stencilThenCoverFillPathInstanced(
cdaltonc7103a12014-08-11 14:05:05 -0700448 GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
449 GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
450 GrGLenum transformType, const GrGLfloat *transformValues) {
kkinnunen5b653572014-08-20 04:13:27 -0700451 if (caps().stencilThenCoverSupport) {
452 GL_CALL(StencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode,
453 mask, coverMode, transformType, transformValues));
454 return;
455 }
cdaltonc7103a12014-08-11 14:05:05 -0700456 GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
457 fillMode, mask, transformType, transformValues));
458 GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
459 coverMode, transformType, transformValues));
460}
461
kkinnunen5b653572014-08-20 04:13:27 -0700462inline void GrGLPathRendering::stencilThenCoverStrokePathInstanced(
463 GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
464 GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
465 GrGLenum transformType, const GrGLfloat *transformValues) {
466 if (caps().stencilThenCoverSupport) {
467 GL_CALL(StencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
468 reference, mask, coverMode, transformType,
469 transformValues));
470 return;
471 }
472
cdaltonc7103a12014-08-11 14:05:05 -0700473 GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
474 reference, mask, transformType, transformValues));
475 GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
476 coverMode, transformType, transformValues));
477}