Chromium Code Reviews| Index: src/gpu/gl/GrGLPath.cpp |
| diff --git a/src/gpu/gl/GrGLPath.cpp b/src/gpu/gl/GrGLPath.cpp |
| index 07fdfd687a2d900a98c6b6b3d18c13d6258195f2..abbd12798de180470d3446d524faf8ec8c4fa8ad 100644 |
| --- a/src/gpu/gl/GrGLPath.cpp |
| +++ b/src/gpu/gl/GrGLPath.cpp |
| @@ -16,13 +16,14 @@ inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) { |
| GR_GL_MOVE_TO, |
| GR_GL_LINE_TO, |
| GR_GL_QUADRATIC_CURVE_TO, |
| - 0xFF, // conic |
| + GR_GL_CONIC_CURVE_TO, |
| GR_GL_CUBIC_CURVE_TO, |
| GR_GL_CLOSE_PATH, |
| }; |
| GR_STATIC_ASSERT(0 == SkPath::kMove_Verb); |
| GR_STATIC_ASSERT(1 == SkPath::kLine_Verb); |
| GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb); |
| + GR_STATIC_ASSERT(3 == SkPath::kConic_Verb); |
| GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb); |
| GR_STATIC_ASSERT(5 == SkPath::kClose_Verb); |
| @@ -31,18 +32,19 @@ inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) { |
| } |
| #ifdef SK_DEBUG |
| -inline int num_pts(SkPath::Verb verb) { |
| +inline int num_coords(SkPath::Verb verb) { |
| static const int gTable[] = { |
| - 1, // move |
| - 1, // line |
| - 2, // quad |
| - 2, // conic |
| - 3, // cubic |
| + 2, // move |
| + 2, // line |
| + 4, // quad |
| + 5, // conic |
| + 6, // cubic |
| 0, // close |
| }; |
| GR_STATIC_ASSERT(0 == SkPath::kMove_Verb); |
| GR_STATIC_ASSERT(1 == SkPath::kLine_Verb); |
| GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb); |
| + GR_STATIC_ASSERT(3 == SkPath::kConic_Verb); |
| GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb); |
| GR_STATIC_ASSERT(5 == SkPath::kClose_Verb); |
| @@ -77,6 +79,13 @@ inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) { |
| GR_STATIC_ASSERT(SK_ARRAY_COUNT(gSkCapsToGrGLCaps) == SkPaint::kCapCount); |
| } |
| +inline void points_to_coords(const SkPoint points[], size_t first_point, size_t amount, |
| + GrGLfloat coords[]) { |
| + for (size_t i = 0; i < amount; ++i) { |
| + coords[i * 2] = SkScalarToFloat(points[first_point + i].fX); |
| + coords[i * 2 + 1] = SkScalarToFloat(points[first_point + i].fY); |
| + } |
| +} |
| } |
| static const bool kIsWrapped = false; // The constructor creates the GL path object. |
| @@ -86,29 +95,77 @@ void GrGLPath::InitPathObject(GrGpuGL* gpu, |
| const SkPath& skPath, |
| const SkStrokeRec& stroke) { |
| if (!skPath.isEmpty()) { |
| - SkSTArray<16, GrGLubyte, true> pathCommands; |
| - SkSTArray<16, SkPoint, true> pathPoints; |
| - |
| int verbCnt = skPath.countVerbs(); |
| int pointCnt = skPath.countPoints(); |
| - pathCommands.resize_back(verbCnt); |
| - pathPoints.resize_back(pointCnt); |
| - |
| - // TODO: Direct access to path points since we could pass them on directly. |
| - skPath.getPoints(&pathPoints[0], pointCnt); |
| - skPath.getVerbs(&pathCommands[0], verbCnt); |
| - |
| - SkDEBUGCODE(int numPts = 0); |
| - for (int i = 0; i < verbCnt; ++i) { |
| - SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]); |
| - pathCommands[i] = verb_to_gl_path_cmd(v); |
| - SkDEBUGCODE(numPts += num_pts(v)); |
| + int minCoordCnt = pointCnt * 2; |
| + |
| + SkSTArray<16, GrGLubyte, true> pathCommands(verbCnt); |
| + SkSTArray<16, GrGLfloat, true> pathCoords(minCoordCnt); |
| + |
| + SkDEBUGCODE(int numCoords = 0); |
| + |
| + if ((skPath.getSegmentMasks() & SkPath::kConic_SegmentMask) == 0) { |
| + // This branch does type punning, converting SkPoint* to GrGLfloat*. |
| + SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(GrGLfloat) * 2, sk_point_not_two_floats); |
| + // This branch does not convert with SkScalarToFloat. |
| +#ifndef SK_SCALAR_IS_FLOAT |
|
bsalomon
2014/11/19 16:53:33
There is some interest in scalar=double. I suppose
|
| +#error Need SK_SCALAR_IS_FLOAT. |
| +#endif |
| + pathCommands.resize_back(verbCnt); |
| + pathCoords.resize_back(minCoordCnt); |
| + skPath.getPoints(reinterpret_cast<SkPoint*>(&pathCoords[0]), pointCnt); |
| + skPath.getVerbs(&pathCommands[0], verbCnt); |
| + for (int i = 0; i < verbCnt; ++i) { |
| + SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]); |
| + pathCommands[i] = verb_to_gl_path_cmd(v); |
| + SkDEBUGCODE(numCoords += num_coords(v)); |
| + } |
| + } else { |
| + SkPoint points[4]; |
| + SkPath::RawIter iter(skPath); |
| + SkPath::Verb verb; |
| + while ((verb = iter.next(points)) != SkPath::kDone_Verb) { |
| + pathCommands.push_back(verb_to_gl_path_cmd(verb)); |
| + GrGLfloat coords[6]; |
| + int coordsForVerb; |
| + switch (verb) { |
| + case SkPath::kMove_Verb: |
| + points_to_coords(points, 0, 1, coords); |
| + coordsForVerb = 2; |
| + break; |
| + case SkPath::kLine_Verb: |
| + points_to_coords(points, 1, 1, coords); |
| + coordsForVerb = 2; |
| + break; |
| + case SkPath::kConic_Verb: |
| + points_to_coords(points, 1, 2, coords); |
| + coords[4] = SkScalarToFloat(iter.conicWeight()); |
| + coordsForVerb = 5; |
| + break; |
| + case SkPath::kQuad_Verb: |
| + points_to_coords(points, 1, 2, coords); |
| + coordsForVerb = 4; |
| + break; |
| + case SkPath::kCubic_Verb: |
| + points_to_coords(points, 1, 3, coords); |
| + coordsForVerb = 6; |
| + break; |
| + case SkPath::kClose_Verb: |
| + continue; |
| + default: |
| + SkASSERT(false); // Not reached. |
| + continue; |
| + } |
| + SkDEBUGCODE(numCoords += num_coords(verb)); |
| + pathCoords.push_back_n(coordsForVerb, coords); |
| + } |
| } |
| - SkASSERT(pathPoints.count() == numPts); |
| - GR_GL_CALL(gpu->glInterface(), |
| - PathCommands(pathID, verbCnt, &pathCommands[0], |
| - 2 * pointCnt, GR_GL_FLOAT, &pathPoints[0])); |
| + SkASSERT(verbCnt == pathCommands.count()); |
| + SkASSERT(numCoords == pathCoords.count()); |
| + |
| + GR_GL_CALL(gpu->glInterface(), PathCommands(pathID, pathCommands.count(), &pathCommands[0], |
| + pathCoords.count(), GR_GL_FLOAT, &pathCoords[0])); |
| } else { |
| GR_GL_CALL(gpu->glInterface(), PathCommands(pathID, 0, NULL, 0, GR_GL_FLOAT, NULL)); |
| } |