Make a separate path renderer object. Move enum types to GrTypes.h

Review URL http://codereview.appspot.com/4167067/



git-svn-id: http://skia.googlecode.com/svn/trunk@829 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 7ce8f35..dbc7f6c 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -24,6 +24,7 @@
 #include "GrIndexBuffer.h"

 #include "GrInOrderDrawBuffer.h"

 #include "GrBufferAllocPool.h"

+#include "GrPathRenderer.h"

 

 #define DEFER_TEXT_RENDERING 1

 

@@ -62,6 +63,7 @@
     delete fDrawBuffer;

     delete fDrawBufferVBAllocPool;

     delete fDrawBufferVBAllocPool;

+    delete fPathRenderer;

 }

 

 void GrContext::abandonAllTextures() {

@@ -146,7 +148,7 @@
             fGpu->setStencilPass(GrDrawTarget::kNone_StencilPass);

             fGpu->setViewMatrix(GrMatrix::I());

             fGpu->setAlpha(0xff);

-            fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff, GrDrawTarget::kZero_BlendCoeff);

+            fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);

             fGpu->disableState(GrDrawTarget::kDither_StateBit |

                                GrDrawTarget::kClip_StateBit   |

                                GrDrawTarget::kAntialias_StateBit);

@@ -166,7 +168,7 @@
                                      texture->height(),

                                      2*sizeof(GrPoint));

                 verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));

-                fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,

+                fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,

                                      0, 4);

                 entry = fTextureCache->createAndLock(*key, texture);

             }

@@ -349,18 +351,18 @@
             return;

         }

 

-        GrDrawTarget::PrimitiveType primType;

+        GrPrimitiveType primType;

         int vertCount;

         GrPoint* vertex = geo.positions();

 

         if (width > 0) {

             vertCount = 10;

-            primType = GrDrawTarget::kTriangleStrip_PrimitiveType;

+            primType = kTriangleStrip_PrimitiveType;

             setStrokeRectStrip(vertex, rect, width);

         } else {

             // hairline

             vertCount = 5;

-            primType = GrDrawTarget::kLineStrip_PrimitiveType;

+            primType = kLineStrip_PrimitiveType;

             vertex[0].set(rect.fLeft, rect.fTop);

             vertex[1].set(rect.fRight, rect.fTop);

             vertex[2].set(rect.fRight, rect.fBottom);

@@ -398,7 +400,7 @@
             if (textured) {

                 target->preConcatSamplerMatrix(0, m);

             }

-            target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);

+            target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);

         #else

             target->drawSimpleRect(rect, matrix, textured ? 1 : 0);

         #endif

@@ -443,7 +445,7 @@
     target->preConcatSamplerMatrix(0, m);

 

     target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());

-    target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);

+    target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);

 #else

 

     GrDrawTarget* target;

@@ -463,7 +465,7 @@
 }

 

 void GrContext::drawVertices(const GrPaint& paint,

-                             GrDrawTarget::PrimitiveType primitiveType,

+                             GrPrimitiveType primitiveType,

                              int vertexCount,

                              const GrPoint positions[],

                              const GrPoint texCoords[],

@@ -529,339 +531,19 @@
 

 ////////////////////////////////////////////////////////////////////////////////

 

-#define STENCIL_OFF     0   // Always disable stencil (even when needed)

-#define EVAL_TOL GR_Scalar1

-

-static const uint32_t MAX_POINTS_PER_CURVE = 1 << 10;

-

-static uint32_t quadratic_point_count(const GrPoint points[], GrScalar tol) {

-    GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);

-    // TODO: fixed points sqrt

-    if (d < tol) {

-        return 1;

-    } else {

-        // Each time we subdivide, d should be cut in 4. So we need to

-        // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)

-        // points.

-        // 2^(log4(x)) = sqrt(x);

-        d = ceilf(sqrtf(d/tol));

-        return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);

-    }

-}

-

-static uint32_t generate_quadratic_points(const GrPoint& p0,

-                                          const GrPoint& p1,

-                                          const GrPoint& p2,

-                                          GrScalar tolSqd,

-                                          GrPoint** points,

-                                          uint32_t pointsLeft) {

-    if (pointsLeft < 2 ||

-        (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {

-        (*points)[0] = p2;

-        *points += 1;

-        return 1;

-    }

-

-    GrPoint q[] = {

-        GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),

-        GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),

-    };

-    GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY));

-

-    pointsLeft >>= 1;

-    uint32_t a = generate_quadratic_points(p0, q[0], r, tolSqd, points, pointsLeft);

-    uint32_t b = generate_quadratic_points(r, q[1], p2, tolSqd, points, pointsLeft);

-    return a + b;

-}

-

-static uint32_t cubic_point_count(const GrPoint points[], GrScalar tol) {

-    GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),

-                       points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));

-    d = sqrtf(d);

-    if (d < tol) {

-        return 1;

-    } else {

-        d = ceilf(sqrtf(d/tol));

-        return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);

-    }

-}

-

-static uint32_t generate_cubic_points(const GrPoint& p0,

-                                      const GrPoint& p1,

-                                      const GrPoint& p2,

-                                      const GrPoint& p3,

-                                      GrScalar tolSqd,

-                                      GrPoint** points,

-                                      uint32_t pointsLeft) {

-    if (pointsLeft < 2 ||

-        (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&

-         p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {

-            (*points)[0] = p3;

-            *points += 1;

-            return 1;

-        }

-    GrPoint q[] = {

-        GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),

-        GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),

-        GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY))

-    };

-    GrPoint r[] = {

-        GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)),

-        GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY))

-    };

-    GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY));

-    pointsLeft >>= 1;

-    uint32_t a = generate_cubic_points(p0, q[0], r[0], s, tolSqd, points, pointsLeft);

-    uint32_t b = generate_cubic_points(s, r[1], q[2], p3, tolSqd, points, pointsLeft);

-    return a + b;

-}

-

-static int worst_case_point_count(GrPathIter* path,

-                                  int* subpaths,

-                                  GrScalar tol) {

-    int pointCount = 0;

-    *subpaths = 1;

-

-    bool first = true;

-

-    GrPathIter::Command cmd;

-

-    GrPoint pts[4];

-    while ((cmd = path->next(pts)) != GrPathIter::kEnd_Command) {

-

-        switch (cmd) {

-            case GrPathIter::kLine_Command:

-                pointCount += 1;

-                break;

-            case GrPathIter::kQuadratic_Command:

-                pointCount += quadratic_point_count(pts, tol);

-                break;

-            case GrPathIter::kCubic_Command:

-                pointCount += cubic_point_count(pts, tol);

-                break;

-            case GrPathIter::kMove_Command:

-                pointCount += 1;

-                if (!first) {

-                    ++(*subpaths);

-                }

-                break;

-            default:

-                break;

-        }

-        first = false;

-    }

-    return pointCount;

-}

-

-static inline bool single_pass_path(const GrPathIter& path,

-                                    GrContext::PathFills fill,

-                                    const GrDrawTarget& target) {

-#if STENCIL_OFF

-    return true;

-#else

-    if (GrContext::kEvenOdd_PathFill == fill) {

-        GrPathIter::ConvexHint hint = path.hint();

-        return hint == GrPathIter::kConvex_ConvexHint ||

-               hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint;

-    } else if (GrContext::kWinding_PathFill == fill) {

-        GrPathIter::ConvexHint hint = path.hint();

-        return hint == GrPathIter::kConvex_ConvexHint ||

-               hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint ||

-               (hint == GrPathIter::kSameWindingConvexPieces_ConvexHint &&

-                target.canDisableBlend() && !target.isDitherState());

-

-    }

-    return false;

-#endif

-}

-

 void GrContext::drawPath(const GrPaint& paint,

                          GrPathIter* path,

-                         PathFills fill,

+                         GrPathFill fill,

                          const GrPoint* translate) {

 

 

     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);

 

-    GrDrawTarget::AutoStateRestore asr(target);

-

-    GrMatrix viewM = target->getViewMatrix();

-    // In order to tesselate the path we get a bound on how much the matrix can

-    // stretch when mapping to screen coordinates.

-    GrScalar stretch = viewM.getMaxStretch();

-    bool useStretch = stretch > 0;

-    GrScalar tol = EVAL_TOL;

-    if (!useStretch) {

-        // TODO: deal with perspective in some better way.

-        tol /= 10;

-    } else {

-        // TODO: fixed point divide

-        GrScalar sinv = 1 / stretch;

-        tol = GrMul(tol, sinv);

-    }

-    GrScalar tolSqd = GrMul(tol, tol);

-

-    int subpathCnt;

-    int maxPts = worst_case_point_count(path,

-                                        &subpathCnt,

-                                        tol);

-    GrVertexLayout layout = 0;

-

+    GrDrawTarget::StageBitfield enabledStages = 0;

     if (NULL != paint.getTexture()) {

-        layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);

+        enabledStages |= 1;

     }

-    // add 4 to hold the bounding rect

-    GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxPts + 4, 0);

-

-    GrPoint* base = (GrPoint*) arg.vertices();

-    GrPoint* vert = base;

-    GrPoint* subpathBase = base;

-

-    GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);

-

-    path->rewind();

-

-    // TODO: use primitve restart if available rather than multiple draws

-    GrDrawTarget::PrimitiveType type;

-    int                         passCount = 0;

-    GrDrawTarget::StencilPass   passes[3];

-    bool                        reverse = false;

-

-    if (kHairLine_PathFill == fill) {

-        type = GrDrawTarget::kLineStrip_PrimitiveType;

-        passCount = 1;

-        passes[0] = GrDrawTarget::kNone_StencilPass;

-    } else {

-        type = GrDrawTarget::kTriangleFan_PrimitiveType;

-        if (single_pass_path(*path, fill, *target)) {

-            passCount = 1;

-            passes[0] = GrDrawTarget::kNone_StencilPass;

-        } else {

-            switch (fill) {

-                case kInverseEvenOdd_PathFill:

-                    reverse = true;

-                    // fallthrough

-                case kEvenOdd_PathFill:

-                    passCount = 2;

-                    passes[0] = GrDrawTarget::kEvenOddStencil_StencilPass;

-                    passes[1] = GrDrawTarget::kEvenOddColor_StencilPass;

-                    break;

-

-                case kInverseWinding_PathFill:

-                    reverse = true;

-                    // fallthrough

-                case kWinding_PathFill:

-                    passes[0] = GrDrawTarget::kWindingStencil1_StencilPass;

-                    if (fGpu->supportsSingleStencilPassWinding()) {

-                        passes[1] = GrDrawTarget::kWindingColor_StencilPass;

-                        passCount = 2;

-                    } else {

-                        passes[1] = GrDrawTarget::kWindingStencil2_StencilPass;

-                        passes[2] = GrDrawTarget::kWindingColor_StencilPass;

-                        passCount = 3;

-                    }

-                    break;

-                default:

-                    GrAssert(!"Unknown path fill!");

-                    return;

-            }

-        }

-    }

-    target->setReverseFill(reverse);

-

-    GrPoint pts[4];

-

-    bool first = true;

-    int subpath = 0;

-

-    for (;;) {

-        GrPathIter::Command cmd = path->next(pts);

-        switch (cmd) {

-            case GrPathIter::kMove_Command:

-                if (!first) {

-                    subpathVertCount[subpath] = vert-subpathBase;

-                    subpathBase = vert;

-                    ++subpath;

-                }

-                *vert = pts[0];

-                vert++;

-                break;

-            case GrPathIter::kLine_Command:

-                *vert = pts[1];

-                vert++;

-                break;

-            case GrPathIter::kQuadratic_Command: {

-                generate_quadratic_points(pts[0], pts[1], pts[2],

-                                          tolSqd, &vert,

-                                          quadratic_point_count(pts, tol));

-                break;

-            }

-            case GrPathIter::kCubic_Command: {

-                generate_cubic_points(pts[0], pts[1], pts[2], pts[3],

-                                      tolSqd, &vert,

-                                      cubic_point_count(pts, tol));

-                break;

-            }

-            case GrPathIter::kClose_Command:

-                break;

-            case GrPathIter::kEnd_Command:

-                subpathVertCount[subpath] = vert-subpathBase;

-                ++subpath; // this could be only in debug

-                goto FINISHED;

-        }

-        first = false;

-    }

-FINISHED:

-    GrAssert(subpath == subpathCnt);

-    GrAssert((vert - base) <= maxPts);

-

-    if (translate) {

-        int count = vert - base;

-        for (int i = 0; i < count; i++) {

-            base[i].offset(translate->fX, translate->fY);

-        }

-    }

-

-    // arbitrary path complexity cutoff

-    bool useBounds = fill != kHairLine_PathFill &&

-                    (reverse || (vert - base) > 8);

-    GrPoint* boundsVerts = base + maxPts;

-    if (useBounds) {

-        GrRect bounds;

-        if (reverse) {

-            GrAssert(NULL != target->getRenderTarget());

-            // draw over the whole world.

-            bounds.setLTRB(0, 0,

-                           GrIntToScalar(target->getRenderTarget()->width()),

-                           GrIntToScalar(target->getRenderTarget()->height()));

-            GrMatrix vmi;

-            if (target->getViewInverse(&vmi)) {

-                vmi.mapRect(&bounds);

-            }

-        } else {

-            bounds.setBounds((GrPoint*)base, vert - base);

-        }

-        boundsVerts[0].setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight,

-                                  bounds.fBottom);

-    }

-

-    for (int p = 0; p < passCount; ++p) {

-        target->setStencilPass(passes[p]);

-        if (useBounds && (GrDrawTarget::kEvenOddColor_StencilPass == passes[p] ||

-                          GrDrawTarget::kWindingColor_StencilPass == passes[p])) {

-            target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,

-                                 maxPts, 4);

-

-        } else {

-            int baseVertex = 0;

-            for (int sp = 0; sp < subpathCnt; ++sp) {

-                target->drawNonIndexed(type,

-                                     baseVertex,

-                                     subpathVertCount[sp]);

-                baseVertex += subpathVertCount[sp];

-            }

-        }

-    }

+    fPathRenderer->drawPath(target, enabledStages, path, fill, translate);

 }

 

 ////////////////////////////////////////////////////////////////////////////////

@@ -918,8 +600,8 @@
 

     fGpu->disableState(GrDrawTarget::kClip_StateBit);

     fGpu->setAlpha(0xFF);

-    fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff,

-                       GrDrawTarget::kZero_BlendCoeff);

+    fGpu->setBlendFunc(kOne_BlendCoeff,

+                       kZero_BlendCoeff);

     fGpu->setTexture(0, texture);

 

     GrSamplerState sampler;

@@ -936,7 +618,7 @@
         return;

     }

     ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);

-    fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, VCOUNT);

+    fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);

 }

 ////////////////////////////////////////////////////////////////////////////////

 

@@ -1069,7 +751,7 @@
 #if BATCH_RECT_TO_RECT

     fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());

 #endif

-

+    fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsSingleStencilPassWinding());

 }

 

 bool GrContext::finalizeTextureKey(GrTextureKey* key,