mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	GPU: Add proper framebuffer register handling.
This commit is contained in:
		
							parent
							
								
									bbc6f314eb
								
							
						
					
					
						commit
						0b4055c152
					
				
					 2 changed files with 105 additions and 11 deletions
				
			
		|  | @ -84,6 +84,10 @@ const u8* GetFramebufferPointer(const u32 address) { | |||
| template <typename T> | ||||
| inline void Read(T &var, const u32 addr) { | ||||
|     switch (addr) { | ||||
|     case Registers::FramebufferTopSize: | ||||
|         var = g_regs.top_framebuffer.size; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferTopLeft1: | ||||
|         var = g_regs.framebuffer_top_left_1; | ||||
|         break; | ||||
|  | @ -92,6 +96,18 @@ inline void Read(T &var, const u32 addr) { | |||
|         var = g_regs.framebuffer_top_left_2; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferTopFormat: | ||||
|         var = g_regs.top_framebuffer.format; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferTopSwapBuffers: | ||||
|         var = g_regs.top_framebuffer.active_fb; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferTopStride: | ||||
|         var = g_regs.top_framebuffer.stride; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferTopRight1: | ||||
|         var = g_regs.framebuffer_top_right_1; | ||||
|         break; | ||||
|  | @ -100,6 +116,10 @@ inline void Read(T &var, const u32 addr) { | |||
|         var = g_regs.framebuffer_top_right_2; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferSubSize: | ||||
|         var = g_regs.sub_framebuffer.size; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferSubLeft1: | ||||
|         var = g_regs.framebuffer_sub_left_1; | ||||
|         break; | ||||
|  | @ -108,6 +128,26 @@ inline void Read(T &var, const u32 addr) { | |||
|         var = g_regs.framebuffer_sub_right_1; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferSubFormat: | ||||
|         var = g_regs.sub_framebuffer.format; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferSubSwapBuffers: | ||||
|         var = g_regs.sub_framebuffer.active_fb; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferSubStride: | ||||
|         var = g_regs.sub_framebuffer.stride; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferSubLeft2: | ||||
|         var = g_regs.framebuffer_sub_left_2; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferSubRight2: | ||||
|         var = g_regs.framebuffer_sub_right_2; | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::DisplayInputBufferAddr: | ||||
|         var = g_regs.display_transfer.input_address; | ||||
|         break; | ||||
|  | @ -154,6 +194,17 @@ inline void Read(T &var, const u32 addr) { | |||
| template <typename T> | ||||
| inline void Write(u32 addr, const T data) { | ||||
|     switch (static_cast<Registers::Id>(addr)) { | ||||
|     // TODO: Framebuffer registers!!
 | ||||
|     case Registers::FramebufferTopSwapBuffers: | ||||
|         g_regs.top_framebuffer.active_fb = data; | ||||
|         // TODO: Not sure if this should only be done upon a change!
 | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::FramebufferSubSwapBuffers: | ||||
|         g_regs.sub_framebuffer.active_fb = data; | ||||
|         // TODO: Not sure if this should only be done upon a change!
 | ||||
|         break; | ||||
| 
 | ||||
|     case Registers::DisplayInputBufferAddr: | ||||
|         g_regs.display_transfer.input_address = data; | ||||
|         break; | ||||
|  | @ -195,7 +246,7 @@ inline void Write(u32 addr, const T data) { | |||
|                       g_regs.display_transfer.output_height * g_regs.display_transfer.output_width * 4, | ||||
|                       g_regs.display_transfer.GetPhysicalInputAddress(), (int)g_regs.display_transfer.input_width, (int)g_regs.display_transfer.input_height, | ||||
|                       g_regs.display_transfer.GetPhysicalOutputAddress(), (int)g_regs.display_transfer.output_width, (int)g_regs.display_transfer.output_height, | ||||
|                       (int)g_regs.display_transfer.output_format); | ||||
|                       (int)g_regs.display_transfer.output_format.Value()); | ||||
|         } | ||||
|         break; | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,12 +14,21 @@ static const u32 kFrameTicks    = kFrameCycles / 3; ///< Approximate number of i | |||
| 
 | ||||
| struct Registers { | ||||
|     enum Id : u32 { | ||||
|         FramebufferTopSize        = 0x1EF0045C, | ||||
|         FramebufferTopLeft1       = 0x1EF00468,   // Main LCD, first framebuffer for 3D left
 | ||||
|         FramebufferTopLeft2       = 0x1EF0046C,   // Main LCD, second framebuffer for 3D left
 | ||||
|         FramebufferTopFormat      = 0x1EF00470, | ||||
|         FramebufferTopSwapBuffers = 0x1EF00478, | ||||
|         FramebufferTopStride      = 0x1EF00490,   // framebuffer row stride?
 | ||||
|         FramebufferTopRight1      = 0x1EF00494,   // Main LCD, first framebuffer for 3D right
 | ||||
|         FramebufferTopRight2      = 0x1EF00498,   // Main LCD, second framebuffer for 3D right
 | ||||
| 
 | ||||
|         FramebufferSubSize        = 0x1EF0055C, | ||||
|         FramebufferSubLeft1       = 0x1EF00568,   // Sub LCD, first framebuffer
 | ||||
|         FramebufferSubLeft2       = 0x1EF0056C,   // Sub LCD, second framebuffer
 | ||||
|         FramebufferSubFormat      = 0x1EF00570, | ||||
|         FramebufferSubSwapBuffers = 0x1EF00578, | ||||
|         FramebufferSubStride      = 0x1EF00590,   // framebuffer row stride?
 | ||||
|         FramebufferSubRight1      = 0x1EF00594,   // Sub LCD, unused first framebuffer
 | ||||
|         FramebufferSubRight2      = 0x1EF00598,   // Sub LCD, unused second framebuffer
 | ||||
| 
 | ||||
|  | @ -36,6 +45,15 @@ struct Registers { | |||
|         ProcessCommandList      = 0x1EF018F0, | ||||
|     }; | ||||
| 
 | ||||
|     enum class FramebufferFormat : u32 { | ||||
|         RGBA8  = 0, | ||||
|         RGB8   = 1, | ||||
|         RGB565 = 2, | ||||
|         RGB5A1 = 3, | ||||
|         RGBA4  = 4, | ||||
|     }; | ||||
| 
 | ||||
|     // TODO: Move these into the framebuffer struct
 | ||||
|     u32 framebuffer_top_left_1; | ||||
|     u32 framebuffer_top_left_2; | ||||
|     u32 framebuffer_top_right_1; | ||||
|  | @ -45,6 +63,31 @@ struct Registers { | |||
|     u32 framebuffer_sub_right_1; | ||||
|     u32 framebuffer_sub_right_2; | ||||
| 
 | ||||
|     struct FrameBufferConfig { | ||||
|         union { | ||||
|             u32 size; | ||||
| 
 | ||||
|             BitField< 0, 16, u32> width; | ||||
|             BitField<16, 16, u32> height; | ||||
|         }; | ||||
| 
 | ||||
|         union { | ||||
|             u32 format; | ||||
| 
 | ||||
|             BitField< 0, 3, FramebufferFormat> color_format; | ||||
|         }; | ||||
| 
 | ||||
|         union { | ||||
|             u32 active_fb; | ||||
| 
 | ||||
|             BitField<0, 1, u32> second_fb_active; | ||||
|         }; | ||||
| 
 | ||||
|         u32 stride; | ||||
|     }; | ||||
|     FrameBufferConfig top_framebuffer; | ||||
|     FrameBufferConfig sub_framebuffer; | ||||
| 
 | ||||
|     struct { | ||||
|         u32 input_address; | ||||
|         u32 output_address; | ||||
|  | @ -75,8 +118,8 @@ struct Registers { | |||
|             u32 flags; | ||||
| 
 | ||||
|             BitField< 0, 1, u32> flip_data; | ||||
|             BitField< 8, 3, u32> input_format; | ||||
|             BitField<12, 3, u32> output_format; | ||||
|             BitField< 8, 3, FramebufferFormat> input_format; | ||||
|             BitField<12, 3, FramebufferFormat> output_format; | ||||
|             BitField<16, 1, u32> output_tiled; | ||||
|         }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue