blob: a20c4de08b03510762cfa9cd9d9821dc88ba575c [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
cdalton855d83f2014-09-18 13:51:53 -070017#include "SkStream.h"
18#include "SkTypeface.h"
19
kkinnunenccdaa042014-08-20 01:36:23 -070020#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
21#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(fGpu->glInterface(), RET, X)
22
23
cdalton55b24af2014-11-25 11:00:56 -080024static const GrGLenum gIndexType2GLType[] = {
25 GR_GL_UNSIGNED_BYTE,
26 GR_GL_UNSIGNED_SHORT,
27 GR_GL_UNSIGNED_INT
28};
29
30GR_STATIC_ASSERT(0 == GrPathRange::kU8_PathIndexType);
31GR_STATIC_ASSERT(1 == GrPathRange::kU16_PathIndexType);
32GR_STATIC_ASSERT(2 == GrPathRange::kU32_PathIndexType);
33GR_STATIC_ASSERT(GrPathRange::kU32_PathIndexType == GrPathRange::kLast_PathIndexType);
34
kkinnunenccdaa042014-08-20 01:36:23 -070035static const GrGLenum gXformType2GLType[] = {
36 GR_GL_NONE,
37 GR_GL_TRANSLATE_X,
38 GR_GL_TRANSLATE_Y,
39 GR_GL_TRANSLATE_2D,
40 GR_GL_TRANSPOSE_AFFINE_2D
41};
42
43GR_STATIC_ASSERT(0 == GrPathRendering::kNone_PathTransformType);
44GR_STATIC_ASSERT(1 == GrPathRendering::kTranslateX_PathTransformType);
45GR_STATIC_ASSERT(2 == GrPathRendering::kTranslateY_PathTransformType);
46GR_STATIC_ASSERT(3 == GrPathRendering::kTranslate_PathTransformType);
47GR_STATIC_ASSERT(4 == GrPathRendering::kAffine_PathTransformType);
48GR_STATIC_ASSERT(GrPathRendering::kAffine_PathTransformType == GrPathRendering::kLast_PathTransformType);
49
50static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
51 switch (op) {
52 default:
53 SkFAIL("Unexpected path fill.");
54 /* fallthrough */;
55 case kIncClamp_StencilOp:
56 return GR_GL_COUNT_UP;
57 case kInvert_StencilOp:
58 return GR_GL_INVERT;
59 }
60}
cdaltonc7103a12014-08-11 14:05:05 -070061
bsalomon861e1032014-12-16 07:33:49 -080062GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu)
kkinnunenccdaa042014-08-20 01:36:23 -070063 : fGpu(gpu) {
kkinnunen5b653572014-08-20 04:13:27 -070064 const GrGLInterface* glInterface = gpu->glInterface();
65 fCaps.stencilThenCoverSupport =
cdalton149b3ec2014-09-17 09:19:18 -070066 NULL != glInterface->fFunctions.fStencilThenCoverFillPath &&
67 NULL != glInterface->fFunctions.fStencilThenCoverStrokePath &&
68 NULL != glInterface->fFunctions.fStencilThenCoverFillPathInstanced &&
69 NULL != glInterface->fFunctions.fStencilThenCoverStrokePathInstanced;
kkinnunen5b653572014-08-20 04:13:27 -070070 fCaps.fragmentInputGenSupport =
kkinnunenec56e452014-08-25 22:21:16 -070071 kGLES_GrGLStandard == glInterface->fStandard &&
cdalton149b3ec2014-09-17 09:19:18 -070072 NULL != glInterface->fFunctions.fProgramPathFragmentInputGen;
73 fCaps.glyphLoadingSupport =
74 NULL != glInterface->fFunctions.fPathMemoryGlyphIndexArray;
kkinnunenec56e452014-08-25 22:21:16 -070075
76 if (!fCaps.fragmentInputGenSupport) {
77 fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords());
78 }
cdaltonc7103a12014-08-11 14:05:05 -070079}
80
81GrGLPathRendering::~GrGLPathRendering() {
82}
83
84void GrGLPathRendering::abandonGpuResources() {
85 fPathNameAllocator.reset(NULL);
86}
87
kkinnunenccdaa042014-08-20 01:36:23 -070088void GrGLPathRendering::resetContext() {
89 fHWProjectionMatrixState.invalidate();
90 // we don't use the model view matrix.
kkinnunenec56e452014-08-25 22:21:16 -070091 GrGLenum matrixMode =
92 fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_MODELVIEW : GR_GL_MODELVIEW;
93 GL_CALL(MatrixLoadIdentity(matrixMode));
kkinnunenccdaa042014-08-20 01:36:23 -070094
kkinnunenec56e452014-08-25 22:21:16 -070095 if (!caps().fragmentInputGenSupport) {
96 for (int i = 0; i < fGpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
97 GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
98 fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
99 fHWPathTexGenSettings[i].fNumComponents = 0;
100 }
101 fHWActivePathTexGenSets = 0;
kkinnunenccdaa042014-08-20 01:36:23 -0700102 }
kkinnunenccdaa042014-08-20 01:36:23 -0700103 fHWPathStencilSettings.invalidate();
104}
105
106GrPath* GrGLPathRendering::createPath(const SkPath& inPath, const SkStrokeRec& stroke) {
107 return SkNEW_ARGS(GrGLPath, (fGpu, inPath, stroke));
108}
109
cdalton855d83f2014-09-18 13:51:53 -0700110GrPathRange* GrGLPathRendering::createPathRange(GrPathRange::PathGenerator* pathGenerator,
111 const SkStrokeRec& stroke) {
112 return SkNEW_ARGS(GrGLPathRange, (fGpu, pathGenerator, stroke));
113}
114
115GrPathRange* GrGLPathRendering::createGlyphs(const SkTypeface* typeface,
116 const SkDescriptor* desc,
117 const SkStrokeRec& stroke) {
118 if (NULL != desc || !caps().glyphLoadingSupport) {
119 return GrPathRendering::createGlyphs(typeface, desc, stroke);
120 }
121
122 if (NULL == typeface) {
123 typeface = SkTypeface::GetDefaultTypeface();
124 SkASSERT(NULL != typeface);
125 }
126
127 int faceIndex;
128 SkAutoTUnref<SkStream> fontStream(typeface->openStream(&faceIndex));
129
130 const size_t fontDataLength = fontStream->getLength();
131 if (0 == fontDataLength) {
132 return GrPathRendering::createGlyphs(typeface, NULL, stroke);
133 }
134
135 SkTArray<uint8_t> fontTempBuffer;
136 const void* fontData = fontStream->getMemoryBase();
137 if (NULL == fontData) {
138 // TODO: Find a more efficient way to pass the font data (e.g. open file descriptor).
bsalomonef3fcd82014-12-12 08:51:38 -0800139 fontTempBuffer.reset(SkToInt(fontDataLength));
cdalton855d83f2014-09-18 13:51:53 -0700140 fontStream->read(&fontTempBuffer.front(), fontDataLength);
141 fontData = &fontTempBuffer.front();
142 }
143
bsalomonccb328d2014-12-11 13:31:06 -0800144 const int numPaths = typeface->countGlyphs();
cdalton855d83f2014-09-18 13:51:53 -0700145 const GrGLuint basePathID = this->genPaths(numPaths);
cdalton544c5b82014-09-19 11:12:46 -0700146 SkAutoTUnref<GrGLPath> templatePath(SkNEW_ARGS(GrGLPath, (fGpu, SkPath(), stroke)));
cdalton855d83f2014-09-18 13:51:53 -0700147
148 GrGLenum status;
149 GL_CALL_RET(status, PathMemoryGlyphIndexArray(basePathID, GR_GL_STANDARD_FONT_FORMAT,
cdalton544c5b82014-09-19 11:12:46 -0700150 fontDataLength, fontData, faceIndex, 0,
151 numPaths, templatePath->pathID(),
cdalton855d83f2014-09-18 13:51:53 -0700152 SkPaint::kCanonicalTextSizeForPaths));
153
154 if (GR_GL_FONT_GLYPHS_AVAILABLE != status) {
155 this->deletePaths(basePathID, numPaths);
156 return GrPathRendering::createGlyphs(typeface, NULL, stroke);
157 }
158
159 // This is a crude approximation. We may want to consider giving this class
160 // a pseudo PathGenerator whose sole purpose is to track the approximate gpu
161 // memory size.
162 const size_t gpuMemorySize = fontDataLength / 4;
163 return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize, stroke));
kkinnunenccdaa042014-08-20 01:36:23 -0700164}
165
joshualitt92e496f2014-10-31 13:56:50 -0700166void GrGLPathRendering::stencilPath(const GrPath* path, const GrStencilSettings& stencilSettings) {
kkinnunen5b653572014-08-20 04:13:27 -0700167 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
kkinnunen5b653572014-08-20 04:13:27 -0700168
joshualitt92e496f2014-10-31 13:56:50 -0700169 this->flushPathStencilSettings(stencilSettings);
kkinnunen5b653572014-08-20 04:13:27 -0700170 SkASSERT(!fHWPathStencilSettings.isTwoSided());
171
172 const SkStrokeRec& stroke = path->getStroke();
173
joshualitt92e496f2014-10-31 13:56:50 -0700174 GrGLenum fillMode =
175 gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
176 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
177
178 if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
179 GL_CALL(StencilFillPath(id, fillMode, writeMask));
180 }
181 if (stroke.needToApply()) {
182 GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
183 }
184}
185
186void GrGLPathRendering::drawPath(const GrPath* path, const GrStencilSettings& stencilSettings) {
187 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
joshualitt92e496f2014-10-31 13:56:50 -0700188
189 this->flushPathStencilSettings(stencilSettings);
190 SkASSERT(!fHWPathStencilSettings.isTwoSided());
191
192 const SkStrokeRec& stroke = path->getStroke();
kkinnunen5b653572014-08-20 04:13:27 -0700193
194 GrGLenum fillMode =
195 gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
196 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
197
joshualitt92e496f2014-10-31 13:56:50 -0700198 if (stroke.needToApply()) {
199 if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
kkinnunen5b653572014-08-20 04:13:27 -0700200 GL_CALL(StencilFillPath(id, fillMode, writeMask));
201 }
joshualitt92e496f2014-10-31 13:56:50 -0700202 this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
203 } else {
204 this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
kkinnunen5b653572014-08-20 04:13:27 -0700205 }
206}
207
cdalton55b24af2014-11-25 11:00:56 -0800208void GrGLPathRendering::drawPaths(const GrPathRange* pathRange,
209 const void* indices, PathIndexType indexType,
210 const float transformValues[], PathTransformType transformType,
211 int count, const GrStencilSettings& stencilSettings) {
kkinnunen5b653572014-08-20 04:13:27 -0700212 SkASSERT(fGpu->caps()->pathRenderingSupport());
kkinnunen5b653572014-08-20 04:13:27 -0700213
214 GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
215
joshualitt92e496f2014-10-31 13:56:50 -0700216 this->flushPathStencilSettings(stencilSettings);
kkinnunen5b653572014-08-20 04:13:27 -0700217 SkASSERT(!fHWPathStencilSettings.isTwoSided());
218
219 const SkStrokeRec& stroke = pathRange->getStroke();
220
kkinnunen5b653572014-08-20 04:13:27 -0700221 GrGLenum fillMode =
222 gr_stencil_op_to_gl_path_rendering_fill_mode(
223 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
224 GrGLint writeMask =
225 fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
226
joshualitt92e496f2014-10-31 13:56:50 -0700227 if (stroke.needToApply()) {
228 if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
kkinnunen5b653572014-08-20 04:13:27 -0700229 GL_CALL(StencilFillPathInstanced(
cdalton55b24af2014-11-25 11:00:56 -0800230 count, gIndexType2GLType[indexType], indices, baseID, fillMode,
231 writeMask, gXformType2GLType[transformType], transformValues));
kkinnunen5b653572014-08-20 04:13:27 -0700232 }
joshualitt92e496f2014-10-31 13:56:50 -0700233 this->stencilThenCoverStrokePathInstanced(
cdalton55b24af2014-11-25 11:00:56 -0800234 count, gIndexType2GLType[indexType], indices, baseID,
235 0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
236 gXformType2GLType[transformType], transformValues);
joshualitt92e496f2014-10-31 13:56:50 -0700237 } else {
238 this->stencilThenCoverFillPathInstanced(
cdalton55b24af2014-11-25 11:00:56 -0800239 count, gIndexType2GLType[indexType], indices, baseID,
240 fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
241 gXformType2GLType[transformType], transformValues);
kkinnunen5b653572014-08-20 04:13:27 -0700242 }
243}
244
kkinnunenccdaa042014-08-20 01:36:23 -0700245void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents components,
246 const GrGLfloat* coefficients) {
247 SkASSERT(components >= kS_PathTexGenComponents &&
248 components <= kSTR_PathTexGenComponents);
249 SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= unitIdx);
250
251 if (GR_GL_OBJECT_LINEAR == fHWPathTexGenSettings[unitIdx].fMode &&
252 components == fHWPathTexGenSettings[unitIdx].fNumComponents &&
253 !memcmp(coefficients, fHWPathTexGenSettings[unitIdx].fCoefficients,
254 3 * components * sizeof(GrGLfloat))) {
255 return;
256 }
257
258 fGpu->setTextureUnit(unitIdx);
259
260 fHWPathTexGenSettings[unitIdx].fNumComponents = components;
kkinnunen5b653572014-08-20 04:13:27 -0700261 GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx, GR_GL_OBJECT_LINEAR, components, coefficients));
kkinnunenccdaa042014-08-20 01:36:23 -0700262
263 memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
264 3 * components * sizeof(GrGLfloat));
265}
266
267void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents components,
268 const SkMatrix& matrix) {
269 GrGLfloat coefficients[3 * 3];
270 SkASSERT(components >= kS_PathTexGenComponents &&
271 components <= kSTR_PathTexGenComponents);
272
273 coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
274 coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
275 coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
276
277 if (components >= kST_PathTexGenComponents) {
278 coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
279 coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
280 coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
281 }
282
283 if (components >= kSTR_PathTexGenComponents) {
284 coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
285 coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
286 coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
287 }
288
289 this->enablePathTexGen(unitIdx, components, coefficients);
290}
291
292void GrGLPathRendering::flushPathTexGenSettings(int numUsedTexCoordSets) {
293 SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= numUsedTexCoordSets);
294
295 // Only write the inactive path tex gens, since active path tex gens were
296 // written when they were enabled.
297
298 SkDEBUGCODE(
299 for (int i = 0; i < numUsedTexCoordSets; i++) {
300 SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
301 }
302 );
303
304 for (int i = numUsedTexCoordSets; i < fHWActivePathTexGenSets; i++) {
305 SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
306
307 fGpu->setTextureUnit(i);
308 GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
309 fHWPathTexGenSettings[i].fNumComponents = 0;
310 }
311
312 fHWActivePathTexGenSets = numUsedTexCoordSets;
313}
314
kkinnunen5b653572014-08-20 04:13:27 -0700315void GrGLPathRendering::setProgramPathFragmentInputTransform(GrGLuint program, GrGLint location,
316 GrGLenum genMode, GrGLint components,
317 const SkMatrix& matrix) {
318 SkASSERT(caps().fragmentInputGenSupport);
319 GrGLfloat coefficients[3 * 3];
320 SkASSERT(components >= 1 && components <= 3);
kkinnunenccdaa042014-08-20 01:36:23 -0700321
kkinnunen5b653572014-08-20 04:13:27 -0700322 coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
323 coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
324 coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
kkinnunenccdaa042014-08-20 01:36:23 -0700325
kkinnunen5b653572014-08-20 04:13:27 -0700326 if (components >= 2) {
327 coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
328 coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
329 coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
kkinnunenccdaa042014-08-20 01:36:23 -0700330 }
kkinnunenccdaa042014-08-20 01:36:23 -0700331
kkinnunen5b653572014-08-20 04:13:27 -0700332 if (components >= 3) {
333 coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
334 coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
335 coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
kkinnunenccdaa042014-08-20 01:36:23 -0700336 }
kkinnunenccdaa042014-08-20 01:36:23 -0700337
kkinnunen5b653572014-08-20 04:13:27 -0700338 GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components, coefficients));
kkinnunenccdaa042014-08-20 01:36:23 -0700339}
340
341void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix,
342 const SkISize& renderTargetSize,
343 GrSurfaceOrigin renderTargetOrigin) {
344
345 SkASSERT(fGpu->glCaps().pathRenderingSupport());
346
347 if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
348 renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
349 matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
350 return;
351 }
352
353 fHWProjectionMatrixState.fViewMatrix = matrix;
354 fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
355 fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
356
357 GrGLfloat glMatrix[4 * 4];
358 fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix);
kkinnunenec56e452014-08-25 22:21:16 -0700359 GrGLenum matrixMode =
360 fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_PROJECTION : GR_GL_PROJECTION;
361 GL_CALL(MatrixLoadf(matrixMode, glMatrix));
kkinnunenccdaa042014-08-20 01:36:23 -0700362}
363
cdaltonc7103a12014-08-11 14:05:05 -0700364GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
365 if (range > 1) {
366 GrGLuint name;
367 GL_CALL_RET(name, GenPaths(range));
368 return name;
369 }
370
371 if (NULL == fPathNameAllocator.get()) {
372 static const int range = 65536;
373 GrGLuint firstName;
374 GL_CALL_RET(firstName, GenPaths(range));
375 fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
376 }
377
378 // When allocating names one at a time, pull from a client-side pool of
379 // available names in order to save a round trip to the GL server.
380 GrGLuint name = fPathNameAllocator->allocateName();
381
382 if (0 == name) {
383 // Our reserved path names are all in use. Fall back on GenPaths.
384 GL_CALL_RET(name, GenPaths(1));
385 }
386
387 return name;
388}
389
kkinnunen5b653572014-08-20 04:13:27 -0700390void GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
cdaltonc7103a12014-08-11 14:05:05 -0700391 if (range > 1) {
392 // It is not supported to delete names in ranges that were allocated
393 // individually using GrGLPathNameAllocator.
394 SkASSERT(NULL == fPathNameAllocator.get() ||
395 path + range <= fPathNameAllocator->firstName() ||
396 path >= fPathNameAllocator->endName());
397 GL_CALL(DeletePaths(path, range));
398 return;
399 }
400
401 if (NULL == fPathNameAllocator.get() ||
402 path < fPathNameAllocator->firstName() ||
403 path >= fPathNameAllocator->endName()) {
404 // If we aren't inside fPathNameAllocator's range then this name was
405 // generated by the GenPaths fallback (or else was never allocated).
406 GL_CALL(DeletePaths(path, 1));
407 return;
408 }
409
410 // Make the path empty to save memory, but don't free the name in the driver.
411 GL_CALL(PathCommands(path, 0, NULL, 0, GR_GL_FLOAT, NULL));
412 fPathNameAllocator->free(path);
413}
414
joshualitt92e496f2014-10-31 13:56:50 -0700415void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stencilSettings) {
416 if (fHWPathStencilSettings != stencilSettings) {
kkinnunen5b653572014-08-20 04:13:27 -0700417 // Just the func, ref, and mask is set here. The op and write mask are params to the call
418 // that draws the path to the SB (glStencilFillPath)
419 GrGLenum func =
joshualitt92e496f2014-10-31 13:56:50 -0700420 GrToGLStencilFunc(stencilSettings.func(GrStencilSettings::kFront_Face));
421 GL_CALL(PathStencilFunc(func, stencilSettings.funcRef(GrStencilSettings::kFront_Face),
422 stencilSettings.funcMask(GrStencilSettings::kFront_Face)));
kkinnunen5b653572014-08-20 04:13:27 -0700423
joshualitt92e496f2014-10-31 13:56:50 -0700424 fHWPathStencilSettings = stencilSettings;
kkinnunen5b653572014-08-20 04:13:27 -0700425 }
cdaltonc7103a12014-08-11 14:05:05 -0700426}
427
kkinnunen5b653572014-08-20 04:13:27 -0700428inline void GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
cdaltonc7103a12014-08-11 14:05:05 -0700429 GrGLuint mask, GrGLenum coverMode) {
kkinnunen5b653572014-08-20 04:13:27 -0700430 if (caps().stencilThenCoverSupport) {
431 GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode));
432 return;
433 }
cdaltonc7103a12014-08-11 14:05:05 -0700434 GL_CALL(StencilFillPath(path, fillMode, mask));
435 GL_CALL(CoverFillPath(path, coverMode));
436}
437
kkinnunen5b653572014-08-20 04:13:27 -0700438inline void GrGLPathRendering::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
cdaltonc7103a12014-08-11 14:05:05 -0700439 GrGLuint mask, GrGLenum coverMode) {
kkinnunen5b653572014-08-20 04:13:27 -0700440 if (caps().stencilThenCoverSupport) {
441 GL_CALL(StencilThenCoverStrokePath(path, reference, mask, coverMode));
442 return;
443 }
cdaltonc7103a12014-08-11 14:05:05 -0700444 GL_CALL(StencilStrokePath(path, reference, mask));
445 GL_CALL(CoverStrokePath(path, coverMode));
446}
447
kkinnunen5b653572014-08-20 04:13:27 -0700448inline void GrGLPathRendering::stencilThenCoverFillPathInstanced(
cdaltonc7103a12014-08-11 14:05:05 -0700449 GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
450 GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
451 GrGLenum transformType, const GrGLfloat *transformValues) {
kkinnunen5b653572014-08-20 04:13:27 -0700452 if (caps().stencilThenCoverSupport) {
453 GL_CALL(StencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode,
454 mask, coverMode, transformType, transformValues));
455 return;
456 }
cdaltonc7103a12014-08-11 14:05:05 -0700457 GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
458 fillMode, mask, transformType, transformValues));
459 GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
460 coverMode, transformType, transformValues));
461}
462
kkinnunen5b653572014-08-20 04:13:27 -0700463inline void GrGLPathRendering::stencilThenCoverStrokePathInstanced(
464 GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
465 GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
466 GrGLenum transformType, const GrGLfloat *transformValues) {
467 if (caps().stencilThenCoverSupport) {
468 GL_CALL(StencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
469 reference, mask, coverMode, transformType,
470 transformValues));
471 return;
472 }
473
cdaltonc7103a12014-08-11 14:05:05 -0700474 GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
475 reference, mask, transformType, transformValues));
476 GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
477 coverMode, transformType, transformValues));
478}