mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Pica: Merge texture lookup logic for DebugUtils and Rasterizer.
This effectively adds support for a lot texture formats in the rasterizer.
This commit is contained in:
		
							parent
							
								
									0fba1d48a6
								
							
						
					
					
						commit
						3df88d59b0
					
				
					 4 changed files with 41 additions and 55 deletions
				
			
		|  | @ -24,7 +24,7 @@ QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { | |||
|     QImage decoded_image(info.width, info.height, QImage::Format_ARGB32); | ||||
|     for (int y = 0; y < info.height; ++y) { | ||||
|         for (int x = 0; x < info.width; ++x) { | ||||
|             Math::Vec4<u8> color = Pica::DebugUtils::LookupTexture(src, x, y, info); | ||||
|             Math::Vec4<u8> color = Pica::DebugUtils::LookupTexture(src, x, y, info, true); | ||||
|             decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a())); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -356,9 +356,29 @@ std::unique_ptr<PicaTrace> FinishPicaTracing() | |||
|     return std::move(ret); | ||||
| } | ||||
| 
 | ||||
| const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info) { | ||||
| const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info, bool disable_alpha) { | ||||
| 
 | ||||
|     // Cf. rasterizer code for an explanation of this algorithm.
 | ||||
|     // Images are split into 8x8 tiles. Each tile is composed of four 4x4 subtiles each
 | ||||
|     // of which is composed of four 2x2 subtiles each of which is composed of four texels.
 | ||||
|     // Each structure is embedded into the next-bigger one in a diagonal pattern, e.g.
 | ||||
|     // texels are laid out in a 2x2 subtile like this:
 | ||||
|     // 2 3
 | ||||
|     // 0 1
 | ||||
|     //
 | ||||
|     // The full 8x8 tile has the texels arranged like this:
 | ||||
|     //
 | ||||
|     // 42 43 46 47 58 59 62 63
 | ||||
|     // 40 41 44 45 56 57 60 61
 | ||||
|     // 34 35 38 39 50 51 54 55
 | ||||
|     // 32 33 36 37 48 49 52 53
 | ||||
|     // 10 11 14 15 26 27 30 31
 | ||||
|     // 08 09 12 13 24 25 28 29
 | ||||
|     // 02 03 06 07 18 19 22 23
 | ||||
|     // 00 01 04 05 16 17 20 21
 | ||||
| 
 | ||||
|     // TODO(neobrain): Not sure if this swizzling pattern is used for all textures.
 | ||||
|     // To be flexible in case different but similar patterns are used, we keep this
 | ||||
|     // somewhat inefficient code around for now.
 | ||||
|     int texel_index_within_tile = 0; | ||||
|     for (int block_size_index = 0; block_size_index < 3; ++block_size_index) { | ||||
|         int sub_tile_width = 1 << block_size_index; | ||||
|  | @ -379,7 +399,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture | |||
|     case Regs::TextureFormat::RGBA8: | ||||
|     { | ||||
|         const u8* source_ptr = source + coarse_x * block_height * 4 + coarse_y * info.stride + texel_index_within_tile * 4; | ||||
|         return { source_ptr[3], source_ptr[2], source_ptr[1], 255 }; | ||||
|         return { source_ptr[3], source_ptr[2], source_ptr[1], disable_alpha ? 255 : source_ptr[0] }; | ||||
|     } | ||||
| 
 | ||||
|     case Regs::TextureFormat::RGB8: | ||||
|  | @ -394,8 +414,8 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture | |||
|         u8 r = (source_ptr >> 11) & 0x1F; | ||||
|         u8 g = ((source_ptr) >> 6) & 0x1F; | ||||
|         u8 b = (source_ptr >> 1) & 0x1F; | ||||
|         u8 a = 1; | ||||
|         return Math::MakeVec<u8>((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), a * 255); | ||||
|         u8 a = source_ptr & 1; | ||||
|         return Math::MakeVec<u8>((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), disable_alpha ? 255 : (a * 255)); | ||||
|     } | ||||
| 
 | ||||
|     case Regs::TextureFormat::RGBA4: | ||||
|  | @ -404,16 +424,24 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture | |||
|         u8 r = source_ptr[1] >> 4; | ||||
|         u8 g = source_ptr[1] & 0xFF; | ||||
|         u8 b = source_ptr[0] >> 4; | ||||
|         u8 a = source_ptr[0] & 0xFF; | ||||
|         r = (r << 4) | r; | ||||
|         g = (g << 4) | g; | ||||
|         b = (b << 4) | b; | ||||
|         return { r, g, b, 255 }; | ||||
|         a = (a << 4) | a; | ||||
|         return { r, g, b, disable_alpha ? 255 : a }; | ||||
|     } | ||||
| 
 | ||||
|     case Regs::TextureFormat::A8: | ||||
|     { | ||||
|         const u8* source_ptr = source + coarse_x * block_height + coarse_y * info.stride + texel_index_within_tile; | ||||
|         return { *source_ptr, *source_ptr, *source_ptr, 255 }; | ||||
| 
 | ||||
|         // TODO: Better control this...
 | ||||
|         if (disable_alpha) { | ||||
|             return { *source_ptr, *source_ptr, *source_ptr, 255 }; | ||||
|         } else { | ||||
|             return { 0, 0, 0, *source_ptr }; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     default: | ||||
|  |  | |||
|  | @ -202,7 +202,8 @@ struct TextureInfo { | |||
|                                         const Pica::Regs::TextureFormat& format); | ||||
| }; | ||||
| 
 | ||||
| const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info); | ||||
| const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info, | ||||
|                                    bool disable_alpha = false); | ||||
| void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data); | ||||
| 
 | ||||
| void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages); | ||||
|  |  | |||
|  | @ -183,27 +183,6 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |||
| 
 | ||||
|                 _dbg_assert_(HW_GPU, 0 != texture.config.address); | ||||
| 
 | ||||
|                 // Images are split into 8x8 tiles. Each tile is composed of four 4x4 subtiles each
 | ||||
|                 // of which is composed of four 2x2 subtiles each of which is composed of four texels.
 | ||||
|                 // Each structure is embedded into the next-bigger one in a diagonal pattern, e.g.
 | ||||
|                 // texels are laid out in a 2x2 subtile like this:
 | ||||
|                 // 2 3
 | ||||
|                 // 0 1
 | ||||
|                 //
 | ||||
|                 // The full 8x8 tile has the texels arranged like this:
 | ||||
|                 //
 | ||||
|                 // 42 43 46 47 58 59 62 63
 | ||||
|                 // 40 41 44 45 56 57 60 61
 | ||||
|                 // 34 35 38 39 50 51 54 55
 | ||||
|                 // 32 33 36 37 48 49 52 53
 | ||||
|                 // 10 11 14 15 26 27 30 31
 | ||||
|                 // 08 09 12 13 24 25 28 29
 | ||||
|                 // 02 03 06 07 18 19 22 23
 | ||||
|                 // 00 01 04 05 16 17 20 21
 | ||||
| 
 | ||||
|                 // TODO(neobrain): Not sure if this swizzling pattern is used for all textures.
 | ||||
|                 // To be flexible in case different but similar patterns are used, we keep this
 | ||||
|                 // somewhat inefficient code around for now.
 | ||||
|                 int s = (int)(uv[i].u() * float24::FromFloat32(static_cast<float>(texture.config.width))).ToFloat32(); | ||||
|                 int t = (int)(uv[i].v() * float24::FromFloat32(static_cast<float>(texture.config.height))).ToFloat32(); | ||||
|                 auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val, unsigned size) { | ||||
|  | @ -225,32 +204,10 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |||
|                 s = GetWrappedTexCoord(registers.texture0.wrap_s, s, registers.texture0.width); | ||||
|                 t = GetWrappedTexCoord(registers.texture0.wrap_t, t, registers.texture0.height); | ||||
| 
 | ||||
|                 int texel_index_within_tile = 0; | ||||
|                 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) { | ||||
|                     int sub_tile_width = 1 << block_size_index; | ||||
|                     int sub_tile_height = 1 << block_size_index; | ||||
| 
 | ||||
|                     int sub_tile_index = (s & sub_tile_width) << block_size_index; | ||||
|                     sub_tile_index += 2 * ((t & sub_tile_height) << block_size_index); | ||||
|                     texel_index_within_tile += sub_tile_index; | ||||
|                 } | ||||
| 
 | ||||
|                 const int block_width = 8; | ||||
|                 const int block_height = 8; | ||||
| 
 | ||||
|                 int coarse_s = (s / block_width) * block_width; | ||||
|                 int coarse_t = (t / block_height) * block_height; | ||||
| 
 | ||||
|                 // TODO: This is currently hardcoded for RGB8
 | ||||
|                 u32* texture_data = (u32*)Memory::GetPointer(texture.config.GetPhysicalAddress()); | ||||
| 
 | ||||
|                 const int row_stride = texture.config.width * 3; | ||||
|                 u8* source_ptr = (u8*)texture_data + coarse_s * block_height * 3 + coarse_t * row_stride + texel_index_within_tile * 3; | ||||
|                 texture_color[i].r() = source_ptr[2]; | ||||
|                 texture_color[i].g() = source_ptr[1]; | ||||
|                 texture_color[i].b() = source_ptr[0]; | ||||
|                 texture_color[i].a() = 0xFF; | ||||
|                 u8* texture_data = Memory::GetPointer(texture.config.GetPhysicalAddress()); | ||||
|                 auto info = DebugUtils::TextureInfo::FromPicaRegister(texture.config, texture.format); | ||||
| 
 | ||||
|                 texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info); | ||||
|                 DebugUtils::DumpTexture(texture.config, (u8*)texture_data); | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue