Home | History | Annotate | Download | only in gl
      1 
      2 /*
      3  * Copyright 2012 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 "GrGLPath.h"
     10 #include "GrGpuGL.h"
     11 
     12 #define GPUGL static_cast<GrGpuGL*>(this->getGpu())
     13 
     14 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
     15 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(GPUGL->glInterface(), R, X)
     16 
     17 namespace {
     18 inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) {
     19     static const GrGLubyte gTable[] = {
     20         GR_GL_MOVE_TO,
     21         GR_GL_LINE_TO,
     22         GR_GL_QUADRATIC_CURVE_TO,
     23         0xFF, // conic
     24         GR_GL_CUBIC_CURVE_TO,
     25         GR_GL_CLOSE_PATH,
     26     };
     27     GR_STATIC_ASSERT(0 == SkPath::kMove_Verb);
     28     GR_STATIC_ASSERT(1 == SkPath::kLine_Verb);
     29     GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb);
     30     GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb);
     31     GR_STATIC_ASSERT(5 == SkPath::kClose_Verb);
     32 
     33     SkASSERT(verb >= 0 && (size_t)verb < GR_ARRAY_COUNT(gTable));
     34     return gTable[verb];
     35 }
     36 
     37 #ifdef SK_DEBUG
     38 inline int num_pts(SkPath::Verb verb) {
     39     static const int gTable[] = {
     40         1, // move
     41         1, // line
     42         2, // quad
     43         2, // conic
     44         3, // cubic
     45         0, // close
     46     };
     47     GR_STATIC_ASSERT(0 == SkPath::kMove_Verb);
     48     GR_STATIC_ASSERT(1 == SkPath::kLine_Verb);
     49     GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb);
     50     GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb);
     51     GR_STATIC_ASSERT(5 == SkPath::kClose_Verb);
     52 
     53     SkASSERT(verb >= 0 && (size_t)verb < GR_ARRAY_COUNT(gTable));
     54     return gTable[verb];
     55 }
     56 #endif
     57 
     58 inline GrGLenum join_to_gl_join(SkPaint::Join join) {
     59     static GrGLenum gSkJoinsToGrGLJoins[] = {
     60         GR_GL_MITER_REVERT,
     61         GR_GL_ROUND,
     62         GR_GL_BEVEL
     63     };
     64     return gSkJoinsToGrGLJoins[join];
     65     GR_STATIC_ASSERT(0 == SkPaint::kMiter_Join);
     66     GR_STATIC_ASSERT(1 == SkPaint::kRound_Join);
     67     GR_STATIC_ASSERT(2 == SkPaint::kBevel_Join);
     68     GR_STATIC_ASSERT(GR_ARRAY_COUNT(gSkJoinsToGrGLJoins) == SkPaint::kJoinCount);
     69 }
     70 
     71 inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) {
     72     static GrGLenum gSkCapsToGrGLCaps[] = {
     73         GR_GL_FLAT,
     74         GR_GL_ROUND,
     75         GR_GL_SQUARE
     76     };
     77     return gSkCapsToGrGLCaps[cap];
     78     GR_STATIC_ASSERT(0 == SkPaint::kButt_Cap);
     79     GR_STATIC_ASSERT(1 == SkPaint::kRound_Cap);
     80     GR_STATIC_ASSERT(2 == SkPaint::kSquare_Cap);
     81     GR_STATIC_ASSERT(GR_ARRAY_COUNT(gSkCapsToGrGLCaps) == SkPaint::kCapCount);
     82 }
     83 
     84 }
     85 
     86 static const bool kIsWrapped = false; // The constructor creates the GL path object.
     87 
     88 GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path, const SkStrokeRec& stroke)
     89     : INHERITED(gpu, kIsWrapped, path, stroke) {
     90 #ifndef SK_SCALAR_IS_FLOAT
     91     GrCrash("Assumes scalar is float.");
     92 #endif
     93     SkASSERT(!path.isEmpty());
     94 
     95     GL_CALL_RET(fPathID, GenPaths(1));
     96 
     97     SkSTArray<16, GrGLubyte, true> pathCommands;
     98     SkSTArray<16, SkPoint, true> pathPoints;
     99 
    100     int verbCnt = fSkPath.countVerbs();
    101     int pointCnt = fSkPath.countPoints();
    102     pathCommands.resize_back(verbCnt);
    103     pathPoints.resize_back(pointCnt);
    104 
    105     // TODO: Direct access to path points since we could pass them on directly.
    106     fSkPath.getPoints(&pathPoints[0], pointCnt);
    107     fSkPath.getVerbs(&pathCommands[0], verbCnt);
    108 
    109     SkDEBUGCODE(int numPts = 0);
    110     for (int i = 0; i < verbCnt; ++i) {
    111         SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]);
    112         pathCommands[i] = verb_to_gl_path_cmd(v);
    113         SkDEBUGCODE(numPts += num_pts(v));
    114     }
    115     SkASSERT(pathPoints.count() == numPts);
    116 
    117     GL_CALL(PathCommands(fPathID,
    118                          verbCnt, &pathCommands[0],
    119                          2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]));
    120 
    121     if (stroke.needToApply()) {
    122         GL_CALL(PathParameterf(fPathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth())));
    123         GL_CALL(PathParameterf(fPathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter())));
    124         GrGLenum join = join_to_gl_join(stroke.getJoin());
    125         GL_CALL(PathParameteri(fPathID, GR_GL_PATH_JOIN_STYLE, join));
    126         GrGLenum cap = cap_to_gl_cap(stroke.getCap());
    127         GL_CALL(PathParameteri(fPathID, GR_GL_PATH_INITIAL_END_CAP, cap));
    128         GL_CALL(PathParameteri(fPathID, GR_GL_PATH_TERMINAL_END_CAP, cap));
    129 
    130         // FIXME: try to account for stroking, without rasterizing the stroke.
    131         fBounds.outset(SkScalarToFloat(stroke.getWidth()), SkScalarToFloat(stroke.getWidth()));
    132     }
    133 }
    134 
    135 GrGLPath::~GrGLPath() {
    136     this->release();
    137 }
    138 
    139 void GrGLPath::onRelease() {
    140     if (0 != fPathID && !this->isWrapped()) {
    141         GL_CALL(DeletePaths(fPathID, 1));
    142         fPathID = 0;
    143     }
    144 
    145     INHERITED::onRelease();
    146 }
    147 
    148 void GrGLPath::onAbandon() {
    149     fPathID = 0;
    150 
    151     INHERITED::onAbandon();
    152 }
    153