citra/src/video_core/renderer_software/sw_clipper.cpp

89 lines
3.1 KiB
C++
Raw Normal View History

2023-06-24 00:59:18 +02:00
// Copyright 2023 Citra Emulator Project
2014-12-17 06:38:14 +01:00
// Licensed under GPLv2 or any later version
2014-07-27 17:34:11 +02:00
// Refer to the license.txt file included.
#include <array>
#include <cstddef>
2023-06-24 00:59:18 +02:00
#include "video_core/regs_texturing.h"
Prepare frontend for multiple graphics APIs (#6347) * externals: Update dynarmic * settings: Introduce GraphicsAPI enum * For now it's OpenGL only but will be expanded upon later * citra_qt: Introduce backend agnostic context management * Mostly a direct port from yuzu * core: Simplify context acquire * settings: Add option to create debug contexts * renderer_opengl: Abstract initialization to Driver * This commit also updates glad and adds some useful extensions which we will use in part 2 * Rasterizer construction is moved to the specific renderer instead of RendererBase. Software rendering has been disable to achieve this but will be brought back in the next commit. * video_core: Remove Init/Shutdown methods from renderer * The constructor and destructor can do the same job * In addition move opengl function loading to Qt since SDL already does this. Also remove ErrorVideoCore which is never reached * citra_qt: Decouple software renderer from opengl part 1 * citra: Decouple software renderer from opengl part 2 * android: Decouple software renderer from opengl part 3 * swrasterizer: Decouple software renderer from opengl part 4 * This commit simply enforces the renderer naming conventions in the software renderer * video_core: Move RendererBase to VideoCore * video_core: De-globalize screenshot state * video_core: Pass system to the renderers * video_core: Commonize shader uniform data * video_core: Abstract backend agnostic rasterizer operations * bootmanager: Remove references to OpenGL for macOS OpenGL macOS headers definitions clash heavily with each other * citra_qt: Proper title for api settings * video_core: Reduce boost usage * bootmanager: Fix hide mouse option Remove event handlers from RenderWidget for events that are already handled by the parent GRenderWindow. Also enable mouse tracking on the RenderWidget. * android: Remove software from graphics api list * code: Address review comments * citra: Port per-game settings read * Having to update the default value for all backends is a pain so lets centralize it * android: Rename to OpenGLES --------- Co-authored-by: MerryMage <MerryMage@users.noreply.github.com> Co-authored-by: Vitor Kiguchi <vitor-kiguchi@hotmail.com>
2023-03-27 13:29:17 +02:00
#include "video_core/renderer_software/sw_clipper.h"
2014-07-27 17:34:11 +02:00
2023-06-24 00:59:18 +02:00
namespace SwRenderer {
2023-06-24 00:59:18 +02:00
using Pica::TexturingRegs;
2014-07-27 17:34:11 +02:00
2023-06-24 00:59:18 +02:00
void FlipQuaternionIfOpposite(Common::Vec4<f24>& a, const Common::Vec4<f24>& b) {
if (Common::Dot(a, b) < f24::Zero()) {
a *= f24::FromFloat32(-1.0f);
2014-07-27 17:34:11 +02:00
}
};
2023-06-24 00:59:18 +02:00
int SignedArea(const Common::Vec2<Fix12P4>& vtx1, const Common::Vec2<Fix12P4>& vtx2,
const Common::Vec2<Fix12P4>& vtx3) {
const auto vec1 = Common::MakeVec(vtx2 - vtx1, 0);
const auto vec2 = Common::MakeVec(vtx3 - vtx1, 0);
// TODO: There is a very small chance this will overflow for sizeof(int) == 4
return Common::Cross(vec1, vec2).z;
};
2014-07-27 17:34:11 +02:00
2023-06-24 00:59:18 +02:00
std::tuple<f24, f24, f24, PAddr> ConvertCubeCoord(f24 u, f24 v, f24 w,
const Pica::TexturingRegs& regs) {
const float abs_u = std::abs(u.ToFloat32());
const float abs_v = std::abs(v.ToFloat32());
const float abs_w = std::abs(w.ToFloat32());
f24 x, y, z;
PAddr addr;
if (abs_u > abs_v && abs_u > abs_w) {
if (u > f24::Zero()) {
addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveX);
y = -v;
} else {
addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeX);
y = v;
2014-07-27 17:34:11 +02:00
}
2023-06-24 00:59:18 +02:00
x = -w;
z = u;
} else if (abs_v > abs_w) {
if (v > f24::Zero()) {
addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveY);
x = u;
} else {
addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeY);
x = -u;
}
y = w;
z = v;
} else {
if (w > f24::Zero()) {
addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveZ);
y = -v;
} else {
addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeZ);
y = v;
}
x = u;
z = w;
}
2023-06-24 00:59:18 +02:00
const f24 z_abs = f24::FromFloat32(std::abs(z.ToFloat32()));
const f24 half = f24::FromFloat32(0.5f);
return std::make_tuple(x / z * half + half, y / z * half + half, z_abs, addr);
}
2023-06-24 00:59:18 +02:00
bool IsRightSideOrFlatBottomEdge(const Common::Vec2<Fix12P4>& vtx,
const Common::Vec2<Fix12P4>& line1,
const Common::Vec2<Fix12P4>& line2) {
if (line1.y == line2.y) {
// Just check if vertex is above us => bottom line parallel to x-axis
return vtx.y < line1.y;
} else {
// Check if vertex is on our left => right side
// TODO: Not sure how likely this is to overflow
const auto svtx = vtx.Cast<s32>();
const auto sline1 = line1.Cast<s32>();
const auto sline2 = line2.Cast<s32>();
return svtx.x <
sline1.x + (sline2.x - sline1.x) * (svtx.y - sline1.y) / (sline2.y - sline1.y);
2014-07-27 17:34:11 +02:00
}
}
2023-06-24 00:59:18 +02:00
} // namespace SwRenderer