1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGLPath.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,149 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2012 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 +#include "GrGLPath.h" 1.13 +#include "GrGpuGL.h" 1.14 + 1.15 +#define GPUGL static_cast<GrGpuGL*>(this->getGpu()) 1.16 + 1.17 +#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X) 1.18 +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(GPUGL->glInterface(), R, X) 1.19 + 1.20 +namespace { 1.21 +inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) { 1.22 + static const GrGLubyte gTable[] = { 1.23 + GR_GL_MOVE_TO, 1.24 + GR_GL_LINE_TO, 1.25 + GR_GL_QUADRATIC_CURVE_TO, 1.26 + 0xFF, // conic 1.27 + GR_GL_CUBIC_CURVE_TO, 1.28 + GR_GL_CLOSE_PATH, 1.29 + }; 1.30 + GR_STATIC_ASSERT(0 == SkPath::kMove_Verb); 1.31 + GR_STATIC_ASSERT(1 == SkPath::kLine_Verb); 1.32 + GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb); 1.33 + GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb); 1.34 + GR_STATIC_ASSERT(5 == SkPath::kClose_Verb); 1.35 + 1.36 + SkASSERT(verb >= 0 && (size_t)verb < GR_ARRAY_COUNT(gTable)); 1.37 + return gTable[verb]; 1.38 +} 1.39 + 1.40 +#ifdef SK_DEBUG 1.41 +inline int num_pts(SkPath::Verb verb) { 1.42 + static const int gTable[] = { 1.43 + 1, // move 1.44 + 1, // line 1.45 + 2, // quad 1.46 + 2, // conic 1.47 + 3, // cubic 1.48 + 0, // close 1.49 + }; 1.50 + GR_STATIC_ASSERT(0 == SkPath::kMove_Verb); 1.51 + GR_STATIC_ASSERT(1 == SkPath::kLine_Verb); 1.52 + GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb); 1.53 + GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb); 1.54 + GR_STATIC_ASSERT(5 == SkPath::kClose_Verb); 1.55 + 1.56 + SkASSERT(verb >= 0 && (size_t)verb < GR_ARRAY_COUNT(gTable)); 1.57 + return gTable[verb]; 1.58 +} 1.59 +#endif 1.60 + 1.61 +inline GrGLenum join_to_gl_join(SkPaint::Join join) { 1.62 + static GrGLenum gSkJoinsToGrGLJoins[] = { 1.63 + GR_GL_MITER_REVERT, 1.64 + GR_GL_ROUND, 1.65 + GR_GL_BEVEL 1.66 + }; 1.67 + return gSkJoinsToGrGLJoins[join]; 1.68 + GR_STATIC_ASSERT(0 == SkPaint::kMiter_Join); 1.69 + GR_STATIC_ASSERT(1 == SkPaint::kRound_Join); 1.70 + GR_STATIC_ASSERT(2 == SkPaint::kBevel_Join); 1.71 + GR_STATIC_ASSERT(GR_ARRAY_COUNT(gSkJoinsToGrGLJoins) == SkPaint::kJoinCount); 1.72 +} 1.73 + 1.74 +inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) { 1.75 + static GrGLenum gSkCapsToGrGLCaps[] = { 1.76 + GR_GL_FLAT, 1.77 + GR_GL_ROUND, 1.78 + GR_GL_SQUARE 1.79 + }; 1.80 + return gSkCapsToGrGLCaps[cap]; 1.81 + GR_STATIC_ASSERT(0 == SkPaint::kButt_Cap); 1.82 + GR_STATIC_ASSERT(1 == SkPaint::kRound_Cap); 1.83 + GR_STATIC_ASSERT(2 == SkPaint::kSquare_Cap); 1.84 + GR_STATIC_ASSERT(GR_ARRAY_COUNT(gSkCapsToGrGLCaps) == SkPaint::kCapCount); 1.85 +} 1.86 + 1.87 +} 1.88 + 1.89 +static const bool kIsWrapped = false; // The constructor creates the GL path object. 1.90 + 1.91 +GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path, const SkStrokeRec& stroke) 1.92 + : INHERITED(gpu, kIsWrapped, path, stroke) { 1.93 + SkASSERT(!path.isEmpty()); 1.94 + 1.95 + GL_CALL_RET(fPathID, GenPaths(1)); 1.96 + 1.97 + SkSTArray<16, GrGLubyte, true> pathCommands; 1.98 + SkSTArray<16, SkPoint, true> pathPoints; 1.99 + 1.100 + int verbCnt = fSkPath.countVerbs(); 1.101 + int pointCnt = fSkPath.countPoints(); 1.102 + pathCommands.resize_back(verbCnt); 1.103 + pathPoints.resize_back(pointCnt); 1.104 + 1.105 + // TODO: Direct access to path points since we could pass them on directly. 1.106 + fSkPath.getPoints(&pathPoints[0], pointCnt); 1.107 + fSkPath.getVerbs(&pathCommands[0], verbCnt); 1.108 + 1.109 + SkDEBUGCODE(int numPts = 0); 1.110 + for (int i = 0; i < verbCnt; ++i) { 1.111 + SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]); 1.112 + pathCommands[i] = verb_to_gl_path_cmd(v); 1.113 + SkDEBUGCODE(numPts += num_pts(v)); 1.114 + } 1.115 + SkASSERT(pathPoints.count() == numPts); 1.116 + 1.117 + GL_CALL(PathCommands(fPathID, 1.118 + verbCnt, &pathCommands[0], 1.119 + 2 * pointCnt, GR_GL_FLOAT, &pathPoints[0])); 1.120 + 1.121 + if (stroke.needToApply()) { 1.122 + GL_CALL(PathParameterf(fPathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth()))); 1.123 + GL_CALL(PathParameterf(fPathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter()))); 1.124 + GrGLenum join = join_to_gl_join(stroke.getJoin()); 1.125 + GL_CALL(PathParameteri(fPathID, GR_GL_PATH_JOIN_STYLE, join)); 1.126 + GrGLenum cap = cap_to_gl_cap(stroke.getCap()); 1.127 + GL_CALL(PathParameteri(fPathID, GR_GL_PATH_INITIAL_END_CAP, cap)); 1.128 + GL_CALL(PathParameteri(fPathID, GR_GL_PATH_TERMINAL_END_CAP, cap)); 1.129 + 1.130 + // FIXME: try to account for stroking, without rasterizing the stroke. 1.131 + fBounds.outset(SkScalarToFloat(stroke.getWidth()), SkScalarToFloat(stroke.getWidth())); 1.132 + } 1.133 +} 1.134 + 1.135 +GrGLPath::~GrGLPath() { 1.136 + this->release(); 1.137 +} 1.138 + 1.139 +void GrGLPath::onRelease() { 1.140 + if (0 != fPathID && !this->isWrapped()) { 1.141 + GL_CALL(DeletePaths(fPathID, 1)); 1.142 + fPathID = 0; 1.143 + } 1.144 + 1.145 + INHERITED::onRelease(); 1.146 +} 1.147 + 1.148 +void GrGLPath::onAbandon() { 1.149 + fPathID = 0; 1.150 + 1.151 + INHERITED::onAbandon(); 1.152 +}