Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "GrDefaultPathRenderer.h"
     10 
     11 #include "GrContext.h"
     12 #include "GrDrawState.h"
     13 #include "GrPathUtils.h"
     14 #include "SkString.h"
     15 #include "SkTrace.h"
     16 
     17 
     18 GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
     19                                              bool stencilWrapOpsSupport)
     20     : fSeparateStencil(separateStencilSupport)
     21     , fStencilWrapOps(stencilWrapOpsSupport) {
     22 }
     23 
     24 
     25 ////////////////////////////////////////////////////////////////////////////////
     26 // Stencil rules for paths
     27 
     28 ////// Even/Odd
     29 
     30 GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
     31     kInvert_StencilOp,
     32     kKeep_StencilOp,
     33     kAlwaysIfInClip_StencilFunc,
     34     0xffff,
     35     0xffff,
     36     0xffff);
     37 
     38 // ok not to check clip b/c stencil pass only wrote inside clip
     39 GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
     40     kZero_StencilOp,
     41     kZero_StencilOp,
     42     kNotEqual_StencilFunc,
     43     0xffff,
     44     0x0000,
     45     0xffff);
     46 
     47 // have to check clip b/c outside clip will always be zero.
     48 GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
     49     kZero_StencilOp,
     50     kZero_StencilOp,
     51     kEqualIfInClip_StencilFunc,
     52     0xffff,
     53     0x0000,
     54     0xffff);
     55 
     56 ////// Winding
     57 
     58 // when we have separate stencil we increment front faces / decrement back faces
     59 // when we don't have wrap incr and decr we use the stencil test to simulate
     60 // them.
     61 
     62 GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
     63     kIncWrap_StencilOp,             kDecWrap_StencilOp,
     64     kKeep_StencilOp,                kKeep_StencilOp,
     65     kAlwaysIfInClip_StencilFunc,    kAlwaysIfInClip_StencilFunc,
     66     0xffff,                         0xffff,
     67     0xffff,                         0xffff,
     68     0xffff,                         0xffff);
     69 
     70 // if inc'ing the max value, invert to make 0
     71 // if dec'ing zero invert to make all ones.
     72 // we can't avoid touching the stencil on both passing and
     73 // failing, so we can't resctrict ourselves to the clip.
     74 GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
     75     kInvert_StencilOp,              kInvert_StencilOp,
     76     kIncClamp_StencilOp,            kDecClamp_StencilOp,
     77     kEqual_StencilFunc,             kEqual_StencilFunc,
     78     0xffff,                         0xffff,
     79     0xffff,                         0x0000,
     80     0xffff,                         0xffff);
     81 
     82 // When there are no separate faces we do two passes to setup the winding rule
     83 // stencil. First we draw the front faces and inc, then we draw the back faces
     84 // and dec. These are same as the above two split into the incrementing and
     85 // decrementing passes.
     86 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
     87     kIncWrap_StencilOp,
     88     kKeep_StencilOp,
     89     kAlwaysIfInClip_StencilFunc,
     90     0xffff,
     91     0xffff,
     92     0xffff);
     93 
     94 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
     95     kDecWrap_StencilOp,
     96     kKeep_StencilOp,
     97     kAlwaysIfInClip_StencilFunc,
     98     0xffff,
     99     0xffff,
    100     0xffff);
    101 
    102 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
    103     kInvert_StencilOp,
    104     kIncClamp_StencilOp,
    105     kEqual_StencilFunc,
    106     0xffff,
    107     0xffff,
    108     0xffff);
    109 
    110 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
    111     kInvert_StencilOp,
    112     kDecClamp_StencilOp,
    113     kEqual_StencilFunc,
    114     0xffff,
    115     0x0000,
    116     0xffff);
    117 
    118 // Color passes are the same whether we use the two-sided stencil or two passes
    119 
    120 GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
    121     kZero_StencilOp,
    122     kZero_StencilOp,
    123     kNonZeroIfInClip_StencilFunc,
    124     0xffff,
    125     0x0000,
    126     0xffff);
    127 
    128 GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
    129     kZero_StencilOp,
    130     kZero_StencilOp,
    131     kEqualIfInClip_StencilFunc,
    132     0xffff,
    133     0x0000,
    134     0xffff);
    135 
    136 ////// Normal render to stencil
    137 
    138 // Sometimes the default path renderer can draw a path directly to the stencil
    139 // buffer without having to first resolve the interior / exterior.
    140 GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
    141     kZero_StencilOp,
    142     kIncClamp_StencilOp,
    143     kAlwaysIfInClip_StencilFunc,
    144     0xffff,
    145     0x0000,
    146     0xffff);
    147 
    148 ////////////////////////////////////////////////////////////////////////////////
    149 // Helpers for drawPath
    150 
    151 #define STENCIL_OFF     0   // Always disable stencil (even when needed)
    152 
    153 static inline bool single_pass_path(const GrPath& path, GrPathFill fill) {
    154 #if STENCIL_OFF
    155     return true;
    156 #else
    157     if (kEvenOdd_PathFill == fill || kWinding_PathFill == fill) {
    158         return path.isConvex();
    159     }
    160     return false;
    161 #endif
    162 }
    163 
    164 bool GrDefaultPathRenderer::requiresStencilPass(const SkPath& path,
    165                                                 GrPathFill fill,
    166                                                 const GrDrawTarget* target) const {
    167     return !single_pass_path(path, fill);
    168 }
    169 
    170 static inline void append_countour_edge_indices(GrPathFill fillType,
    171                                                 uint16_t fanCenterIdx,
    172                                                 uint16_t edgeV0Idx,
    173                                                 uint16_t** indices) {
    174     // when drawing lines we're appending line segments along
    175     // the contour. When applying the other fill rules we're
    176     // drawing triangle fans around fanCenterIdx.
    177     if (kHairLine_PathFill != fillType) {
    178         *((*indices)++) = fanCenterIdx;
    179     }
    180     *((*indices)++) = edgeV0Idx;
    181     *((*indices)++) = edgeV0Idx + 1;
    182 }
    183 
    184 bool GrDefaultPathRenderer::createGeom(const SkPath& path,
    185                                        GrPathFill fill,
    186                                        const GrVec* translate,
    187                                        GrScalar srcSpaceTol,
    188                                        GrDrawTarget* target,
    189                                        GrDrawState::StageMask stageMask,
    190                                        GrPrimitiveType* primType,
    191                                        int* vertexCnt,
    192                                        int* indexCnt) {
    193     {
    194     SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
    195 
    196     GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol);
    197     int contourCnt;
    198     int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt,
    199                                                   srcSpaceTol);
    200 
    201     if (maxPts <= 0) {
    202         return false;
    203     }
    204     if (maxPts > ((int)SK_MaxU16 + 1)) {
    205         GrPrintf("Path not rendered, too many verts (%d)\n", maxPts);
    206         return false;
    207     }
    208 
    209     GrVertexLayout layout = 0;
    210     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    211         if ((1 << s) & stageMask) {
    212             layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
    213         }
    214     }
    215 
    216     bool indexed = contourCnt > 1;
    217 
    218     int maxIdxs = 0;
    219     if (kHairLine_PathFill == fill) {
    220         if (indexed) {
    221             maxIdxs = 2 * maxPts;
    222             *primType = kLines_PrimitiveType;
    223         } else {
    224             *primType = kLineStrip_PrimitiveType;
    225         }
    226     } else {
    227         if (indexed) {
    228             maxIdxs = 3 * maxPts;
    229             *primType = kTriangles_PrimitiveType;
    230         } else {
    231             *primType = kTriangleFan_PrimitiveType;
    232         }
    233     }
    234 
    235     GrPoint* base;
    236     if (!target->reserveVertexSpace(layout, maxPts, (void**)&base)) {
    237         return false;
    238     }
    239     GrAssert(NULL != base);
    240     GrPoint* vert = base;
    241 
    242     uint16_t* idxBase = NULL;
    243     uint16_t* idx = NULL;
    244     uint16_t subpathIdxStart = 0;
    245     if (indexed) {
    246         if (!target->reserveIndexSpace(maxIdxs, (void**)&idxBase)) {
    247             target->resetVertexSource();
    248             return false;
    249         }
    250         GrAssert(NULL != idxBase);
    251         idx = idxBase;
    252     }
    253 
    254     GrPoint pts[4];
    255 
    256     bool first = true;
    257     int subpath = 0;
    258 
    259     SkPath::Iter iter(path, false);
    260 
    261     for (;;) {
    262         GrPathCmd cmd = (GrPathCmd)iter.next(pts);
    263         switch (cmd) {
    264             case kMove_PathCmd:
    265                 if (!first) {
    266                     uint16_t currIdx = (uint16_t) (vert - base);
    267                     subpathIdxStart = currIdx;
    268                     ++subpath;
    269                 }
    270                 *vert = pts[0];
    271                 vert++;
    272                 break;
    273             case kLine_PathCmd:
    274                 if (indexed) {
    275                     uint16_t prevIdx = (uint16_t)(vert - base) - 1;
    276                     append_countour_edge_indices(fill, subpathIdxStart,
    277                                                  prevIdx, &idx);
    278                 }
    279                 *(vert++) = pts[1];
    280                 break;
    281             case kQuadratic_PathCmd: {
    282                 // first pt of quad is the pt we ended on in previous step
    283                 uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1;
    284                 uint16_t numPts =  (uint16_t)
    285                     GrPathUtils::generateQuadraticPoints(
    286                             pts[0], pts[1], pts[2],
    287                             srcSpaceTolSqd, &vert,
    288                             GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
    289                 if (indexed) {
    290                     for (uint16_t i = 0; i < numPts; ++i) {
    291                         append_countour_edge_indices(fill, subpathIdxStart,
    292                                                      firstQPtIdx + i, &idx);
    293                     }
    294                 }
    295                 break;
    296             }
    297             case kCubic_PathCmd: {
    298                 // first pt of cubic is the pt we ended on in previous step
    299                 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1;
    300                 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
    301                                 pts[0], pts[1], pts[2], pts[3],
    302                                 srcSpaceTolSqd, &vert,
    303                                 GrPathUtils::cubicPointCount(pts, srcSpaceTol));
    304                 if (indexed) {
    305                     for (uint16_t i = 0; i < numPts; ++i) {
    306                         append_countour_edge_indices(fill, subpathIdxStart,
    307                                                      firstCPtIdx + i, &idx);
    308                     }
    309                 }
    310                 break;
    311             }
    312             case kClose_PathCmd:
    313                 break;
    314             case kEnd_PathCmd:
    315                 uint16_t currIdx = (uint16_t) (vert - base);
    316                 goto FINISHED;
    317         }
    318         first = false;
    319     }
    320 FINISHED:
    321     GrAssert((vert - base) <= maxPts);
    322     GrAssert((idx - idxBase) <= maxIdxs);
    323 
    324     *vertexCnt = vert - base;
    325     *indexCnt = idx - idxBase;
    326 
    327     if (NULL != translate &&
    328         (translate->fX || translate->fY)) {
    329         int count = vert - base;
    330         for (int i = 0; i < count; i++) {
    331             base[i].offset(translate->fX, translate->fY);
    332         }
    333     }
    334     }
    335     return true;
    336 }
    337 
    338 bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
    339                                              GrPathFill fill,
    340                                              const GrVec* translate,
    341                                              GrDrawTarget* target,
    342                                              GrDrawState::StageMask stageMask,
    343                                              bool stencilOnly) {
    344 
    345     GrMatrix viewM = target->getDrawState().getViewMatrix();
    346     GrScalar tol = GR_Scalar1;
    347     tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds());
    348     GrDrawState* drawState = target->drawState();
    349 
    350     int vertexCnt;
    351     int indexCnt;
    352     GrPrimitiveType primType;
    353     if (!this->createGeom(path,
    354                           fill,
    355                           translate,
    356                           tol,
    357                           target,
    358                           stageMask,
    359                           &primType,
    360                           &vertexCnt,
    361                           &indexCnt)) {
    362         return false;
    363     }
    364 
    365     GrAssert(NULL != target);
    366     GrDrawTarget::AutoStateRestore asr(target);
    367     bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
    368     // face culling doesn't make sense here
    369     GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
    370 
    371     int                         passCount = 0;
    372     const GrStencilSettings*    passes[3];
    373     GrDrawState::DrawFace       drawFace[3];
    374     bool                        reverse = false;
    375     bool                        lastPassIsBounds;
    376 
    377     if (kHairLine_PathFill == fill) {
    378         passCount = 1;
    379         if (stencilOnly) {
    380             passes[0] = &gDirectToStencil;
    381         } else {
    382             passes[0] = NULL;
    383         }
    384         lastPassIsBounds = false;
    385         drawFace[0] = GrDrawState::kBoth_DrawFace;
    386     } else {
    387         if (single_pass_path(path, fill)) {
    388             passCount = 1;
    389             if (stencilOnly) {
    390                 passes[0] = &gDirectToStencil;
    391             } else {
    392                 passes[0] = NULL;
    393             }
    394             drawFace[0] = GrDrawState::kBoth_DrawFace;
    395             lastPassIsBounds = false;
    396         } else {
    397             switch (fill) {
    398                 case kInverseEvenOdd_PathFill:
    399                     reverse = true;
    400                     // fallthrough
    401                 case kEvenOdd_PathFill:
    402                     passes[0] = &gEOStencilPass;
    403                     if (stencilOnly) {
    404                         passCount = 1;
    405                         lastPassIsBounds = false;
    406                     } else {
    407                         passCount = 2;
    408                         lastPassIsBounds = true;
    409                         if (reverse) {
    410                             passes[1] = &gInvEOColorPass;
    411                         } else {
    412                             passes[1] = &gEOColorPass;
    413                         }
    414                     }
    415                     drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
    416                     break;
    417 
    418                 case kInverseWinding_PathFill:
    419                     reverse = true;
    420                     // fallthrough
    421                 case kWinding_PathFill:
    422                     if (fSeparateStencil) {
    423                         if (fStencilWrapOps) {
    424                             passes[0] = &gWindStencilSeparateWithWrap;
    425                         } else {
    426                             passes[0] = &gWindStencilSeparateNoWrap;
    427                         }
    428                         passCount = 2;
    429                         drawFace[0] = GrDrawState::kBoth_DrawFace;
    430                     } else {
    431                         if (fStencilWrapOps) {
    432                             passes[0] = &gWindSingleStencilWithWrapInc;
    433                             passes[1] = &gWindSingleStencilWithWrapDec;
    434                         } else {
    435                             passes[0] = &gWindSingleStencilNoWrapInc;
    436                             passes[1] = &gWindSingleStencilNoWrapDec;
    437                         }
    438                         // which is cw and which is ccw is arbitrary.
    439                         drawFace[0] = GrDrawState::kCW_DrawFace;
    440                         drawFace[1] = GrDrawState::kCCW_DrawFace;
    441                         passCount = 3;
    442                     }
    443                     if (stencilOnly) {
    444                         lastPassIsBounds = false;
    445                         --passCount;
    446                     } else {
    447                         lastPassIsBounds = true;
    448                         drawFace[passCount-1] = GrDrawState::kBoth_DrawFace;
    449                         if (reverse) {
    450                             passes[passCount-1] = &gInvWindColorPass;
    451                         } else {
    452                             passes[passCount-1] = &gWindColorPass;
    453                         }
    454                     }
    455                     break;
    456                 default:
    457                     GrAssert(!"Unknown path fFill!");
    458                     return false;
    459             }
    460         }
    461     }
    462 
    463     {
    464     for (int p = 0; p < passCount; ++p) {
    465         drawState->setDrawFace(drawFace[p]);
    466         if (NULL != passes[p]) {
    467             *drawState->stencil() = *passes[p];
    468         }
    469 
    470         if (lastPassIsBounds && (p == passCount-1)) {
    471             if (!colorWritesWereDisabled) {
    472                 drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
    473             }
    474             GrRect bounds;
    475             if (reverse) {
    476                 GrAssert(NULL != drawState->getRenderTarget());
    477                 // draw over the whole world.
    478                 bounds.setLTRB(0, 0,
    479                                GrIntToScalar(drawState->getRenderTarget()->width()),
    480                                GrIntToScalar(drawState->getRenderTarget()->height()));
    481                 GrMatrix vmi;
    482                 // mapRect through persp matrix may not be correct
    483                 if (!drawState->getViewMatrix().hasPerspective() &&
    484                     drawState->getViewInverse(&vmi)) {
    485                     vmi.mapRect(&bounds);
    486                 } else {
    487                     if (stageMask) {
    488                         if (!drawState->getViewInverse(&vmi)) {
    489                             GrPrintf("Could not invert matrix.");
    490                             return false;
    491                         }
    492                         drawState->preConcatSamplerMatrices(stageMask, vmi);
    493                     }
    494                     drawState->setViewMatrix(GrMatrix::I());
    495                 }
    496             } else {
    497                 bounds = path.getBounds();
    498                 if (NULL != translate) {
    499                     bounds.offset(*translate);
    500                 }
    501             }
    502             GrDrawTarget::AutoGeometryPush agp(target);
    503             target->drawSimpleRect(bounds, NULL, stageMask);
    504         } else {
    505             if (passCount > 1) {
    506                 drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
    507             }
    508             if (indexCnt) {
    509                 target->drawIndexed(primType, 0, 0,
    510                                     vertexCnt, indexCnt);
    511             } else {
    512                 target->drawNonIndexed(primType, 0, vertexCnt);
    513             }
    514         }
    515     }
    516     }
    517     return true;
    518 }
    519 
    520 bool GrDefaultPathRenderer::canDrawPath(const SkPath& path,
    521                                         GrPathFill fill,
    522                                         const GrDrawTarget* target,
    523                                         bool antiAlias) const {
    524     // this class can draw any path with any fill but doesn't do any
    525     // anti-aliasing.
    526     return !antiAlias;
    527 }
    528 
    529 bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
    530                                        GrPathFill fill,
    531                                        const GrVec* translate,
    532                                        GrDrawTarget* target,
    533                                        GrDrawState::StageMask stageMask,
    534                                        bool antiAlias) {
    535     return this->internalDrawPath(path,
    536                                   fill,
    537                                   translate,
    538                                   target,
    539                                   stageMask,
    540                                   false);
    541 }
    542 
    543 void GrDefaultPathRenderer::drawPathToStencil(const SkPath& path,
    544                                               GrPathFill fill,
    545                                               GrDrawTarget* target) {
    546     GrAssert(kInverseEvenOdd_PathFill != fill);
    547     GrAssert(kInverseWinding_PathFill != fill);
    548     this->internalDrawPath(path, fill, NULL, target, 0, true);
    549 }
    550