1 
2 /*
3  * Copyright 2014 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 "GrGLPathRange.h"
10 #include "GrGLPath.h"
11 #include "GrGLPathRendering.h"
12 #include "GrGLGpu.h"
13 
GrGLPathRange(GrGLGpu * gpu,PathGenerator * pathGenerator,const GrStrokeInfo & stroke)14 GrGLPathRange::GrGLPathRange(GrGLGpu* gpu, PathGenerator* pathGenerator, const GrStrokeInfo& stroke)
15     : INHERITED(gpu, pathGenerator),
16       fStroke(stroke),
17       fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
18       fGpuMemorySize(0) {
19     this->init();
20     this->registerWithCache();
21 }
22 
GrGLPathRange(GrGLGpu * gpu,GrGLuint basePathID,int numPaths,size_t gpuMemorySize,const GrStrokeInfo & stroke)23 GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
24                              GrGLuint basePathID,
25                              int numPaths,
26                              size_t gpuMemorySize,
27                              const GrStrokeInfo& stroke)
28     : INHERITED(gpu, numPaths),
29       fStroke(stroke),
30       fBasePathID(basePathID),
31       fGpuMemorySize(gpuMemorySize) {
32     this->init();
33     this->registerWithCache();
34 }
35 
init()36 void GrGLPathRange::init() {
37     // Must force fill:
38     // * dashing: NVPR stroke dashing is different to Skia.
39     // * end caps: NVPR stroking degenerate contours with end caps is different to Skia.
40     bool forceFill = fStroke.isDashed() ||
41             (fStroke.needToApply() && fStroke.getCap() != SkPaint::kButt_Cap);
42 
43     if (forceFill) {
44         fShouldStroke = false;
45         fShouldFill = true;
46     } else {
47         fShouldStroke = fStroke.needToApply();
48         fShouldFill = fStroke.isFillStyle() ||
49                 fStroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
50     }
51 }
52 
onInitPath(int index,const SkPath & origSkPath) const53 void GrGLPathRange::onInitPath(int index, const SkPath& origSkPath) const {
54     GrGLGpu* gpu = static_cast<GrGLGpu*>(this->getGpu());
55     if (nullptr == gpu) {
56         return;
57     }
58 
59     // Make sure the path at this index hasn't been initted already.
60     SkDEBUGCODE(
61         GrGLboolean isPath;
62         GR_GL_CALL_RET(gpu->glInterface(), isPath, IsPath(fBasePathID + index)));
63     SkASSERT(GR_GL_FALSE == isPath);
64 
65     if (origSkPath.isEmpty()) {
66         GrGLPath::InitPathObjectEmptyPath(gpu, fBasePathID + index);
67     } else if (fShouldStroke) {
68         GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, origSkPath);
69         GrGLPath::InitPathObjectStroke(gpu, fBasePathID + index, fStroke);
70     } else {
71         const SkPath* skPath = &origSkPath;
72         SkTLazy<SkPath> tmpPath;
73         const GrStrokeInfo* stroke = &fStroke;
74         GrStrokeInfo tmpStroke(SkStrokeRec::kFill_InitStyle);
75 
76         // Dashing must be applied to the path. However, if dashing is present,
77         // we must convert all the paths to fills. The GrStrokeInfo::applyDash leaves
78         // simple paths as strokes but converts other paths to fills.
79         // Thus we must stroke the strokes here, so that all paths in the
80         // path range are using the same style.
81         if (fStroke.isDashed()) {
82             if (!stroke->applyDashToPath(tmpPath.init(), &tmpStroke, *skPath)) {
83                 return;
84             }
85             skPath = tmpPath.get();
86             stroke = &tmpStroke;
87         }
88         if (stroke->needToApply()) {
89             if (!tmpPath.isValid()) {
90                 tmpPath.init();
91             }
92             if (!stroke->applyToPath(tmpPath.get(), *tmpPath.get())) {
93                 return;
94             }
95         }
96         GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, *skPath);
97     }
98     // TODO: Use a better approximation for the individual path sizes.
99     fGpuMemorySize += 100;
100 }
101 
onRelease()102 void GrGLPathRange::onRelease() {
103     SkASSERT(this->getGpu());
104 
105     if (0 != fBasePathID && this->shouldFreeResources()) {
106         static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
107                                                                               this->getNumPaths());
108         fBasePathID = 0;
109     }
110 
111     INHERITED::onRelease();
112 }
113 
onAbandon()114 void GrGLPathRange::onAbandon() {
115     fBasePathID = 0;
116 
117     INHERITED::onAbandon();
118 }
119