blob: 3f02ac75f66f8830c581dfa067e0a69d4fa620df [file] [log] [blame]
Chris Dalton5ba36ba2018-05-09 01:08:38 -06001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrCCPerFlushResources.h"
9
10#include "GrOnFlushResourceProvider.h"
11#include "GrRenderTargetContext.h"
12#include "SkIPoint16.h"
13
14using PathInstance = GrCCPathProcessor::Instance;
15
16GrCCPerFlushResources::GrCCPerFlushResources(GrOnFlushResourceProvider* onFlushRP,
17 int numPathDraws, int numClipPaths,
18 const GrCCPathParser::PathStats& pathStats)
19 : fPathParser(sk_make_sp<GrCCPathParser>(numPathDraws + numClipPaths, pathStats))
20 , fIndexBuffer(GrCCPathProcessor::FindIndexBuffer(onFlushRP))
21 , fVertexBuffer(GrCCPathProcessor::FindVertexBuffer(onFlushRP))
22 , fInstanceBuffer(onFlushRP->makeBuffer(kVertex_GrBufferType,
23 numPathDraws * sizeof(PathInstance))) {
24 if (!fIndexBuffer) {
25 SkDebugf("WARNING: failed to allocate CCPR index buffer. No paths will be drawn.\n");
26 return;
27 }
28 if (!fVertexBuffer) {
29 SkDebugf("WARNING: failed to allocate CCPR vertex buffer. No paths will be drawn.\n");
30 return;
31 }
32 if (!fInstanceBuffer) {
33 SkDebugf("WARNING: failed to allocate CCPR instance buffer. No paths will be drawn.\n");
34 return;
35 }
36 fPathInstanceData = static_cast<PathInstance*>(fInstanceBuffer->map());
37 SkASSERT(fPathInstanceData);
38 SkDEBUGCODE(fPathInstanceBufferCount = numPathDraws);
39}
40
Chris Daltondaef06a2018-05-23 17:11:09 -060041GrCCAtlas* GrCCPerFlushResources::renderPathInAtlas(const GrCaps& caps, const SkIRect& clipIBounds,
42 const SkMatrix& m, const SkPath& path,
43 SkRect* devBounds, SkRect* devBounds45,
44 int16_t* atlasOffsetX, int16_t* atlasOffsetY) {
Chris Dalton5ba36ba2018-05-09 01:08:38 -060045 SkASSERT(this->isMapped());
46 SkIRect devIBounds;
47 fPathParser->parsePath(m, path, devBounds, devBounds45);
48 devBounds->roundOut(&devIBounds);
49 return this->placeParsedPathInAtlas(caps, clipIBounds, devIBounds, atlasOffsetX, atlasOffsetY);
50}
51
Chris Daltondaef06a2018-05-23 17:11:09 -060052GrCCAtlas* GrCCPerFlushResources::renderDeviceSpacePathInAtlas(const GrCaps& caps,
53 const SkIRect& clipIBounds,
54 const SkPath& devPath,
55 const SkIRect& devPathIBounds,
56 int16_t* atlasOffsetX,
57 int16_t* atlasOffsetY) {
Chris Dalton5ba36ba2018-05-09 01:08:38 -060058 SkASSERT(this->isMapped());
59 fPathParser->parseDeviceSpacePath(devPath);
60 return this->placeParsedPathInAtlas(caps, clipIBounds, devPathIBounds, atlasOffsetX,
61 atlasOffsetY);
62}
63
64GrCCAtlas* GrCCPerFlushResources::placeParsedPathInAtlas(const GrCaps& caps,
65 const SkIRect& clipIBounds,
66 const SkIRect& pathIBounds,
67 int16_t* atlasOffsetX,
68 int16_t* atlasOffsetY) {
69 using ScissorMode = GrCCPathParser::ScissorMode;
70 ScissorMode scissorMode;
71 SkIRect clippedPathIBounds;
72 if (clipIBounds.contains(pathIBounds)) {
73 clippedPathIBounds = pathIBounds;
74 scissorMode = ScissorMode::kNonScissored;
75 } else if (clippedPathIBounds.intersect(clipIBounds, pathIBounds)) {
76 scissorMode = ScissorMode::kScissored;
77 } else {
78 fPathParser->discardParsedPath();
79 return nullptr;
80 }
81
82 SkIPoint16 atlasLocation;
83 int h = clippedPathIBounds.height(), w = clippedPathIBounds.width();
84 if (fAtlases.empty() || !fAtlases.back().addRect(w, h, &atlasLocation)) {
85 if (!fAtlases.empty()) {
86 // The atlas is out of room and can't grow any bigger.
87 auto coverageCountBatchID = fPathParser->closeCurrentBatch();
88 fAtlases.back().setCoverageCountBatchID(coverageCountBatchID);
89 }
90 fAtlases.emplace_back(caps, SkTMax(w, h));
91 SkAssertResult(fAtlases.back().addRect(w, h, &atlasLocation));
92 }
93
94 *atlasOffsetX = atlasLocation.x() - static_cast<int16_t>(clippedPathIBounds.left());
95 *atlasOffsetY = atlasLocation.y() - static_cast<int16_t>(clippedPathIBounds.top());
96 fPathParser->saveParsedPath(scissorMode, clippedPathIBounds, *atlasOffsetX, *atlasOffsetY);
97
98 return &fAtlases.back();
99}
100
101bool GrCCPerFlushResources::finalize(GrOnFlushResourceProvider* onFlushRP,
102 SkTArray<sk_sp<GrRenderTargetContext>>* atlasDraws) {
103 SkASSERT(this->isMapped());
104 fInstanceBuffer->unmap();
105 fPathInstanceData = nullptr;
106
107 if (!fAtlases.empty()) {
108 auto coverageCountBatchID = fPathParser->closeCurrentBatch();
109 fAtlases.back().setCoverageCountBatchID(coverageCountBatchID);
110 }
111
112 if (!fPathParser->finalize(onFlushRP)) {
113 SkDebugf("WARNING: failed to allocate GPU buffers for CCPR. No paths will be drawn.\n");
114 return false;
115 }
116
117 // Draw the atlas(es).
118 GrTAllocator<GrCCAtlas>::Iter atlasIter(&fAtlases);
119 while (atlasIter.next()) {
120 if (auto rtc = atlasIter.get()->finalize(onFlushRP, fPathParser)) {
121 atlasDraws->push_back(std::move(rtc));
122 }
123 }
124
125 return true;
126}