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 < SK_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 < SK_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(SK_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(SK_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     SkASSERT(!path.isEmpty());
     91 
     92     fPathID = gpu->createGLPathObject();
     93 
     94     SkSTArray<16, GrGLubyte, true> pathCommands;
     95     SkSTArray<16, SkPoint, true> pathPoints;
     96 
     97     int verbCnt = fSkPath.countVerbs();
     98     int pointCnt = fSkPath.countPoints();
     99     pathCommands.resize_back(verbCnt);
    100     pathPoints.resize_back(pointCnt);
    101 
    102     // TODO: Direct access to path points since we could pass them on directly.
    103     fSkPath.getPoints(&pathPoints[0], pointCnt);
    104     fSkPath.getVerbs(&pathCommands[0], verbCnt);
    105 
    106     SkDEBUGCODE(int numPts = 0);
    107     for (int i = 0; i < verbCnt; ++i) {
    108         SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]);
    109         pathCommands[i] = verb_to_gl_path_cmd(v);
    110         SkDEBUGCODE(numPts += num_pts(v));
    111     }
    112     SkASSERT(pathPoints.count() == numPts);
    113 
    114     GL_CALL(PathCommands(fPathID,
    115                          verbCnt, &pathCommands[0],
    116                          2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]));
    117 
    118     if (stroke.needToApply()) {
    119         GL_CALL(PathParameterf(fPathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth())));
    120         GL_CALL(PathParameterf(fPathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter())));
    121         GrGLenum join = join_to_gl_join(stroke.getJoin());
    122         GL_CALL(PathParameteri(fPathID, GR_GL_PATH_JOIN_STYLE, join));
    123         GrGLenum cap = cap_to_gl_cap(stroke.getCap());
    124         GL_CALL(PathParameteri(fPathID, GR_GL_PATH_INITIAL_END_CAP, cap));
    125         GL_CALL(PathParameteri(fPathID, GR_GL_PATH_TERMINAL_END_CAP, cap));
    126 
    127         // FIXME: try to account for stroking, without rasterizing the stroke.
    128         fBounds.outset(SkScalarToFloat(stroke.getWidth()), SkScalarToFloat(stroke.getWidth()));
    129     }
    130 }
    131 
    132 GrGLPath::~GrGLPath() {
    133     this->release();
    134 }
    135 
    136 void GrGLPath::onRelease() {
    137     if (0 != fPathID && !this->isWrapped()) {
    138         static_cast<GrGpuGL*>(this->getGpu())->deleteGLPathObject(fPathID);
    139         fPathID = 0;
    140     }
    141 
    142     INHERITED::onRelease();
    143 }
    144 
    145 void GrGLPath::onAbandon() {
    146     fPathID = 0;
    147 
    148     INHERITED::onAbandon();
    149 }
    150