summaryrefslogtreecommitdiff
path: root/src/video_core/swrasterizer/rasterizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/swrasterizer/rasterizer.cpp')
-rw-r--r--src/video_core/swrasterizer/rasterizer.cpp237
1 files changed, 1 insertions, 236 deletions
diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp
index 17ba59144..cb11338b7 100644
--- a/src/video_core/swrasterizer/rasterizer.cpp
+++ b/src/video_core/swrasterizer/rasterizer.cpp
@@ -22,6 +22,7 @@
22#include "video_core/regs_rasterizer.h" 22#include "video_core/regs_rasterizer.h"
23#include "video_core/regs_texturing.h" 23#include "video_core/regs_texturing.h"
24#include "video_core/shader/shader.h" 24#include "video_core/shader/shader.h"
25#include "video_core/swrasterizer/framebuffer.h"
25#include "video_core/swrasterizer/rasterizer.h" 26#include "video_core/swrasterizer/rasterizer.h"
26#include "video_core/texture/texture_decode.h" 27#include "video_core/texture/texture_decode.h"
27#include "video_core/utils.h" 28#include "video_core/utils.h"
@@ -30,242 +31,6 @@ namespace Pica {
30 31
31namespace Rasterizer { 32namespace Rasterizer {
32 33
33static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
34 const auto& framebuffer = g_state.regs.framebuffer.framebuffer;
35 const PAddr addr = framebuffer.GetColorBufferPhysicalAddress();
36
37 // Similarly to textures, the render framebuffer is laid out from bottom to top, too.
38 // NOTE: The framebuffer height register contains the actual FB height minus one.
39 y = framebuffer.height - y;
40
41 const u32 coarse_y = y & ~7;
42 u32 bytes_per_pixel =
43 GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value()));
44 u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) +
45 coarse_y * framebuffer.width * bytes_per_pixel;
46 u8* dst_pixel = Memory::GetPhysicalPointer(addr) + dst_offset;
47
48 switch (framebuffer.color_format) {
49 case FramebufferRegs::ColorFormat::RGBA8:
50 Color::EncodeRGBA8(color, dst_pixel);
51 break;
52
53 case FramebufferRegs::ColorFormat::RGB8:
54 Color::EncodeRGB8(color, dst_pixel);
55 break;
56
57 case FramebufferRegs::ColorFormat::RGB5A1:
58 Color::EncodeRGB5A1(color, dst_pixel);
59 break;
60
61 case FramebufferRegs::ColorFormat::RGB565:
62 Color::EncodeRGB565(color, dst_pixel);
63 break;
64
65 case FramebufferRegs::ColorFormat::RGBA4:
66 Color::EncodeRGBA4(color, dst_pixel);
67 break;
68
69 default:
70 LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x",
71 framebuffer.color_format.Value());
72 UNIMPLEMENTED();
73 }
74}
75
76static const Math::Vec4<u8> GetPixel(int x, int y) {
77 const auto& framebuffer = g_state.regs.framebuffer.framebuffer;
78 const PAddr addr = framebuffer.GetColorBufferPhysicalAddress();
79
80 y = framebuffer.height - y;
81
82 const u32 coarse_y = y & ~7;
83 u32 bytes_per_pixel =
84 GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value()));
85 u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) +
86 coarse_y * framebuffer.width * bytes_per_pixel;
87 u8* src_pixel = Memory::GetPhysicalPointer(addr) + src_offset;
88
89 switch (framebuffer.color_format) {
90 case FramebufferRegs::ColorFormat::RGBA8:
91 return Color::DecodeRGBA8(src_pixel);
92
93 case FramebufferRegs::ColorFormat::RGB8:
94 return Color::DecodeRGB8(src_pixel);
95
96 case FramebufferRegs::ColorFormat::RGB5A1:
97 return Color::DecodeRGB5A1(src_pixel);
98
99 case FramebufferRegs::ColorFormat::RGB565:
100 return Color::DecodeRGB565(src_pixel);
101
102 case FramebufferRegs::ColorFormat::RGBA4:
103 return Color::DecodeRGBA4(src_pixel);
104
105 default:
106 LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x",
107 framebuffer.color_format.Value());
108 UNIMPLEMENTED();
109 }
110
111 return {0, 0, 0, 0};
112}
113
114static u32 GetDepth(int x, int y) {
115 const auto& framebuffer = g_state.regs.framebuffer.framebuffer;
116 const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress();
117 u8* depth_buffer = Memory::GetPhysicalPointer(addr);
118
119 y = framebuffer.height - y;
120
121 const u32 coarse_y = y & ~7;
122 u32 bytes_per_pixel = FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format);
123 u32 stride = framebuffer.width * bytes_per_pixel;
124
125 u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
126 u8* src_pixel = depth_buffer + src_offset;
127
128 switch (framebuffer.depth_format) {
129 case FramebufferRegs::DepthFormat::D16:
130 return Color::DecodeD16(src_pixel);
131 case FramebufferRegs::DepthFormat::D24:
132 return Color::DecodeD24(src_pixel);
133 case FramebufferRegs::DepthFormat::D24S8:
134 return Color::DecodeD24S8(src_pixel).x;
135 default:
136 LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format);
137 UNIMPLEMENTED();
138 return 0;
139 }
140}
141
142static u8 GetStencil(int x, int y) {
143 const auto& framebuffer = g_state.regs.framebuffer.framebuffer;
144 const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress();
145 u8* depth_buffer = Memory::GetPhysicalPointer(addr);
146
147 y = framebuffer.height - y;
148
149 const u32 coarse_y = y & ~7;
150 u32 bytes_per_pixel = Pica::FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format);
151 u32 stride = framebuffer.width * bytes_per_pixel;
152
153 u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
154 u8* src_pixel = depth_buffer + src_offset;
155
156 switch (framebuffer.depth_format) {
157 case FramebufferRegs::DepthFormat::D24S8:
158 return Color::DecodeD24S8(src_pixel).y;
159
160 default:
161 LOG_WARNING(
162 HW_GPU,
163 "GetStencil called for function which doesn't have a stencil component (format %u)",
164 framebuffer.depth_format);
165 return 0;
166 }
167}
168
169static void SetDepth(int x, int y, u32 value) {
170 const auto& framebuffer = g_state.regs.framebuffer.framebuffer;
171 const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress();
172 u8* depth_buffer = Memory::GetPhysicalPointer(addr);
173
174 y = framebuffer.height - y;
175
176 const u32 coarse_y = y & ~7;
177 u32 bytes_per_pixel = FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format);
178 u32 stride = framebuffer.width * bytes_per_pixel;
179
180 u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
181 u8* dst_pixel = depth_buffer + dst_offset;
182
183 switch (framebuffer.depth_format) {
184 case FramebufferRegs::DepthFormat::D16:
185 Color::EncodeD16(value, dst_pixel);
186 break;
187
188 case FramebufferRegs::DepthFormat::D24:
189 Color::EncodeD24(value, dst_pixel);
190 break;
191
192 case FramebufferRegs::DepthFormat::D24S8:
193 Color::EncodeD24X8(value, dst_pixel);
194 break;
195
196 default:
197 LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format);
198 UNIMPLEMENTED();
199 break;
200 }
201}
202
203static void SetStencil(int x, int y, u8 value) {
204 const auto& framebuffer = g_state.regs.framebuffer.framebuffer;
205 const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress();
206 u8* depth_buffer = Memory::GetPhysicalPointer(addr);
207
208 y = framebuffer.height - y;
209
210 const u32 coarse_y = y & ~7;
211 u32 bytes_per_pixel = Pica::FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format);
212 u32 stride = framebuffer.width * bytes_per_pixel;
213
214 u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
215 u8* dst_pixel = depth_buffer + dst_offset;
216
217 switch (framebuffer.depth_format) {
218 case Pica::FramebufferRegs::DepthFormat::D16:
219 case Pica::FramebufferRegs::DepthFormat::D24:
220 // Nothing to do
221 break;
222
223 case Pica::FramebufferRegs::DepthFormat::D24S8:
224 Color::EncodeX24S8(value, dst_pixel);
225 break;
226
227 default:
228 LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format);
229 UNIMPLEMENTED();
230 break;
231 }
232}
233
234static u8 PerformStencilAction(FramebufferRegs::StencilAction action, u8 old_stencil, u8 ref) {
235 switch (action) {
236 case FramebufferRegs::StencilAction::Keep:
237 return old_stencil;
238
239 case FramebufferRegs::StencilAction::Zero:
240 return 0;
241
242 case FramebufferRegs::StencilAction::Replace:
243 return ref;
244
245 case FramebufferRegs::StencilAction::Increment:
246 // Saturated increment
247 return std::min<u8>(old_stencil, 254) + 1;
248
249 case FramebufferRegs::StencilAction::Decrement:
250 // Saturated decrement
251 return std::max<u8>(old_stencil, 1) - 1;
252
253 case FramebufferRegs::StencilAction::Invert:
254 return ~old_stencil;
255
256 case FramebufferRegs::StencilAction::IncrementWrap:
257 return old_stencil + 1;
258
259 case FramebufferRegs::StencilAction::DecrementWrap:
260 return old_stencil - 1;
261
262 default:
263 LOG_CRITICAL(HW_GPU, "Unknown stencil action %x", (int)action);
264 UNIMPLEMENTED();
265 return 0;
266 }
267}
268
269// NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values 34// NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values
270struct Fix12P4 { 35struct Fix12P4 {
271 Fix12P4() {} 36 Fix12P4() {}