blob: 27687d27c98e06a253fa31cff17f6caacaf46900 [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "experimental/graphite/src/geom/Transform_graphite.h"
#include "experimental/graphite/src/geom/Rect.h"
#include "experimental/graphite/src/geom/VectorTypes.h"
#include "src/core/SkMatrixPriv.h"
namespace skgpu {
namespace {
Rect map_rect(const SkM44& m, const Rect& r) {
// TODO: Can Rect's (l,t,-r,-b) structure be used to optimize mapRect?
// TODO: Can take this opportunity to implement 100% accurate perspective plane clipping since
// it doesn't have to match raster/ganesh rendering behavior.
return SkMatrixPriv::MapRect(m, r.asSkRect());
}
} // anonymous namespace
Transform::Transform(const SkM44& m)
: fM(m) {
if (fM.invert(&fInvM)) {
// TODO: actually detect these
fType = (fM == SkM44()) ? Type::kIdentity : Type::kPerspective;
fScale = {1.f, 1.f};
} else {
fType = Type::kInvalid;
fInvM = SkM44();
fScale = {1.f, 1.f};
}
}
bool Transform::operator==(const Transform& t) const {
// Checking fM should be sufficient as all other values are computed from it.
SkASSERT(fM != t.fM || (fInvM == t.fInvM && fType == t.fType && fScale == t.fScale));
return fM == t.fM;
}
Rect Transform::mapRect(const Rect& rect) const { return map_rect(fM, rect); }
Rect Transform::inverseMapRect(const Rect& rect) const { return map_rect(fInvM, rect); }
void Transform::mapPoints(const Rect& localRect, SkV4 deviceOut[4]) const {
SkV2 localCorners[4] = {{localRect.left(), localRect.top()},
{localRect.right(), localRect.top()},
{localRect.right(), localRect.bot()},
{localRect.left(), localRect.bot()}};
this->mapPoints(localCorners, deviceOut, 4);
}
void Transform::mapPoints(const SkV2* localIn, SkV4* deviceOut, int count) const {
// TODO: These maybe should go into SkM44, since bulk point mapping seems generally useful
float4 c0 = float4::Load(SkMatrixPriv::M44ColMajor(fM) + 0);
float4 c1 = float4::Load(SkMatrixPriv::M44ColMajor(fM) + 4);
// skip c2 since localIn's z is assumed to be 0
float4 c3 = float4::Load(SkMatrixPriv::M44ColMajor(fM) + 12);
for (int i = 0; i < count; ++i) {
float4 p = c0 * localIn[i].x + c1 * localIn[i].y /* + c2*0.f */ + c3 /* *1.f */;
p.store(deviceOut + i);
}
}
} // namespace skgpu