blob: a9152140c856bca3157866123c47fcef8a71e0ff [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"
jvanverth39edf762014-12-22 11:44:19 -080011#include "gl/GrGLGpu.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 =
cdalton149b3ec2014-09-17 09:19:18 -070071 NULL != glInterface->fFunctions.fProgramPathFragmentInputGen;
72 fCaps.glyphLoadingSupport =
73 NULL != glInterface->fFunctions.fPathMemoryGlyphIndexArray;
kkinnunenec56e452014-08-25 22:21:16 -070074
75 if (!fCaps.fragmentInputGenSupport) {
76 fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords());
77 }
cdaltonc7103a12014-08-11 14:05:05 -070078}
79
80GrGLPathRendering::~GrGLPathRendering() {
81}
82
83void GrGLPathRendering::abandonGpuResources() {
84 fPathNameAllocator.reset(NULL);
85}
86
kkinnunenccdaa042014-08-20 01:36:23 -070087void GrGLPathRendering::resetContext() {
88 fHWProjectionMatrixState.invalidate();
89 // we don't use the model view matrix.
kkinnunenec56e452014-08-25 22:21:16 -070090 GrGLenum matrixMode =
joshualitt89069a92015-01-14 13:51:18 -080091 fGpu->glCaps().nvprSupport() == GrGLCaps::kNormal_NvprSupport ? GR_GL_PATH_MODELVIEW :
92 GR_GL_MODELVIEW;
kkinnunenec56e452014-08-25 22:21:16 -070093 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;
scroggoa1193e42015-01-21 12:09:53 -0800128 SkAutoTDelete<SkStream> fontStream(typeface->openStream(&faceIndex));
cdalton855d83f2014-09-18 13:51:53 -0700129
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,
joshualittee2af952014-12-30 09:04:15 -0800342 const SkISize& renderTargetSize,
343 GrSurfaceOrigin renderTargetOrigin) {
kkinnunenccdaa042014-08-20 01:36:23 -0700344
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 =
joshualitt89069a92015-01-14 13:51:18 -0800360 fGpu->glCaps().nvprSupport() == GrGLCaps::kNormal_NvprSupport ? GR_GL_PATH_PROJECTION :
361 GR_GL_PROJECTION;
kkinnunenec56e452014-08-25 22:21:16 -0700362 GL_CALL(MatrixLoadf(matrixMode, glMatrix));
kkinnunenccdaa042014-08-20 01:36:23 -0700363}
364
cdaltonc7103a12014-08-11 14:05:05 -0700365GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
366 if (range > 1) {
367 GrGLuint name;
368 GL_CALL_RET(name, GenPaths(range));
369 return name;
370 }
371
372 if (NULL == fPathNameAllocator.get()) {
373 static const int range = 65536;
374 GrGLuint firstName;
375 GL_CALL_RET(firstName, GenPaths(range));
376 fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
377 }
378
379 // When allocating names one at a time, pull from a client-side pool of
380 // available names in order to save a round trip to the GL server.
381 GrGLuint name = fPathNameAllocator->allocateName();
382
383 if (0 == name) {
384 // Our reserved path names are all in use. Fall back on GenPaths.
385 GL_CALL_RET(name, GenPaths(1));
386 }
387
388 return name;
389}
390
kkinnunen5b653572014-08-20 04:13:27 -0700391void GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
cdaltonc7103a12014-08-11 14:05:05 -0700392 if (range > 1) {
393 // It is not supported to delete names in ranges that were allocated
394 // individually using GrGLPathNameAllocator.
395 SkASSERT(NULL == fPathNameAllocator.get() ||
396 path + range <= fPathNameAllocator->firstName() ||
397 path >= fPathNameAllocator->endName());
398 GL_CALL(DeletePaths(path, range));
399 return;
400 }
401
402 if (NULL == fPathNameAllocator.get() ||
403 path < fPathNameAllocator->firstName() ||
404 path >= fPathNameAllocator->endName()) {
405 // If we aren't inside fPathNameAllocator's range then this name was
406 // generated by the GenPaths fallback (or else was never allocated).
407 GL_CALL(DeletePaths(path, 1));
408 return;
409 }
410
411 // Make the path empty to save memory, but don't free the name in the driver.
412 GL_CALL(PathCommands(path, 0, NULL, 0, GR_GL_FLOAT, NULL));
413 fPathNameAllocator->free(path);
414}
415
joshualitt92e496f2014-10-31 13:56:50 -0700416void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stencilSettings) {
417 if (fHWPathStencilSettings != stencilSettings) {
kkinnunen5b653572014-08-20 04:13:27 -0700418 // Just the func, ref, and mask is set here. The op and write mask are params to the call
419 // that draws the path to the SB (glStencilFillPath)
420 GrGLenum func =
joshualitt92e496f2014-10-31 13:56:50 -0700421 GrToGLStencilFunc(stencilSettings.func(GrStencilSettings::kFront_Face));
422 GL_CALL(PathStencilFunc(func, stencilSettings.funcRef(GrStencilSettings::kFront_Face),
423 stencilSettings.funcMask(GrStencilSettings::kFront_Face)));
kkinnunen5b653572014-08-20 04:13:27 -0700424
joshualitt92e496f2014-10-31 13:56:50 -0700425 fHWPathStencilSettings = stencilSettings;
kkinnunen5b653572014-08-20 04:13:27 -0700426 }
cdaltonc7103a12014-08-11 14:05:05 -0700427}
428
kkinnunen5b653572014-08-20 04:13:27 -0700429inline void GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
cdaltonc7103a12014-08-11 14:05:05 -0700430 GrGLuint mask, GrGLenum coverMode) {
kkinnunen5b653572014-08-20 04:13:27 -0700431 if (caps().stencilThenCoverSupport) {
432 GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode));
433 return;
434 }
cdaltonc7103a12014-08-11 14:05:05 -0700435 GL_CALL(StencilFillPath(path, fillMode, mask));
436 GL_CALL(CoverFillPath(path, coverMode));
437}
438
kkinnunen5b653572014-08-20 04:13:27 -0700439inline void GrGLPathRendering::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
cdaltonc7103a12014-08-11 14:05:05 -0700440 GrGLuint mask, GrGLenum coverMode) {
kkinnunen5b653572014-08-20 04:13:27 -0700441 if (caps().stencilThenCoverSupport) {
442 GL_CALL(StencilThenCoverStrokePath(path, reference, mask, coverMode));
443 return;
444 }
cdaltonc7103a12014-08-11 14:05:05 -0700445 GL_CALL(StencilStrokePath(path, reference, mask));
446 GL_CALL(CoverStrokePath(path, coverMode));
447}
448
kkinnunen5b653572014-08-20 04:13:27 -0700449inline void GrGLPathRendering::stencilThenCoverFillPathInstanced(
cdaltonc7103a12014-08-11 14:05:05 -0700450 GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
451 GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
452 GrGLenum transformType, const GrGLfloat *transformValues) {
kkinnunen5b653572014-08-20 04:13:27 -0700453 if (caps().stencilThenCoverSupport) {
454 GL_CALL(StencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode,
455 mask, coverMode, transformType, transformValues));
456 return;
457 }
cdaltonc7103a12014-08-11 14:05:05 -0700458 GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
459 fillMode, mask, transformType, transformValues));
460 GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
461 coverMode, transformType, transformValues));
462}
463
kkinnunen5b653572014-08-20 04:13:27 -0700464inline void GrGLPathRendering::stencilThenCoverStrokePathInstanced(
465 GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
466 GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
467 GrGLenum transformType, const GrGLfloat *transformValues) {
468 if (caps().stencilThenCoverSupport) {
469 GL_CALL(StencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
470 reference, mask, coverMode, transformType,
471 transformValues));
472 return;
473 }
474
cdaltonc7103a12014-08-11 14:05:05 -0700475 GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
476 reference, mask, transformType, transformValues));
477 GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
478 coverMode, transformType, transformValues));
479}