/*
 * 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 "src/gpu/graphite/geom/Transform_graphite.h"

#include "src/core/SkMatrixPriv.h"
#include "src/gpu/graphite/geom/Rect.h"

namespace skgpu::graphite {

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());
}

void map_points(const SkM44& m, const SkV4* in, SkV4* out, int count) {
    // TODO: These maybe should go into SkM44, since bulk point mapping seems generally useful
    auto c0 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m) + 0);
    auto c1 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m) + 4);
    auto c2 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m) + 8);
    auto c3 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m) + 12);

    for (int i = 0; i < count; ++i) {
        auto p = (c0 * in[i].x) + (c1 * in[i].y) + (c2 * in[i].z) + (c3 * in[i].w);
        p.store(out + i);
    }
}

Transform::Type get_matrix_info(const SkM44& m, SkM44* inverse, SkV2* scale) {
    // First compute the inverse.
    // TODO: Alternatively we could compute type first and have type-specific inverses, but it seems
    // useful to ensure any non-invalid matrix returns true from SkM44::invert.
    if (!m.invert(inverse)) {
        *scale = {1.f, 1.f};
        return Transform::Type::kInvalid;
    }

    static constexpr SkV4 kNoPerspective = {0.f, 0.f, 0.f, 1.f};
    static constexpr SkV4 kNoZ = {0.f, 0.f, 1.f, 0.f};
    if (m.row(3) != kNoPerspective || m.col(2) != kNoZ || m.row(2) != kNoZ) {
        // TODO: Use SkMatrixPriv::DifferentialAreaScale, but we need a representative point then.
        // Or something like lengths of upper 2x2 divided by w?
        *scale = {1.f, 1.f};
        return Transform::Type::kProjection;
    }

    //                                              [sx kx 0 tx]
    // At this point, we know that m is of the form [ky sy 0 ty]
    //                                              [0  0  1 0 ]
    //                                              [0  0  0 1 ]
    // Other than kIdentity, none of the types depend on (tx, ty). The remaining types are
    // identified by considering the upper 2x2.
    float sx = m.rc(0, 0);
    float sy = m.rc(1, 1);
    float kx = m.rc(0, 1);
    float ky = m.rc(1, 0);
    if (kx == 0.f && ky == 0.f) {
        // 2x2 is a diagonal matrix
        *scale = {std::abs(sx), std::abs(sy)};
        if (sx == 1.f && sy == 1.f && m.rc(0, 3) == 0.f && m.rc(1, 3) == 0.f) {
            return Transform::Type::kIdentity;
        } else if (sx > 0.f && sy > 0.f) {
            return Transform::Type::kSimpleRectStaysRect;
        } else {
            // We don't need to worry about sx or sy being 0 here because that would imply the
            // matrix wasn't invertible and that was already tested.
            SkASSERT(sx != 0.f && sy != 0.f);
            return Transform::Type::kRectStaysRect;
        }
    } else if (sx == 0.f && sy == 0.f) {
        // 2x2 is an anti-diagonal matrix and represents a 90 or 270 degree rotation plus optional
        // scale and translate. Similar to before, kx and ky can't be 0 or m wouldn't be invertible.
        SkASSERT(kx != 0.f && ky != 0.f);
        *scale = {std::abs(ky), std::abs(kx)};
        return Transform::Type::kRectStaysRect;
    } else {
        *scale = {SkV2{sx, ky}.length(), SkV2{kx, sy}.length()};
        return Transform::Type::kAffine;
    }
}

} // anonymous namespace

Transform::Transform(const SkM44& m) : fM(m) {
    fType = get_matrix_info(m, &fInvM, &fScale);
}

const Transform& Transform::Identity() {
    static const Transform kIdentity{SkM44()};
    return kIdentity;
}
const Transform& Transform::Invalid() {
    static const Transform kInvalid{SkM44(SkM44::kNaN_Constructor)};
    return kInvalid;
}

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
    auto c0 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(fM) + 0);
    auto c1 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(fM) + 4);
    // skip c2 since localIn's z is assumed to be 0
    auto c3 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(fM) + 12);

    for (int i = 0; i < count; ++i) {
        auto p = c0 * localIn[i].x + c1 * localIn[i].y /* + c2*0.f */ + c3 /* *1.f */;
        p.store(deviceOut + i);
    }
}

void Transform::mapPoints(const SkV4* localIn, SkV4* deviceOut, int count) const {
    return map_points(fM, localIn, deviceOut, count);
}

void Transform::inverseMapPoints(const SkV4* deviceIn, SkV4* localOut, int count) const {
    return map_points(fInvM, deviceIn, localOut, count);
}

Transform Transform::preTranslate(float x, float y) const {
    Transform t = *this;
    t.fM.preTranslate(x, y);
    t.fInvM.postTranslate(-x, -y);

    // Under normal conditions, type and scale won't change, but if we've overflown the translation
    // components, mark the matrix as invalid.
    if (!t.fM.isFinite() || !t.fInvM.isFinite()) {
        t.fType = Type::kInvalid;
    }
    return t;
}

Transform Transform::postTranslate(float x, float y) const {
    Transform t = *this;
    t.fM.postTranslate(x, y);
    t.fInvM.preTranslate(-x, -y);
    if (!t.fM.isFinite() || !t.fInvM.isFinite()) {
        t.fType = Type::kInvalid;
    }
    return t;
}

Transform Transform::concat(const Transform& t) const {
    Transform c = {fM * t.fM, t.fInvM * fInvM, std::max(fType, t.fType), {fScale * t.fScale}};
    if (!c.fM.isFinite() || !c.fInvM.isFinite()) {
        c.fType = Type::kInvalid;
    }
    return c;
}

Transform Transform::concatInverse(const Transform& t) const {
    Transform c = {fM * t.fInvM, t.fM * fInvM, std::max(fType, t.fType), {fScale * (1.f/t.fScale)}};
    if (!c.fM.isFinite() || !c.fInvM.isFinite()) {
        c.fType = Type::kInvalid;
    }
    return c;
}

Transform Transform::concatInverse(const SkM44& t) const {
    // saves a multiply compared to inverting just t and then computing fM*t^-1 and t*fInvM, if we
    // instead start with (t*fInvM) and swap definition of computed fM and fInvM.
    Transform inverse{t * fInvM};
    return {inverse.fInvM, inverse.fM, inverse.fType, 1.f / inverse.fScale};
}

} // namespace skgpu::graphite
