blob: a80d789f3ff8241e0c5ff4d2b87557929baf6915 [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,
Chris Dalton42c21152018-06-13 15:28:19 -060017 const GrCCPerFlushResourceSpecs& specs)
18 : fPathParser(sk_make_sp<GrCCPathParser>(specs.fNumRenderedPaths + specs.fNumClipPaths,
19 specs.fParsingPathStats))
20 , fAtlasSpecs(specs.fAtlasSpecs)
Chris Dalton5ba36ba2018-05-09 01:08:38 -060021 , fIndexBuffer(GrCCPathProcessor::FindIndexBuffer(onFlushRP))
22 , fVertexBuffer(GrCCPathProcessor::FindVertexBuffer(onFlushRP))
23 , fInstanceBuffer(onFlushRP->makeBuffer(kVertex_GrBufferType,
Chris Dalton42c21152018-06-13 15:28:19 -060024 specs.fNumRenderedPaths * sizeof(PathInstance))) {
Chris Dalton5ba36ba2018-05-09 01:08:38 -060025 if (!fIndexBuffer) {
26 SkDebugf("WARNING: failed to allocate CCPR index buffer. No paths will be drawn.\n");
27 return;
28 }
29 if (!fVertexBuffer) {
30 SkDebugf("WARNING: failed to allocate CCPR vertex buffer. No paths will be drawn.\n");
31 return;
32 }
33 if (!fInstanceBuffer) {
34 SkDebugf("WARNING: failed to allocate CCPR instance buffer. No paths will be drawn.\n");
35 return;
36 }
37 fPathInstanceData = static_cast<PathInstance*>(fInstanceBuffer->map());
38 SkASSERT(fPathInstanceData);
Chris Dalton42c21152018-06-13 15:28:19 -060039 SkDEBUGCODE(fPathInstanceBufferCount = specs.fNumRenderedPaths);
Chris Dalton5ba36ba2018-05-09 01:08:38 -060040}
41
Chris Dalton42c21152018-06-13 15:28:19 -060042GrCCAtlas* GrCCPerFlushResources::renderPathInAtlas(const SkIRect& clipIBounds, const SkMatrix& m,
43 const SkPath& path, SkRect* devBounds,
44 SkRect* devBounds45, int16_t* atlasOffsetX,
45 int16_t* atlasOffsetY) {
Chris Dalton5ba36ba2018-05-09 01:08:38 -060046 SkASSERT(this->isMapped());
47 SkIRect devIBounds;
48 fPathParser->parsePath(m, path, devBounds, devBounds45);
49 devBounds->roundOut(&devIBounds);
Chris Dalton42c21152018-06-13 15:28:19 -060050 return this->placeParsedPathInAtlas(clipIBounds, devIBounds, atlasOffsetX, atlasOffsetY);
Chris Dalton5ba36ba2018-05-09 01:08:38 -060051}
52
Chris Dalton42c21152018-06-13 15:28:19 -060053GrCCAtlas* GrCCPerFlushResources::renderDeviceSpacePathInAtlas(const SkIRect& clipIBounds,
Chris Daltondaef06a2018-05-23 17:11:09 -060054 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);
Chris Dalton42c21152018-06-13 15:28:19 -060060 return this->placeParsedPathInAtlas(clipIBounds, devPathIBounds, atlasOffsetX, atlasOffsetY);
Chris Dalton5ba36ba2018-05-09 01:08:38 -060061}
62
Chris Dalton42c21152018-06-13 15:28:19 -060063GrCCAtlas* GrCCPerFlushResources::placeParsedPathInAtlas(const SkIRect& clipIBounds,
Chris Dalton5ba36ba2018-05-09 01:08:38 -060064 const SkIRect& pathIBounds,
65 int16_t* atlasOffsetX,
66 int16_t* atlasOffsetY) {
67 using ScissorMode = GrCCPathParser::ScissorMode;
68 ScissorMode scissorMode;
69 SkIRect clippedPathIBounds;
70 if (clipIBounds.contains(pathIBounds)) {
71 clippedPathIBounds = pathIBounds;
72 scissorMode = ScissorMode::kNonScissored;
73 } else if (clippedPathIBounds.intersect(clipIBounds, pathIBounds)) {
74 scissorMode = ScissorMode::kScissored;
75 } else {
76 fPathParser->discardParsedPath();
77 return nullptr;
78 }
79
80 SkIPoint16 atlasLocation;
81 int h = clippedPathIBounds.height(), w = clippedPathIBounds.width();
82 if (fAtlases.empty() || !fAtlases.back().addRect(w, h, &atlasLocation)) {
83 if (!fAtlases.empty()) {
84 // The atlas is out of room and can't grow any bigger.
85 auto coverageCountBatchID = fPathParser->closeCurrentBatch();
86 fAtlases.back().setCoverageCountBatchID(coverageCountBatchID);
87 }
Chris Dalton42c21152018-06-13 15:28:19 -060088 fAtlases.emplace_back(fAtlasSpecs);
Chris Dalton5ba36ba2018-05-09 01:08:38 -060089 SkAssertResult(fAtlases.back().addRect(w, h, &atlasLocation));
90 }
91
92 *atlasOffsetX = atlasLocation.x() - static_cast<int16_t>(clippedPathIBounds.left());
93 *atlasOffsetY = atlasLocation.y() - static_cast<int16_t>(clippedPathIBounds.top());
94 fPathParser->saveParsedPath(scissorMode, clippedPathIBounds, *atlasOffsetX, *atlasOffsetY);
95
96 return &fAtlases.back();
97}
98
99bool GrCCPerFlushResources::finalize(GrOnFlushResourceProvider* onFlushRP,
100 SkTArray<sk_sp<GrRenderTargetContext>>* atlasDraws) {
101 SkASSERT(this->isMapped());
102 fInstanceBuffer->unmap();
103 fPathInstanceData = nullptr;
104
105 if (!fAtlases.empty()) {
106 auto coverageCountBatchID = fPathParser->closeCurrentBatch();
107 fAtlases.back().setCoverageCountBatchID(coverageCountBatchID);
108 }
109
110 if (!fPathParser->finalize(onFlushRP)) {
111 SkDebugf("WARNING: failed to allocate GPU buffers for CCPR. No paths will be drawn.\n");
112 return false;
113 }
114
115 // Draw the atlas(es).
116 GrTAllocator<GrCCAtlas>::Iter atlasIter(&fAtlases);
117 while (atlasIter.next()) {
118 if (auto rtc = atlasIter.get()->finalize(onFlushRP, fPathParser)) {
119 atlasDraws->push_back(std::move(rtc));
120 }
121 }
122
123 return true;
124}