xref: /aosp_15_r20/external/skia/src/gpu/graphite/render/GraphiteVertexFiller.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2023 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkM44.h"
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkVx.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkZip.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/AtlasTypes.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/BufferWriter.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/DrawWriter.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/geom/Rect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/geom/Transform_graphite.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/gpu/Glyph.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/gpu/VertexFiller.h"
21*c8dee2aaSAndroid Build Coastguard Worker 
22*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
23*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker namespace sktext::gpu {
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker struct AtlasPt {
28*c8dee2aaSAndroid Build Coastguard Worker     uint16_t u;
29*c8dee2aaSAndroid Build Coastguard Worker     uint16_t v;
30*c8dee2aaSAndroid Build Coastguard Worker };
31*c8dee2aaSAndroid Build Coastguard Worker 
fillInstanceData(skgpu::graphite::DrawWriter * dw,int offset,int count,unsigned short flags,skvx::uint2 ssboIndex,SkSpan<const Glyph * > glyphs,SkScalar depth) const32*c8dee2aaSAndroid Build Coastguard Worker void VertexFiller::fillInstanceData(skgpu::graphite::DrawWriter* dw,
33*c8dee2aaSAndroid Build Coastguard Worker                                     int offset, int count,
34*c8dee2aaSAndroid Build Coastguard Worker                                     unsigned short flags,
35*c8dee2aaSAndroid Build Coastguard Worker                                     skvx::uint2 ssboIndex,
36*c8dee2aaSAndroid Build Coastguard Worker                                     SkSpan<const Glyph*> glyphs,
37*c8dee2aaSAndroid Build Coastguard Worker                                     SkScalar depth) const {
38*c8dee2aaSAndroid Build Coastguard Worker     auto quadData = [&]() {
39*c8dee2aaSAndroid Build Coastguard Worker         return SkMakeZip(glyphs.subspan(offset, count),
40*c8dee2aaSAndroid Build Coastguard Worker                          fLeftTop.subspan(offset, count));
41*c8dee2aaSAndroid Build Coastguard Worker     };
42*c8dee2aaSAndroid Build Coastguard Worker 
43*c8dee2aaSAndroid Build Coastguard Worker     skgpu::graphite::DrawWriter::Instances instances{*dw, {}, {}, 4};
44*c8dee2aaSAndroid Build Coastguard Worker     instances.reserve(count);
45*c8dee2aaSAndroid Build Coastguard Worker     // Need to send width, height, uvPos, xyPos, and strikeToSourceScale
46*c8dee2aaSAndroid Build Coastguard Worker     // pre-transform coords = (s*w*b_x + t_x, s*h*b_y + t_y)
47*c8dee2aaSAndroid Build Coastguard Worker     // where (b_x, b_y) are the vertexID coords
48*c8dee2aaSAndroid Build Coastguard Worker     for (auto [glyph, leftTop]: quadData()) {
49*c8dee2aaSAndroid Build Coastguard Worker         auto[al, at, ar, ab] = glyph->fAtlasLocator.getUVs();
50*c8dee2aaSAndroid Build Coastguard Worker         instances.append(1) << AtlasPt{uint16_t(ar-al), uint16_t(ab-at)}
51*c8dee2aaSAndroid Build Coastguard Worker                             << AtlasPt{uint16_t(al & 0x1fff), at}
52*c8dee2aaSAndroid Build Coastguard Worker                             << leftTop << /*index=*/uint16_t(al >> 13) << flags
53*c8dee2aaSAndroid Build Coastguard Worker                             << 1.0f
54*c8dee2aaSAndroid Build Coastguard Worker                             << depth << ssboIndex;
55*c8dee2aaSAndroid Build Coastguard Worker     }
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker using Rect = skgpu::graphite::Rect;
59*c8dee2aaSAndroid Build Coastguard Worker using Transform = skgpu::graphite::Transform;
60*c8dee2aaSAndroid Build Coastguard Worker 
boundsAndDeviceMatrix(const Transform & localToDevice,SkPoint drawOrigin) const61*c8dee2aaSAndroid Build Coastguard Worker std::tuple<Rect, Transform> VertexFiller::boundsAndDeviceMatrix(const Transform& localToDevice,
62*c8dee2aaSAndroid Build Coastguard Worker                                                                 SkPoint drawOrigin) const {
63*c8dee2aaSAndroid Build Coastguard Worker     // The baked-in matrix differs from the current localToDevice by a translation if the
64*c8dee2aaSAndroid Build Coastguard Worker     // upper 2x2 remains the same, and there's no perspective. Since there's no projection,
65*c8dee2aaSAndroid Build Coastguard Worker     // Z is irrelevant, so it's okay that fCreationMatrix is an SkMatrix and has
66*c8dee2aaSAndroid Build Coastguard Worker     // discarded the 3rd row/col, and can ignore those values in localToDevice.
67*c8dee2aaSAndroid Build Coastguard Worker     const SkM44& positionMatrix = localToDevice.matrix();
68*c8dee2aaSAndroid Build Coastguard Worker     const bool compatibleMatrix = positionMatrix.rc(0,0) == fCreationMatrix.rc(0, 0) &&
69*c8dee2aaSAndroid Build Coastguard Worker                                   positionMatrix.rc(0,1) == fCreationMatrix.rc(0, 1) &&
70*c8dee2aaSAndroid Build Coastguard Worker                                   positionMatrix.rc(1,0) == fCreationMatrix.rc(1, 0) &&
71*c8dee2aaSAndroid Build Coastguard Worker                                   positionMatrix.rc(1,1) == fCreationMatrix.rc(1, 1) &&
72*c8dee2aaSAndroid Build Coastguard Worker                                   localToDevice.type() != Transform::Type::kPerspective &&
73*c8dee2aaSAndroid Build Coastguard Worker                                   !fCreationMatrix.hasPerspective();
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker     if (compatibleMatrix) {
76*c8dee2aaSAndroid Build Coastguard Worker         const SkV4 mappedOrigin = positionMatrix.map(drawOrigin.x(), drawOrigin.y(), 0.f, 1.f);
77*c8dee2aaSAndroid Build Coastguard Worker         const SkV2 offset = {mappedOrigin.x - fCreationMatrix.getTranslateX(),
78*c8dee2aaSAndroid Build Coastguard Worker                              mappedOrigin.y - fCreationMatrix.getTranslateY()};
79*c8dee2aaSAndroid Build Coastguard Worker         if (SkScalarIsInt(offset.x) && SkScalarIsInt(offset.y)) {
80*c8dee2aaSAndroid Build Coastguard Worker             // The offset is an integer (but make sure), which means the generated mask can be
81*c8dee2aaSAndroid Build Coastguard Worker             // accessed without changing how texels would be sampled.
82*c8dee2aaSAndroid Build Coastguard Worker             return {Rect(fCreationBounds),
83*c8dee2aaSAndroid Build Coastguard Worker                     Transform(SkM44::Translate(SkScalarRoundToInt(offset.x),
84*c8dee2aaSAndroid Build Coastguard Worker                                                SkScalarRoundToInt(offset.y)))};
85*c8dee2aaSAndroid Build Coastguard Worker         }
86*c8dee2aaSAndroid Build Coastguard Worker     }
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker     // Otherwise compute the relative transformation from fCreationMatrix to
89*c8dee2aaSAndroid Build Coastguard Worker     // localToDevice, with the drawOrigin applied. If fCreationMatrix or the
90*c8dee2aaSAndroid Build Coastguard Worker     // concatenation is not invertible the returned Transform is marked invalid and the draw
91*c8dee2aaSAndroid Build Coastguard Worker     // will be automatically dropped.
92*c8dee2aaSAndroid Build Coastguard Worker     const SkMatrix viewDifference = this->viewDifference(
93*c8dee2aaSAndroid Build Coastguard Worker             localToDevice.preTranslate(drawOrigin.x(), drawOrigin.y()));
94*c8dee2aaSAndroid Build Coastguard Worker     return {Rect(fCreationBounds), Transform(SkM44(viewDifference))};
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker 
97*c8dee2aaSAndroid Build Coastguard Worker }  // namespace sktext::gpu
98