Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / gpu / graphite / render / TessellateWedgesRenderStep.cpp
1 /*
2  * Copyright 2022 Google LLC
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 "src/gpu/graphite/render/TessellateWedgesRenderStep.h"
9
10 #include "src/gpu/graphite/DrawGeometry.h"
11 #include "src/gpu/graphite/DrawWriter.h"
12 #include "src/gpu/graphite/render/DynamicInstancesPatchAllocator.h"
13
14 #include "src/gpu/tessellate/AffineMatrix.h"
15 #include "src/gpu/tessellate/FixedCountBufferUtils.h"
16 #include "src/gpu/tessellate/MidpointContourParser.h"
17 #include "src/gpu/tessellate/PatchWriter.h"
18
19 namespace skgpu::graphite {
20
21 namespace {
22
23 using namespace skgpu::tess;
24
25 // Only kFanPoint, no stroke params, since this is for filled wedges.
26 // No explicit curve type, since we assume infinity is supported on GPUs using graphite
27 // No color or wide color attribs, since it might always be part of the PaintParams
28 // or we'll add a color-only fast path to RenderStep later.
29 static constexpr PatchAttribs kAttribs = PatchAttribs::kFanPoint |
30                                          PatchAttribs::kPaintDepth;
31
32 using Writer = PatchWriter<DynamicInstancesPatchAllocator<FixedCountWedges>,
33                            Required<PatchAttribs::kFanPoint>,
34                            Required<PatchAttribs::kPaintDepth>>;
35
36 }  // namespace
37
38 TessellateWedgesRenderStep::TessellateWedgesRenderStep(std::string_view variantName,
39                                                        DepthStencilSettings depthStencilSettings)
40         : RenderStep("TessellateWedgesRenderStep",
41                      variantName,
42                      Flags::kRequiresMSAA |
43                      (depthStencilSettings.fDepthWriteEnabled ? Flags::kPerformsShading
44                                                               : Flags::kNone),
45                      /*uniforms=*/{},
46                      PrimitiveType::kTriangles,
47                      depthStencilSettings,
48                      /*vertexAttrs=*/  {{"resolveLevel_and_idx",
49                                          VertexAttribType::kFloat2, SkSLType::kFloat2}},
50                      /*instanceAttrs=*/{{"p01", VertexAttribType::kFloat4, SkSLType::kFloat4},
51                                         {"p23", VertexAttribType::kFloat4, SkSLType::kFloat4},
52                                         {"fanPointAttrib", VertexAttribType::kFloat2,
53                                                            SkSLType::kFloat2},
54                                         {"depth", VertexAttribType::kFloat, SkSLType::kFloat}}) {
55     SkASSERT(this->instanceStride() == PatchStride(kAttribs));
56 }
57
58 TessellateWedgesRenderStep::~TessellateWedgesRenderStep() {}
59
60 const char* TessellateWedgesRenderStep::vertexSkSL() const {
61     return "float4 devPosition = float4("
62                "middle_out_wedge(resolveLevel_and_idx.x, resolveLevel_and_idx.y, p01, p23, "
63                                 "fanPointAttrib), depth, 1.0);\n";
64 }
65
66 void TessellateWedgesRenderStep::writeVertices(DrawWriter* dw, const DrawGeometry& geom) const {
67     SkPath path = geom.shape().asPath(); // TODO: Iterate the Shape directly
68
69     BindBufferInfo fixedVertexBuffer = dw->bufferManager()->getStaticBuffer(
70             BufferType::kVertex,
71             FixedCountWedges::WriteVertexBuffer,
72             FixedCountWedges::VertexBufferSize);
73     BindBufferInfo fixedIndexBuffer = dw->bufferManager()->getStaticBuffer(
74             BufferType::kIndex,
75             FixedCountWedges::WriteIndexBuffer,
76             FixedCountWedges::IndexBufferSize);
77
78     int patchReserveCount = FixedCountWedges::PreallocCount(path.countVerbs());
79     Writer writer{kAttribs, *dw, fixedVertexBuffer, fixedIndexBuffer, patchReserveCount};
80     writer.updatePaintDepthAttrib(geom.order().depthAsFloat());
81
82     // TODO: Is it better to pre-transform on the CPU and only have a matrix uniform to compute
83     // local coords, or is it better to always transform on the GPU (less CPU usage, more
84     // uniform data to upload, dependent on push constants or storage buffers for good batching)
85
86     // Currently no additional transform is applied by the GPU.
87     writer.setShaderTransform(wangs_formula::VectorXform{});
88     // TODO: This doesn't handle perspective yet, and ideally wouldn't go through SkMatrix.
89     // It may not be relevant, though, if transforms are applied on the GPU and we only need to
90     // determine an approximate 2x2 for 'shaderXform' and Wang's formula evaluation.
91     AffineMatrix m(geom.transform().matrix().asM33());
92
93     // TODO: Essentially the same as PathWedgeTessellator::write_patches but with a different
94     // PatchWriter template.
95     // For wedges, we iterate over each contour explicitly, using a fan point position that is in
96     // the midpoint of the current contour.
97     MidpointContourParser parser{path};
98     while (parser.parseNextContour()) {
99         writer.updateFanPointAttrib(m.mapPoint(parser.currentMidpoint()));
100         skvx::float2 lastPoint = {0, 0};
101         skvx::float2 startPoint = {0, 0};
102         for (auto [verb, pts, w] : parser.currentContour()) {
103             switch (verb) {
104                 case SkPathVerb::kMove: {
105                     startPoint = lastPoint = m.map1Point(pts);
106                     break;
107                 }
108
109                 case SkPathVerb::kLine: {
110                     // Unlike curve tessellation, wedges have to handle lines as part of the patch,
111                     // effectively forming a single triangle with the fan point.
112                     auto [p0, p1] = m.map2Points(pts);
113                     writer.writeLine(p0, p1);
114                     lastPoint = p1;
115                     break;
116                 }
117
118                 case SkPathVerb::kQuad: {
119                     auto [p0, p1] = m.map2Points(pts);
120                     auto p2 = m.map1Point(pts+2);
121
122                     writer.writeQuadratic(p0, p1, p2);
123                     lastPoint = p2;
124                     break;
125                 }
126
127                 case SkPathVerb::kConic: {
128                     auto [p0, p1] = m.map2Points(pts);
129                     auto p2 = m.map1Point(pts+2);
130
131                     writer.writeConic(p0, p1, p2, *w);
132                     lastPoint = p2;
133                     break;
134                 }
135
136                 case SkPathVerb::kCubic: {
137                     auto [p0, p1] = m.map2Points(pts);
138                     auto [p2, p3] = m.map2Points(pts+2);
139
140                     writer.writeCubic(p0, p1, p2, p3);
141                     lastPoint = p3;
142                     break;
143                 }
144
145                 default: break;
146             }
147         }
148
149         // Explicitly close the contour with another line segment, which also differs from curve
150         // tessellation since that approach's triangle step automatically closes the contour.
151         if (any(lastPoint != startPoint)) {
152             writer.writeLine(lastPoint, startPoint);
153         }
154     }
155 }
156
157 void TessellateWedgesRenderStep::writeUniforms(const DrawGeometry&, SkPipelineDataGatherer*) const {
158     // Control points are pre-transformed to device space on the CPU, so no uniforms needed.
159 }
160
161 }  // namespace skgpu::graphite