Home | History | Annotate | Download | only in gl
      1 /*
      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"
      9 #include "gl/GrGLNameAllocator.h"
     10 #include "gl/GrGLUtil.h"
     11 #include "gl/GrGpuGL.h"
     12 
     13 #include "GrGLPath.h"
     14 #include "GrGLPathRange.h"
     15 #include "GrGLPathRendering.h"
     16 
     17 #include "SkStream.h"
     18 #include "SkTypeface.h"
     19 
     20 #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 
     24 static const GrGLenum gXformType2GLType[] = {
     25     GR_GL_NONE,
     26     GR_GL_TRANSLATE_X,
     27     GR_GL_TRANSLATE_Y,
     28     GR_GL_TRANSLATE_2D,
     29     GR_GL_TRANSPOSE_AFFINE_2D
     30 };
     31 
     32 GR_STATIC_ASSERT(0 == GrPathRendering::kNone_PathTransformType);
     33 GR_STATIC_ASSERT(1 == GrPathRendering::kTranslateX_PathTransformType);
     34 GR_STATIC_ASSERT(2 == GrPathRendering::kTranslateY_PathTransformType);
     35 GR_STATIC_ASSERT(3 == GrPathRendering::kTranslate_PathTransformType);
     36 GR_STATIC_ASSERT(4 == GrPathRendering::kAffine_PathTransformType);
     37 GR_STATIC_ASSERT(GrPathRendering::kAffine_PathTransformType == GrPathRendering::kLast_PathTransformType);
     38 
     39 static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
     40     switch (op) {
     41         default:
     42             SkFAIL("Unexpected path fill.");
     43             /* fallthrough */;
     44         case kIncClamp_StencilOp:
     45             return GR_GL_COUNT_UP;
     46         case kInvert_StencilOp:
     47             return GR_GL_INVERT;
     48     }
     49 }
     50 
     51 GrGLPathRendering::GrGLPathRendering(GrGpuGL* gpu)
     52     : fGpu(gpu) {
     53     const GrGLInterface* glInterface = gpu->glInterface();
     54     fCaps.stencilThenCoverSupport =
     55         NULL != glInterface->fFunctions.fStencilThenCoverFillPath &&
     56         NULL != glInterface->fFunctions.fStencilThenCoverStrokePath &&
     57         NULL != glInterface->fFunctions.fStencilThenCoverFillPathInstanced &&
     58         NULL != glInterface->fFunctions.fStencilThenCoverStrokePathInstanced;
     59     fCaps.fragmentInputGenSupport =
     60         kGLES_GrGLStandard == glInterface->fStandard &&
     61         NULL != glInterface->fFunctions.fProgramPathFragmentInputGen;
     62     fCaps.glyphLoadingSupport =
     63         NULL != glInterface->fFunctions.fPathMemoryGlyphIndexArray;
     64 
     65     if (!fCaps.fragmentInputGenSupport) {
     66         fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords());
     67     }
     68 }
     69 
     70 GrGLPathRendering::~GrGLPathRendering() {
     71 }
     72 
     73 void GrGLPathRendering::abandonGpuResources() {
     74     fPathNameAllocator.reset(NULL);
     75 }
     76 
     77 void GrGLPathRendering::resetContext() {
     78     fHWProjectionMatrixState.invalidate();
     79     // we don't use the model view matrix.
     80     GrGLenum matrixMode =
     81         fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_MODELVIEW : GR_GL_MODELVIEW;
     82     GL_CALL(MatrixLoadIdentity(matrixMode));
     83 
     84     if (!caps().fragmentInputGenSupport) {
     85         for (int i = 0; i < fGpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
     86             GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
     87             fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
     88             fHWPathTexGenSettings[i].fNumComponents = 0;
     89         }
     90         fHWActivePathTexGenSets = 0;
     91     }
     92     fHWPathStencilSettings.invalidate();
     93 }
     94 
     95 GrPath* GrGLPathRendering::createPath(const SkPath& inPath, const SkStrokeRec& stroke) {
     96     return SkNEW_ARGS(GrGLPath, (fGpu, inPath, stroke));
     97 }
     98 
     99 GrPathRange* GrGLPathRendering::createPathRange(GrPathRange::PathGenerator* pathGenerator,
    100                                                 const SkStrokeRec& stroke) {
    101     return SkNEW_ARGS(GrGLPathRange, (fGpu, pathGenerator, stroke));
    102 }
    103 
    104 GrPathRange* GrGLPathRendering::createGlyphs(const SkTypeface* typeface,
    105                                              const SkDescriptor* desc,
    106                                              const SkStrokeRec& stroke) {
    107     if (NULL != desc || !caps().glyphLoadingSupport) {
    108         return GrPathRendering::createGlyphs(typeface, desc, stroke);
    109     }
    110 
    111     if (NULL == typeface) {
    112         typeface = SkTypeface::GetDefaultTypeface();
    113         SkASSERT(NULL != typeface);
    114     }
    115 
    116     int faceIndex;
    117     SkAutoTUnref<SkStream> fontStream(typeface->openStream(&faceIndex));
    118 
    119     const size_t fontDataLength = fontStream->getLength();
    120     if (0 == fontDataLength) {
    121         return GrPathRendering::createGlyphs(typeface, NULL, stroke);
    122     }
    123 
    124     SkTArray<uint8_t> fontTempBuffer;
    125     const void* fontData = fontStream->getMemoryBase();
    126     if (NULL == fontData) {
    127         // TODO: Find a more efficient way to pass the font data (e.g. open file descriptor).
    128         fontTempBuffer.reset(fontDataLength);
    129         fontStream->read(&fontTempBuffer.front(), fontDataLength);
    130         fontData = &fontTempBuffer.front();
    131     }
    132 
    133     const size_t numPaths = typeface->countGlyphs();
    134     const GrGLuint basePathID = this->genPaths(numPaths);
    135     SkAutoTUnref<GrGLPath> templatePath(SkNEW_ARGS(GrGLPath, (fGpu, SkPath(), stroke)));
    136 
    137     GrGLenum status;
    138     GL_CALL_RET(status, PathMemoryGlyphIndexArray(basePathID, GR_GL_STANDARD_FONT_FORMAT,
    139                                                   fontDataLength, fontData, faceIndex, 0,
    140                                                   numPaths, templatePath->pathID(),
    141                                                   SkPaint::kCanonicalTextSizeForPaths));
    142 
    143     if (GR_GL_FONT_GLYPHS_AVAILABLE != status) {
    144         this->deletePaths(basePathID, numPaths);
    145         return GrPathRendering::createGlyphs(typeface, NULL, stroke);
    146     }
    147 
    148     // This is a crude approximation. We may want to consider giving this class
    149     // a pseudo PathGenerator whose sole purpose is to track the approximate gpu
    150     // memory size.
    151     const size_t gpuMemorySize = fontDataLength / 4;
    152     return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize, stroke));
    153 }
    154 
    155 void GrGLPathRendering::stencilPath(const GrPath* path, SkPath::FillType fill) {
    156     GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
    157     SkASSERT(fGpu->drawState()->getRenderTarget());
    158     SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
    159 
    160     this->flushPathStencilSettings(fill);
    161     SkASSERT(!fHWPathStencilSettings.isTwoSided());
    162 
    163     GrGLenum fillMode =
    164         gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
    165     GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
    166     GL_CALL(StencilFillPath(id, fillMode, writeMask));
    167 }
    168 
    169 void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) {
    170     GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
    171     SkASSERT(fGpu->drawState()->getRenderTarget());
    172     SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
    173 
    174     this->flushPathStencilSettings(fill);
    175     SkASSERT(!fHWPathStencilSettings.isTwoSided());
    176 
    177     const SkStrokeRec& stroke = path->getStroke();
    178 
    179     SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill);
    180 
    181     GrGLenum fillMode =
    182         gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
    183     GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
    184 
    185     if (nonInvertedFill == fill) {
    186         if (stroke.needToApply()) {
    187             if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
    188                 GL_CALL(StencilFillPath(id, fillMode, writeMask));
    189             }
    190             this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
    191         } else {
    192             this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
    193         }
    194     } else {
    195         if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
    196             GL_CALL(StencilFillPath(id, fillMode, writeMask));
    197         }
    198         if (stroke.needToApply()) {
    199             GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
    200         }
    201 
    202         GrDrawState* drawState = fGpu->drawState();
    203         GrDrawState::AutoViewMatrixRestore avmr;
    204         SkRect bounds = SkRect::MakeLTRB(0, 0,
    205                                          SkIntToScalar(drawState->getRenderTarget()->width()),
    206                                          SkIntToScalar(drawState->getRenderTarget()->height()));
    207         SkMatrix vmi;
    208         // mapRect through persp matrix may not be correct
    209         if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
    210             vmi.mapRect(&bounds);
    211             // theoretically could set bloat = 0, instead leave it because of matrix inversion
    212             // precision.
    213             SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
    214             bounds.outset(bloat, bloat);
    215         } else {
    216             avmr.setIdentity(drawState);
    217         }
    218 
    219         fGpu->drawSimpleRect(bounds);
    220     }
    221 }
    222 
    223 void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t indices[], int count,
    224                                   const float transforms[], PathTransformType transformsType,
    225                                   SkPath::FillType fill) {
    226     SkASSERT(fGpu->caps()->pathRenderingSupport());
    227     SkASSERT(fGpu->drawState()->getRenderTarget());
    228     SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer());
    229 
    230     GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
    231 
    232     this->flushPathStencilSettings(fill);
    233     SkASSERT(!fHWPathStencilSettings.isTwoSided());
    234 
    235     const SkStrokeRec& stroke = pathRange->getStroke();
    236 
    237     SkPath::FillType nonInvertedFill =
    238         SkPath::ConvertToNonInverseFillType(fill);
    239 
    240     GrGLenum fillMode =
    241         gr_stencil_op_to_gl_path_rendering_fill_mode(
    242             fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
    243     GrGLint writeMask =
    244         fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
    245 
    246     if (nonInvertedFill == fill) {
    247         if (stroke.needToApply()) {
    248             if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
    249                 GL_CALL(StencilFillPathInstanced(
    250                                 count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
    251                                 writeMask, gXformType2GLType[transformsType],
    252                                 transforms));
    253             }
    254             this->stencilThenCoverStrokePathInstanced(
    255                                 count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
    256                                 GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
    257                                 gXformType2GLType[transformsType], transforms);
    258         } else {
    259             this->stencilThenCoverFillPathInstanced(
    260                                 count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
    261                                 GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
    262                                 gXformType2GLType[transformsType], transforms);
    263         }
    264     } else {
    265         if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
    266             GL_CALL(StencilFillPathInstanced(
    267                                 count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
    268                                 writeMask, gXformType2GLType[transformsType],
    269                                 transforms));
    270         }
    271         if (stroke.needToApply()) {
    272             GL_CALL(StencilStrokePathInstanced(
    273                                 count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
    274                                 writeMask, gXformType2GLType[transformsType],
    275                                 transforms));
    276         }
    277 
    278         GrDrawState* drawState = fGpu->drawState();
    279         GrDrawState::AutoViewMatrixRestore avmr;
    280         SkRect bounds = SkRect::MakeLTRB(0, 0,
    281                                          SkIntToScalar(drawState->getRenderTarget()->width()),
    282                                          SkIntToScalar(drawState->getRenderTarget()->height()));
    283         SkMatrix vmi;
    284         // mapRect through persp matrix may not be correct
    285         if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
    286             vmi.mapRect(&bounds);
    287             // theoretically could set bloat = 0, instead leave it because of matrix inversion
    288             // precision.
    289             SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
    290             bounds.outset(bloat, bloat);
    291         } else {
    292             avmr.setIdentity(drawState);
    293         }
    294 
    295         fGpu->drawSimpleRect(bounds);
    296     }
    297 }
    298 
    299 void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents components,
    300                                          const GrGLfloat* coefficients) {
    301     SkASSERT(components >= kS_PathTexGenComponents &&
    302              components <= kSTR_PathTexGenComponents);
    303     SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= unitIdx);
    304 
    305     if (GR_GL_OBJECT_LINEAR == fHWPathTexGenSettings[unitIdx].fMode &&
    306         components == fHWPathTexGenSettings[unitIdx].fNumComponents &&
    307         !memcmp(coefficients, fHWPathTexGenSettings[unitIdx].fCoefficients,
    308                 3 * components * sizeof(GrGLfloat))) {
    309         return;
    310     }
    311 
    312     fGpu->setTextureUnit(unitIdx);
    313 
    314     fHWPathTexGenSettings[unitIdx].fNumComponents = components;
    315     GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx, GR_GL_OBJECT_LINEAR, components, coefficients));
    316 
    317     memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
    318            3 * components * sizeof(GrGLfloat));
    319 }
    320 
    321 void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents components,
    322                                          const SkMatrix& matrix) {
    323     GrGLfloat coefficients[3 * 3];
    324     SkASSERT(components >= kS_PathTexGenComponents &&
    325              components <= kSTR_PathTexGenComponents);
    326 
    327     coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
    328     coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
    329     coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
    330 
    331     if (components >= kST_PathTexGenComponents) {
    332         coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
    333         coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
    334         coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
    335     }
    336 
    337     if (components >= kSTR_PathTexGenComponents) {
    338         coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
    339         coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
    340         coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
    341     }
    342 
    343     this->enablePathTexGen(unitIdx, components, coefficients);
    344 }
    345 
    346 void GrGLPathRendering::flushPathTexGenSettings(int numUsedTexCoordSets) {
    347     SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= numUsedTexCoordSets);
    348 
    349     // Only write the inactive path tex gens, since active path tex gens were
    350     // written when they were enabled.
    351 
    352     SkDEBUGCODE(
    353         for (int i = 0; i < numUsedTexCoordSets; i++) {
    354             SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
    355         }
    356     );
    357 
    358     for (int i = numUsedTexCoordSets; i < fHWActivePathTexGenSets; i++) {
    359         SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
    360 
    361         fGpu->setTextureUnit(i);
    362         GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
    363         fHWPathTexGenSettings[i].fNumComponents = 0;
    364     }
    365 
    366     fHWActivePathTexGenSets = numUsedTexCoordSets;
    367 }
    368 
    369 void GrGLPathRendering::setProgramPathFragmentInputTransform(GrGLuint program, GrGLint location,
    370                                                              GrGLenum genMode, GrGLint components,
    371                                                              const SkMatrix& matrix) {
    372     SkASSERT(caps().fragmentInputGenSupport);
    373     GrGLfloat coefficients[3 * 3];
    374     SkASSERT(components >= 1 && components <= 3);
    375 
    376     coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
    377     coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
    378     coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
    379 
    380     if (components >= 2) {
    381         coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
    382         coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
    383         coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
    384     }
    385 
    386     if (components >= 3) {
    387         coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
    388         coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
    389         coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
    390     }
    391 
    392     GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components, coefficients));
    393 }
    394 
    395 void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix,
    396                                   const SkISize& renderTargetSize,
    397                                   GrSurfaceOrigin renderTargetOrigin) {
    398 
    399     SkASSERT(fGpu->glCaps().pathRenderingSupport());
    400 
    401     if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
    402         renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
    403         matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
    404         return;
    405     }
    406 
    407     fHWProjectionMatrixState.fViewMatrix = matrix;
    408     fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
    409     fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
    410 
    411     GrGLfloat glMatrix[4 * 4];
    412     fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix);
    413      GrGLenum matrixMode =
    414          fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_PROJECTION : GR_GL_PROJECTION;
    415      GL_CALL(MatrixLoadf(matrixMode, glMatrix));
    416 }
    417 
    418 GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
    419     if (range > 1) {
    420         GrGLuint name;
    421         GL_CALL_RET(name, GenPaths(range));
    422         return name;
    423     }
    424 
    425     if (NULL == fPathNameAllocator.get()) {
    426         static const int range = 65536;
    427         GrGLuint firstName;
    428         GL_CALL_RET(firstName, GenPaths(range));
    429         fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
    430     }
    431 
    432     // When allocating names one at a time, pull from a client-side pool of
    433     // available names in order to save a round trip to the GL server.
    434     GrGLuint name = fPathNameAllocator->allocateName();
    435 
    436     if (0 == name) {
    437         // Our reserved path names are all in use. Fall back on GenPaths.
    438         GL_CALL_RET(name, GenPaths(1));
    439     }
    440 
    441     return name;
    442 }
    443 
    444 void GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
    445     if (range > 1) {
    446         // It is not supported to delete names in ranges that were allocated
    447         // individually using GrGLPathNameAllocator.
    448         SkASSERT(NULL == fPathNameAllocator.get() ||
    449                  path + range <= fPathNameAllocator->firstName() ||
    450                  path >= fPathNameAllocator->endName());
    451         GL_CALL(DeletePaths(path, range));
    452         return;
    453     }
    454 
    455     if (NULL == fPathNameAllocator.get() ||
    456         path < fPathNameAllocator->firstName() ||
    457         path >= fPathNameAllocator->endName()) {
    458         // If we aren't inside fPathNameAllocator's range then this name was
    459         // generated by the GenPaths fallback (or else was never allocated).
    460         GL_CALL(DeletePaths(path, 1));
    461         return;
    462     }
    463 
    464     // Make the path empty to save memory, but don't free the name in the driver.
    465     GL_CALL(PathCommands(path, 0, NULL, 0, GR_GL_FLOAT, NULL));
    466     fPathNameAllocator->free(path);
    467 }
    468 
    469 void GrGLPathRendering::flushPathStencilSettings(SkPath::FillType fill) {
    470     GrStencilSettings pathStencilSettings;
    471     fGpu->getPathStencilSettingsForFillType(fill, &pathStencilSettings);
    472     if (fHWPathStencilSettings != pathStencilSettings) {
    473         // Just the func, ref, and mask is set here. The op and write mask are params to the call
    474         // that draws the path to the SB (glStencilFillPath)
    475         GrGLenum func =
    476             GrToGLStencilFunc(pathStencilSettings.func(GrStencilSettings::kFront_Face));
    477         GL_CALL(PathStencilFunc(func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
    478                                 pathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
    479 
    480         fHWPathStencilSettings = pathStencilSettings;
    481     }
    482 }
    483 
    484 inline void GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
    485                                                      GrGLuint mask, GrGLenum coverMode) {
    486     if (caps().stencilThenCoverSupport) {
    487         GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode));
    488         return;
    489     }
    490     GL_CALL(StencilFillPath(path, fillMode, mask));
    491     GL_CALL(CoverFillPath(path, coverMode));
    492 }
    493 
    494 inline void GrGLPathRendering::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
    495                                                        GrGLuint mask, GrGLenum coverMode) {
    496     if (caps().stencilThenCoverSupport) {
    497         GL_CALL(StencilThenCoverStrokePath(path, reference, mask, coverMode));
    498         return;
    499     }
    500     GL_CALL(StencilStrokePath(path, reference, mask));
    501     GL_CALL(CoverStrokePath(path, coverMode));
    502 }
    503 
    504 inline void GrGLPathRendering::stencilThenCoverFillPathInstanced(
    505              GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
    506              GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
    507              GrGLenum transformType, const GrGLfloat *transformValues) {
    508     if (caps().stencilThenCoverSupport) {
    509         GL_CALL(StencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode,
    510                                                   mask, coverMode, transformType, transformValues));
    511         return;
    512     }
    513     GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
    514                                      fillMode, mask, transformType, transformValues));
    515     GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
    516                                    coverMode, transformType, transformValues));
    517 }
    518 
    519 inline void GrGLPathRendering::stencilThenCoverStrokePathInstanced(
    520         GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
    521         GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
    522         GrGLenum transformType, const GrGLfloat *transformValues) {
    523     if (caps().stencilThenCoverSupport) {
    524         GL_CALL(StencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
    525                                                     reference, mask, coverMode, transformType,
    526                                                     transformValues));
    527         return;
    528     }
    529 
    530     GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
    531                                        reference, mask, transformType, transformValues));
    532     GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
    533                                      coverMode, transformType, transformValues));
    534 }
    535