aboutsummaryrefslogtreecommitdiffhomepage
path: root/gpu/src/GrPathRenderer.cpp
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-03-28 20:47:09 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-03-28 20:47:09 +0000
commit9d18b7873ce9b44f130a41e0cbd0a3df76ab9adf (patch)
tree5f5f96e33ea96bdaf6c0dc4fbb32f78db26a4642 /gpu/src/GrPathRenderer.cpp
parentcae5fba82e687d674b076b10cdc8aba46e1ac3b3 (diff)
This CL implements a tesselated path renderer, using GLU's libtess. All of the
fill modes except hairline are supported. Note that the path renderer is not enabled by default; to enable it, replace "GrCreatePathRenderer_none.cpp" with "GrCreatePathRenderer_tesselated.cpp" in skia.gyp, and run gyp_skia, and build. This change also contains a number of build fixes for Win32 (for building SampleApp on VS2008) and Mac (for my ancient Mac Pro which supports GL_EXT_framebuffer_object but not GL_ARB_framebuffer_object). Also, priorityq-heap.c was removed from the SampleApp build, since it's #included by priorityq.c (weird, I know). NB: When this change is rolled into chrome, some modifications to chromium's skia.gyp will be necessary. Review URL: http://codereview.appspot.com/4289072/ git-svn-id: http://skia.googlecode.com/svn/trunk@1012 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'gpu/src/GrPathRenderer.cpp')
-rw-r--r--gpu/src/GrPathRenderer.cpp148
1 files changed, 13 insertions, 135 deletions
diff --git a/gpu/src/GrPathRenderer.cpp b/gpu/src/GrPathRenderer.cpp
index fc3c124ee0..f226a99873 100644
--- a/gpu/src/GrPathRenderer.cpp
+++ b/gpu/src/GrPathRenderer.cpp
@@ -3,6 +3,7 @@
#include "GrPoint.h"
#include "GrDrawTarget.h"
#include "GrPathIter.h"
+#include "GrPathUtils.h"
#include "GrMemory.h"
#include "GrTexture.h"
@@ -147,127 +148,6 @@ static const GrStencilSettings gDirectToStencil = {
// Helpers for drawPath
#define STENCIL_OFF 0 // Always disable stencil (even when needed)
-static const GrScalar gTolerance = 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]);
- 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;
-
- GrPathCmd cmd;
-
- GrPoint pts[4];
- while ((cmd = path->next(pts)) != kEnd_PathCmd) {
-
- switch (cmd) {
- case kLine_PathCmd:
- pointCount += 1;
- break;
- case kQuadratic_PathCmd:
- pointCount += quadratic_point_count(pts, tol);
- break;
- case kCubic_PathCmd:
- pointCount += cubic_point_count(pts, tol);
- break;
- case kMove_PathCmd:
- pointCount += 1;
- if (!first) {
- ++(*subpaths);
- }
- break;
- default:
- break;
- }
- first = false;
- }
- return pointCount;
-}
static inline bool single_pass_path(const GrDrawTarget& target,
const GrPathIter& path,
@@ -314,7 +194,7 @@ void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target,
// stretch when mapping to screen coordinates.
GrScalar stretch = viewM.getMaxStretch();
bool useStretch = stretch > 0;
- GrScalar tol = gTolerance;
+ GrScalar tol = GrPathUtils::gTolerance;
if (!useStretch) {
// TODO: deal with perspective in some better way.
@@ -328,9 +208,7 @@ void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target,
path->rewind();
int subpathCnt;
- int maxPts = worst_case_point_count(path,
- &subpathCnt,
- tol);
+ int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
GrVertexLayout layout = 0;
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
@@ -468,15 +346,15 @@ void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target,
vert++;
break;
case kQuadratic_PathCmd: {
- generate_quadratic_points(pts[0], pts[1], pts[2],
- tolSqd, &vert,
- quadratic_point_count(pts, tol));
+ GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2],
+ tolSqd, &vert,
+ GrPathUtils::quadraticPointCount(pts, tol));
break;
}
case kCubic_PathCmd: {
- generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
- tolSqd, &vert,
- cubic_point_count(pts, tol));
+ GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
+ tolSqd, &vert,
+ GrPathUtils::cubicPointCount(pts, tol));
break;
}
case kClose_PathCmd:
@@ -563,7 +441,7 @@ void GrDefaultPathRenderer::drawPathToStencil(GrDrawTarget* target,
GrPathIter* path,
GrPathFill fill,
const GrPoint* translate) {
- GrAssert(kInverseEvenOdd_PathFill != fill);
- GrAssert(kInverseWinding_PathFill != fill);
- this->drawPathHelper(target, 0, path, fill, translate, true);
- }
+ GrAssert(kInverseEvenOdd_PathFill != fill);
+ GrAssert(kInverseWinding_PathFill != fill);
+ this->drawPathHelper(target, 0, path, fill, translate, true);
+}