• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 "experimental/graphite/src/geom/Transform_graphite.h"
9 
10 #include "experimental/graphite/src/geom/Rect.h"
11 #include "experimental/graphite/src/geom/VectorTypes.h"
12 #include "src/core/SkMatrixPriv.h"
13 
14 namespace skgpu {
15 
16 namespace {
17 
map_rect(const SkM44 & m,const Rect & r)18 Rect map_rect(const SkM44& m, const Rect& r) {
19     // TODO: Can Rect's (l,t,-r,-b) structure be used to optimize mapRect?
20     // TODO: Can take this opportunity to implement 100% accurate perspective plane clipping since
21     //       it doesn't have to match raster/ganesh rendering behavior.
22     return SkMatrixPriv::MapRect(m, r.asSkRect());
23 }
24 
25 } // anonymous namespace
26 
Transform(const SkM44 & m)27 Transform::Transform(const SkM44& m)
28         : fM(m) {
29     if (fM.invert(&fInvM)) {
30         // TODO: actually detect these
31         fType = (fM == SkM44()) ? Type::kIdentity : Type::kPerspective;
32         fScale = {1.f, 1.f};
33     } else {
34         fType = Type::kInvalid;
35         fInvM = SkM44();
36         fScale = {1.f, 1.f};
37     }
38 }
39 
operator ==(const Transform & t) const40 bool Transform::operator==(const Transform& t) const {
41     // Checking fM should be sufficient as all other values are computed from it.
42     SkASSERT(fM != t.fM || (fInvM == t.fInvM && fType == t.fType && fScale == t.fScale));
43     return fM == t.fM;
44 }
45 
mapRect(const Rect & rect) const46 Rect Transform::mapRect(const Rect& rect) const { return map_rect(fM, rect); }
inverseMapRect(const Rect & rect) const47 Rect Transform::inverseMapRect(const Rect& rect) const { return map_rect(fInvM, rect); }
48 
mapPoints(const Rect & localRect,SkV4 deviceOut[4]) const49 void Transform::mapPoints(const Rect& localRect, SkV4 deviceOut[4]) const {
50     SkV2 localCorners[4] = {{localRect.left(),  localRect.top()},
51                             {localRect.right(), localRect.top()},
52                             {localRect.right(), localRect.bot()},
53                             {localRect.left(),  localRect.bot()}};
54     this->mapPoints(localCorners, deviceOut, 4);
55 }
56 
mapPoints(const SkV2 * localIn,SkV4 * deviceOut,int count) const57 void Transform::mapPoints(const SkV2* localIn, SkV4* deviceOut, int count) const {
58     // TODO: These maybe should go into SkM44, since bulk point mapping seems generally useful
59     float4 c0 = float4::Load(SkMatrixPriv::M44ColMajor(fM) + 0);
60     float4 c1 = float4::Load(SkMatrixPriv::M44ColMajor(fM) + 4);
61     // skip c2 since localIn's z is assumed to be 0
62     float4 c3 = float4::Load(SkMatrixPriv::M44ColMajor(fM) + 12);
63 
64     for (int i = 0; i < count; ++i) {
65         float4 p = c0 * localIn[i].x + c1 * localIn[i].y /* + c2*0.f */ + c3 /* *1.f */;
66         p.store(deviceOut + i);
67     }
68 }
69 
70 } // namespace skgpu
71