1b85a0aab6905af8b329539b7573a7555b727d5e5cdalton/*
2b85a0aab6905af8b329539b7573a7555b727d5e5cdalton * Copyright 2014 Google Inc.
3b85a0aab6905af8b329539b7573a7555b727d5e5cdalton *
4b85a0aab6905af8b329539b7573a7555b727d5e5cdalton * Use of this source code is governed by a BSD-style license that can be
5b85a0aab6905af8b329539b7573a7555b727d5e5cdalton * found in the LICENSE file.
6b85a0aab6905af8b329539b7573a7555b727d5e5cdalton */
7b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
8b85a0aab6905af8b329539b7573a7555b727d5e5cdalton#include "GrGLPathRange.h"
9b85a0aab6905af8b329539b7573a7555b727d5e5cdalton#include "GrGLPath.h"
10c7103a104fdc7150b4e3c0d3efc42735ad359616cdalton#include "GrGLPathRendering.h"
1139edf7664f50b6c890b933b5bbed67a8735b349bjvanverth#include "GrGLGpu.h"
12b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
136663acff010ce752e4bf778da81fa97448c9db31bsalomonGrGLPathRange::GrGLPathRange(GrGLGpu* gpu, PathGenerator* pathGenerator, const GrStyle& style)
1450b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen    : INHERITED(gpu, pathGenerator),
156663acff010ce752e4bf778da81fa97448c9db31bsalomon      fStyle(style),
16855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton      fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
17855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton      fGpuMemorySize(0) {
1850b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen    this->init();
192e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    this->registerWithCache(SkBudgeted::kYes);
20855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton}
21855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton
22861e1037017bbb7ac52ec5ebecab3a636a82a3e8bsalomonGrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
23855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton                             GrGLuint basePathID,
24855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton                             int numPaths,
25855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton                             size_t gpuMemorySize,
266663acff010ce752e4bf778da81fa97448c9db31bsalomon                             const GrStyle& style)
2750b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen    : INHERITED(gpu, numPaths),
286663acff010ce752e4bf778da81fa97448c9db31bsalomon      fStyle(style),
29855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton      fBasePathID(basePathID),
30855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton      fGpuMemorySize(gpuMemorySize) {
3150b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen    this->init();
322e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    this->registerWithCache(SkBudgeted::kYes);
33b85a0aab6905af8b329539b7573a7555b727d5e5cdalton}
34b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
3550b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunenvoid GrGLPathRange::init() {
366663acff010ce752e4bf778da81fa97448c9db31bsalomon    const SkStrokeRec& stroke = fStyle.strokeRec();
371e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen    // Must force fill:
381e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen    // * dashing: NVPR stroke dashing is different to Skia.
391e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen    // * end caps: NVPR stroking degenerate contours with end caps is different to Skia.
406663acff010ce752e4bf778da81fa97448c9db31bsalomon    bool forceFill = fStyle.pathEffect() ||
416663acff010ce752e4bf778da81fa97448c9db31bsalomon            (stroke.needToApply() && stroke.getCap() != SkPaint::kButt_Cap);
421e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen
431e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen    if (forceFill) {
4450b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen        fShouldStroke = false;
4550b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen        fShouldFill = true;
4650b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen    } else {
476663acff010ce752e4bf778da81fa97448c9db31bsalomon        fShouldStroke = stroke.needToApply();
486663acff010ce752e4bf778da81fa97448c9db31bsalomon        fShouldFill = stroke.isFillStyle() ||
496663acff010ce752e4bf778da81fa97448c9db31bsalomon                stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
5050b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen    }
5150b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen}
5250b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen
5350b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunenvoid GrGLPathRange::onInitPath(int index, const SkPath& origSkPath) const {
54861e1037017bbb7ac52ec5ebecab3a636a82a3e8bsalomon    GrGLGpu* gpu = static_cast<GrGLGpu*>(this->getGpu());
5596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == gpu) {
56b85a0aab6905af8b329539b7573a7555b727d5e5cdalton        return;
57b85a0aab6905af8b329539b7573a7555b727d5e5cdalton    }
58b85a0aab6905af8b329539b7573a7555b727d5e5cdalton    // Make sure the path at this index hasn't been initted already.
595b653577994fe298e08e5f7a5c1fa39fe53c9203kkinnunen    SkDEBUGCODE(
605b653577994fe298e08e5f7a5c1fa39fe53c9203kkinnunen        GrGLboolean isPath;
615b653577994fe298e08e5f7a5c1fa39fe53c9203kkinnunen        GR_GL_CALL_RET(gpu->glInterface(), isPath, IsPath(fBasePathID + index)));
625b653577994fe298e08e5f7a5c1fa39fe53c9203kkinnunen    SkASSERT(GR_GL_FALSE == isPath);
63b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
641e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen    if (origSkPath.isEmpty()) {
651e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen        GrGLPath::InitPathObjectEmptyPath(gpu, fBasePathID + index);
661e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen    } else if (fShouldStroke) {
671e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen        GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, origSkPath);
686663acff010ce752e4bf778da81fa97448c9db31bsalomon        GrGLPath::InitPathObjectStroke(gpu, fBasePathID + index, fStyle.strokeRec());
691e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen    } else {
701e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen        const SkPath* skPath = &origSkPath;
711e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen        SkTLazy<SkPath> tmpPath;
726663acff010ce752e4bf778da81fa97448c9db31bsalomon        if (!fStyle.isSimpleFill()) {
736663acff010ce752e4bf778da81fa97448c9db31bsalomon            SkStrokeRec::InitStyle fill;
746663acff010ce752e4bf778da81fa97448c9db31bsalomon            // The path effect must be applied to the path. However, if a path effect is present,
756663acff010ce752e4bf778da81fa97448c9db31bsalomon            // we must convert all the paths to fills. The path effect application may leave
766663acff010ce752e4bf778da81fa97448c9db31bsalomon            // simple paths as strokes but converts other paths to fills.
776663acff010ce752e4bf778da81fa97448c9db31bsalomon            // Thus we must stroke the strokes here, so that all paths in the
786663acff010ce752e4bf778da81fa97448c9db31bsalomon            // path range are using the same style.
796663acff010ce752e4bf778da81fa97448c9db31bsalomon            if (!fStyle.applyToPath(tmpPath.init(), &fill, *skPath, SK_Scalar1)) {
801e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen                return;
811e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen            }
826663acff010ce752e4bf778da81fa97448c9db31bsalomon            // We shouldn't have allowed hairlines or arbitrary path effect styles to get here
836663acff010ce752e4bf778da81fa97448c9db31bsalomon            // so after application we better have a filled path.
846663acff010ce752e4bf778da81fa97448c9db31bsalomon            SkASSERT(SkStrokeRec::kFill_InitStyle == fill);
851e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen            skPath = tmpPath.get();
866663acff010ce752e4bf778da81fa97448c9db31bsalomon
8750b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen        }
881e2913e7cb8c8122151cabd0aa6c77011253e95bkkinnunen        GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, *skPath);
8950b58e6fbcc50785ceffacb2c51b22c6e67a7ab7kkinnunen    }
90855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton    // TODO: Use a better approximation for the individual path sizes.
91855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton    fGpuMemorySize += 100;
92b85a0aab6905af8b329539b7573a7555b727d5e5cdalton}
93b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
94b85a0aab6905af8b329539b7573a7555b727d5e5cdaltonvoid GrGLPathRange::onRelease() {
9549f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(this->getGpu());
96b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
972e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    if (0 != fBasePathID) {
98861e1037017bbb7ac52ec5ebecab3a636a82a3e8bsalomon        static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
99855d83ff79c6c822b2ad653f2f890178ad0f637bcdalton                                                                              this->getNumPaths());
100b85a0aab6905af8b329539b7573a7555b727d5e5cdalton        fBasePathID = 0;
101b85a0aab6905af8b329539b7573a7555b727d5e5cdalton    }
102b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
103b85a0aab6905af8b329539b7573a7555b727d5e5cdalton    INHERITED::onRelease();
104b85a0aab6905af8b329539b7573a7555b727d5e5cdalton}
105b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
106b85a0aab6905af8b329539b7573a7555b727d5e5cdaltonvoid GrGLPathRange::onAbandon() {
107b85a0aab6905af8b329539b7573a7555b727d5e5cdalton    fBasePathID = 0;
108b85a0aab6905af8b329539b7573a7555b727d5e5cdalton
109b85a0aab6905af8b329539b7573a7555b727d5e5cdalton    INHERITED::onAbandon();
110b85a0aab6905af8b329539b7573a7555b727d5e5cdalton}
111