mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	SWRasterizer: Move framebuffer operation functions to their own file
This commit is contained in:
		
							parent
							
								
									e24717bca0
								
							
						
					
					
						commit
						e1ad7d69b9
					
				
					 4 changed files with 285 additions and 236 deletions
				
			
		|  | @ -14,6 +14,7 @@ set(SRCS | |||
|             shader/shader.cpp | ||||
|             shader/shader_interpreter.cpp | ||||
|             swrasterizer/clipper.cpp | ||||
|             swrasterizer/framebuffer.cpp | ||||
|             swrasterizer/rasterizer.cpp | ||||
|             swrasterizer/swrasterizer.cpp | ||||
|             texture/etc1.cpp | ||||
|  | @ -51,6 +52,7 @@ set(HEADERS | |||
|             shader/shader.h | ||||
|             shader/shader_interpreter.h | ||||
|             swrasterizer/clipper.h | ||||
|             swrasterizer/framebuffer.h | ||||
|             swrasterizer/rasterizer.h | ||||
|             swrasterizer/swrasterizer.h | ||||
|             texture/etc1.h | ||||
|  |  | |||
							
								
								
									
										259
									
								
								src/video_core/swrasterizer/framebuffer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								src/video_core/swrasterizer/framebuffer.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,259 @@ | |||
| // Copyright 2017 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/color.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/vector_math.h" | ||||
| #include "core/hw/gpu.h" | ||||
| #include "core/memory.h" | ||||
| #include "video_core/pica_state.h" | ||||
| #include "video_core/regs_framebuffer.h" | ||||
| #include "video_core/swrasterizer/framebuffer.h" | ||||
| #include "video_core/utils.h" | ||||
| 
 | ||||
| namespace Pica { | ||||
| namespace Rasterizer { | ||||
| 
 | ||||
| void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); | ||||
| 
 | ||||
|     // Similarly to textures, the render framebuffer is laid out from bottom to top, too.
 | ||||
|     // NOTE: The framebuffer height register contains the actual FB height minus one.
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = | ||||
|         GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value())); | ||||
|     u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + | ||||
|                      coarse_y * framebuffer.width * bytes_per_pixel; | ||||
|     u8* dst_pixel = Memory::GetPhysicalPointer(addr) + dst_offset; | ||||
| 
 | ||||
|     switch (framebuffer.color_format) { | ||||
|     case FramebufferRegs::ColorFormat::RGBA8: | ||||
|         Color::EncodeRGBA8(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB8: | ||||
|         Color::EncodeRGB8(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB5A1: | ||||
|         Color::EncodeRGB5A1(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB565: | ||||
|         Color::EncodeRGB565(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGBA4: | ||||
|         Color::EncodeRGBA4(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", | ||||
|                      framebuffer.color_format.Value()); | ||||
|         UNIMPLEMENTED(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const Math::Vec4<u8> GetPixel(int x, int y) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = | ||||
|         GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value())); | ||||
|     u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + | ||||
|                      coarse_y * framebuffer.width * bytes_per_pixel; | ||||
|     u8* src_pixel = Memory::GetPhysicalPointer(addr) + src_offset; | ||||
| 
 | ||||
|     switch (framebuffer.color_format) { | ||||
|     case FramebufferRegs::ColorFormat::RGBA8: | ||||
|         return Color::DecodeRGBA8(src_pixel); | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB8: | ||||
|         return Color::DecodeRGB8(src_pixel); | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB5A1: | ||||
|         return Color::DecodeRGB5A1(src_pixel); | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB565: | ||||
|         return Color::DecodeRGB565(src_pixel); | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGBA4: | ||||
|         return Color::DecodeRGBA4(src_pixel); | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", | ||||
|                      framebuffer.color_format.Value()); | ||||
|         UNIMPLEMENTED(); | ||||
|     } | ||||
| 
 | ||||
|     return {0, 0, 0, 0}; | ||||
| } | ||||
| 
 | ||||
| u32 GetDepth(int x, int y) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|     u8* depth_buffer = Memory::GetPhysicalPointer(addr); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); | ||||
|     u32 stride = framebuffer.width * bytes_per_pixel; | ||||
| 
 | ||||
|     u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|     u8* src_pixel = depth_buffer + src_offset; | ||||
| 
 | ||||
|     switch (framebuffer.depth_format) { | ||||
|     case FramebufferRegs::DepthFormat::D16: | ||||
|         return Color::DecodeD16(src_pixel); | ||||
|     case FramebufferRegs::DepthFormat::D24: | ||||
|         return Color::DecodeD24(src_pixel); | ||||
|     case FramebufferRegs::DepthFormat::D24S8: | ||||
|         return Color::DecodeD24S8(src_pixel).x; | ||||
|     default: | ||||
|         LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format); | ||||
|         UNIMPLEMENTED(); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| u8 GetStencil(int x, int y) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|     u8* depth_buffer = Memory::GetPhysicalPointer(addr); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = Pica::FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); | ||||
|     u32 stride = framebuffer.width * bytes_per_pixel; | ||||
| 
 | ||||
|     u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|     u8* src_pixel = depth_buffer + src_offset; | ||||
| 
 | ||||
|     switch (framebuffer.depth_format) { | ||||
|     case FramebufferRegs::DepthFormat::D24S8: | ||||
|         return Color::DecodeD24S8(src_pixel).y; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_WARNING( | ||||
|             HW_GPU, | ||||
|             "GetStencil called for function which doesn't have a stencil component (format %u)", | ||||
|             framebuffer.depth_format); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void SetDepth(int x, int y, u32 value) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|     u8* depth_buffer = Memory::GetPhysicalPointer(addr); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); | ||||
|     u32 stride = framebuffer.width * bytes_per_pixel; | ||||
| 
 | ||||
|     u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|     u8* dst_pixel = depth_buffer + dst_offset; | ||||
| 
 | ||||
|     switch (framebuffer.depth_format) { | ||||
|     case FramebufferRegs::DepthFormat::D16: | ||||
|         Color::EncodeD16(value, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::DepthFormat::D24: | ||||
|         Color::EncodeD24(value, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::DepthFormat::D24S8: | ||||
|         Color::EncodeD24X8(value, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format); | ||||
|         UNIMPLEMENTED(); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void SetStencil(int x, int y, u8 value) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|     u8* depth_buffer = Memory::GetPhysicalPointer(addr); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = Pica::FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); | ||||
|     u32 stride = framebuffer.width * bytes_per_pixel; | ||||
| 
 | ||||
|     u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|     u8* dst_pixel = depth_buffer + dst_offset; | ||||
| 
 | ||||
|     switch (framebuffer.depth_format) { | ||||
|     case Pica::FramebufferRegs::DepthFormat::D16: | ||||
|     case Pica::FramebufferRegs::DepthFormat::D24: | ||||
|         // Nothing to do
 | ||||
|         break; | ||||
| 
 | ||||
|     case Pica::FramebufferRegs::DepthFormat::D24S8: | ||||
|         Color::EncodeX24S8(value, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format); | ||||
|         UNIMPLEMENTED(); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| u8 PerformStencilAction(FramebufferRegs::StencilAction action, u8 old_stencil, u8 ref) { | ||||
|     switch (action) { | ||||
|     case FramebufferRegs::StencilAction::Keep: | ||||
|         return old_stencil; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Zero: | ||||
|         return 0; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Replace: | ||||
|         return ref; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Increment: | ||||
|         // Saturated increment
 | ||||
|         return std::min<u8>(old_stencil, 254) + 1; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Decrement: | ||||
|         // Saturated decrement
 | ||||
|         return std::max<u8>(old_stencil, 1) - 1; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Invert: | ||||
|         return ~old_stencil; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::IncrementWrap: | ||||
|         return old_stencil + 1; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::DecrementWrap: | ||||
|         return old_stencil - 1; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(HW_GPU, "Unknown stencil action %x", (int)action); | ||||
|         UNIMPLEMENTED(); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace Rasterizer
 | ||||
| } // namespace Pica
 | ||||
							
								
								
									
										23
									
								
								src/video_core/swrasterizer/framebuffer.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/video_core/swrasterizer/framebuffer.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| // Copyright 2017 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "common/vector_math.h" | ||||
| #include "video_core/regs_framebuffer.h" | ||||
| 
 | ||||
| namespace Pica { | ||||
| namespace Rasterizer { | ||||
| 
 | ||||
| void DrawPixel(int x, int y, const Math::Vec4<u8>& color); | ||||
| const Math::Vec4<u8> GetPixel(int x, int y); | ||||
| u32 GetDepth(int x, int y); | ||||
| u8 GetStencil(int x, int y); | ||||
| void SetDepth(int x, int y, u32 value); | ||||
| void SetStencil(int x, int y, u8 value); | ||||
| u8 PerformStencilAction(FramebufferRegs::StencilAction action, u8 old_stencil, u8 ref); | ||||
| 
 | ||||
| } // namespace Rasterizer
 | ||||
| } // namespace Pica
 | ||||
|  | @ -22,6 +22,7 @@ | |||
| #include "video_core/regs_rasterizer.h" | ||||
| #include "video_core/regs_texturing.h" | ||||
| #include "video_core/shader/shader.h" | ||||
| #include "video_core/swrasterizer/framebuffer.h" | ||||
| #include "video_core/swrasterizer/rasterizer.h" | ||||
| #include "video_core/texture/texture_decode.h" | ||||
| #include "video_core/utils.h" | ||||
|  | @ -30,242 +31,6 @@ namespace Pica { | |||
| 
 | ||||
| namespace Rasterizer { | ||||
| 
 | ||||
| static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); | ||||
| 
 | ||||
|     // Similarly to textures, the render framebuffer is laid out from bottom to top, too.
 | ||||
|     // NOTE: The framebuffer height register contains the actual FB height minus one.
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = | ||||
|         GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value())); | ||||
|     u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + | ||||
|                      coarse_y * framebuffer.width * bytes_per_pixel; | ||||
|     u8* dst_pixel = Memory::GetPhysicalPointer(addr) + dst_offset; | ||||
| 
 | ||||
|     switch (framebuffer.color_format) { | ||||
|     case FramebufferRegs::ColorFormat::RGBA8: | ||||
|         Color::EncodeRGBA8(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB8: | ||||
|         Color::EncodeRGB8(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB5A1: | ||||
|         Color::EncodeRGB5A1(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB565: | ||||
|         Color::EncodeRGB565(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGBA4: | ||||
|         Color::EncodeRGBA4(color, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", | ||||
|                      framebuffer.color_format.Value()); | ||||
|         UNIMPLEMENTED(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static const Math::Vec4<u8> GetPixel(int x, int y) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = | ||||
|         GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value())); | ||||
|     u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + | ||||
|                      coarse_y * framebuffer.width * bytes_per_pixel; | ||||
|     u8* src_pixel = Memory::GetPhysicalPointer(addr) + src_offset; | ||||
| 
 | ||||
|     switch (framebuffer.color_format) { | ||||
|     case FramebufferRegs::ColorFormat::RGBA8: | ||||
|         return Color::DecodeRGBA8(src_pixel); | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB8: | ||||
|         return Color::DecodeRGB8(src_pixel); | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB5A1: | ||||
|         return Color::DecodeRGB5A1(src_pixel); | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGB565: | ||||
|         return Color::DecodeRGB565(src_pixel); | ||||
| 
 | ||||
|     case FramebufferRegs::ColorFormat::RGBA4: | ||||
|         return Color::DecodeRGBA4(src_pixel); | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", | ||||
|                      framebuffer.color_format.Value()); | ||||
|         UNIMPLEMENTED(); | ||||
|     } | ||||
| 
 | ||||
|     return {0, 0, 0, 0}; | ||||
| } | ||||
| 
 | ||||
| static u32 GetDepth(int x, int y) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|     u8* depth_buffer = Memory::GetPhysicalPointer(addr); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); | ||||
|     u32 stride = framebuffer.width * bytes_per_pixel; | ||||
| 
 | ||||
|     u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|     u8* src_pixel = depth_buffer + src_offset; | ||||
| 
 | ||||
|     switch (framebuffer.depth_format) { | ||||
|     case FramebufferRegs::DepthFormat::D16: | ||||
|         return Color::DecodeD16(src_pixel); | ||||
|     case FramebufferRegs::DepthFormat::D24: | ||||
|         return Color::DecodeD24(src_pixel); | ||||
|     case FramebufferRegs::DepthFormat::D24S8: | ||||
|         return Color::DecodeD24S8(src_pixel).x; | ||||
|     default: | ||||
|         LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format); | ||||
|         UNIMPLEMENTED(); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static u8 GetStencil(int x, int y) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|     u8* depth_buffer = Memory::GetPhysicalPointer(addr); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = Pica::FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); | ||||
|     u32 stride = framebuffer.width * bytes_per_pixel; | ||||
| 
 | ||||
|     u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|     u8* src_pixel = depth_buffer + src_offset; | ||||
| 
 | ||||
|     switch (framebuffer.depth_format) { | ||||
|     case FramebufferRegs::DepthFormat::D24S8: | ||||
|         return Color::DecodeD24S8(src_pixel).y; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_WARNING( | ||||
|             HW_GPU, | ||||
|             "GetStencil called for function which doesn't have a stencil component (format %u)", | ||||
|             framebuffer.depth_format); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void SetDepth(int x, int y, u32 value) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|     u8* depth_buffer = Memory::GetPhysicalPointer(addr); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); | ||||
|     u32 stride = framebuffer.width * bytes_per_pixel; | ||||
| 
 | ||||
|     u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|     u8* dst_pixel = depth_buffer + dst_offset; | ||||
| 
 | ||||
|     switch (framebuffer.depth_format) { | ||||
|     case FramebufferRegs::DepthFormat::D16: | ||||
|         Color::EncodeD16(value, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::DepthFormat::D24: | ||||
|         Color::EncodeD24(value, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     case FramebufferRegs::DepthFormat::D24S8: | ||||
|         Color::EncodeD24X8(value, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format); | ||||
|         UNIMPLEMENTED(); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void SetStencil(int x, int y, u8 value) { | ||||
|     const auto& framebuffer = g_state.regs.framebuffer.framebuffer; | ||||
|     const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|     u8* depth_buffer = Memory::GetPhysicalPointer(addr); | ||||
| 
 | ||||
|     y = framebuffer.height - y; | ||||
| 
 | ||||
|     const u32 coarse_y = y & ~7; | ||||
|     u32 bytes_per_pixel = Pica::FramebufferRegs::BytesPerDepthPixel(framebuffer.depth_format); | ||||
|     u32 stride = framebuffer.width * bytes_per_pixel; | ||||
| 
 | ||||
|     u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|     u8* dst_pixel = depth_buffer + dst_offset; | ||||
| 
 | ||||
|     switch (framebuffer.depth_format) { | ||||
|     case Pica::FramebufferRegs::DepthFormat::D16: | ||||
|     case Pica::FramebufferRegs::DepthFormat::D24: | ||||
|         // Nothing to do
 | ||||
|         break; | ||||
| 
 | ||||
|     case Pica::FramebufferRegs::DepthFormat::D24S8: | ||||
|         Color::EncodeX24S8(value, dst_pixel); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format); | ||||
|         UNIMPLEMENTED(); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static u8 PerformStencilAction(FramebufferRegs::StencilAction action, u8 old_stencil, u8 ref) { | ||||
|     switch (action) { | ||||
|     case FramebufferRegs::StencilAction::Keep: | ||||
|         return old_stencil; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Zero: | ||||
|         return 0; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Replace: | ||||
|         return ref; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Increment: | ||||
|         // Saturated increment
 | ||||
|         return std::min<u8>(old_stencil, 254) + 1; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Decrement: | ||||
|         // Saturated decrement
 | ||||
|         return std::max<u8>(old_stencil, 1) - 1; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::Invert: | ||||
|         return ~old_stencil; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::IncrementWrap: | ||||
|         return old_stencil + 1; | ||||
| 
 | ||||
|     case FramebufferRegs::StencilAction::DecrementWrap: | ||||
|         return old_stencil - 1; | ||||
| 
 | ||||
|     default: | ||||
|         LOG_CRITICAL(HW_GPU, "Unknown stencil action %x", (int)action); | ||||
|         UNIMPLEMENTED(); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values
 | ||||
| struct Fix12P4 { | ||||
|     Fix12P4() {} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue