mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	D24S8 to RGBA8 conversion
This commit is contained in:
		
							parent
							
								
									db21154142
								
							
						
					
					
						commit
						d813bc5eb5
					
				
					 2 changed files with 143 additions and 0 deletions
				
			
		|  | @ -943,6 +943,52 @@ Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params | ||||||
| RasterizerCacheOpenGL::RasterizerCacheOpenGL() { | RasterizerCacheOpenGL::RasterizerCacheOpenGL() { | ||||||
|     read_framebuffer.Create(); |     read_framebuffer.Create(); | ||||||
|     draw_framebuffer.Create(); |     draw_framebuffer.Create(); | ||||||
|  | 
 | ||||||
|  |     attributeless_vao.Create(); | ||||||
|  | 
 | ||||||
|  |     d24s8_abgr_buffer.Create(); | ||||||
|  |     d24s8_abgr_buffer_size = 0; | ||||||
|  | 
 | ||||||
|  |     const char* vs_source = R"( | ||||||
|  | #version 330 core | ||||||
|  | const vec2 vertices[4] = vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0)); | ||||||
|  | void main() { | ||||||
|  |     gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0); | ||||||
|  | } | ||||||
|  | )"; | ||||||
|  |     const char* fs_source = R"( | ||||||
|  | #version 330 core | ||||||
|  | 
 | ||||||
|  | uniform samplerBuffer tbo; | ||||||
|  | uniform vec2 tbo_size; | ||||||
|  | uniform vec4 viewport; | ||||||
|  | 
 | ||||||
|  | out vec4 color; | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     vec2 tbo_coord = (gl_FragCoord.xy - viewport.xy) * tbo_size / viewport.zw; | ||||||
|  |     int tbo_offset = int(tbo_coord.y) * int(tbo_size.x) + int(tbo_coord.x); | ||||||
|  |     color = texelFetch(tbo, tbo_offset).rabg; | ||||||
|  | } | ||||||
|  | )"; | ||||||
|  |     d24s8_abgr_shader.Create(vs_source, fs_source); | ||||||
|  | 
 | ||||||
|  |     OpenGLState state = OpenGLState::GetCurState(); | ||||||
|  |     GLuint old_program = state.draw.shader_program; | ||||||
|  |     state.draw.shader_program = d24s8_abgr_shader.handle; | ||||||
|  |     state.Apply(); | ||||||
|  | 
 | ||||||
|  |     GLint tbo_u_id = glGetUniformLocation(d24s8_abgr_shader.handle, "tbo"); | ||||||
|  |     ASSERT(tbo_u_id != -1); | ||||||
|  |     glUniform1i(tbo_u_id, 0); | ||||||
|  | 
 | ||||||
|  |     state.draw.shader_program = old_program; | ||||||
|  |     state.Apply(); | ||||||
|  | 
 | ||||||
|  |     d24s8_abgr_tbo_size_u_id = glGetUniformLocation(d24s8_abgr_shader.handle, "tbo_size"); | ||||||
|  |     ASSERT(d24s8_abgr_tbo_size_u_id != -1); | ||||||
|  |     d24s8_abgr_viewport_u_id = glGetUniformLocation(d24s8_abgr_shader.handle, "viewport"); | ||||||
|  |     ASSERT(d24s8_abgr_viewport_u_id != -1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RasterizerCacheOpenGL::~RasterizerCacheOpenGL() { | RasterizerCacheOpenGL::~RasterizerCacheOpenGL() { | ||||||
|  | @ -963,6 +1009,63 @@ bool RasterizerCacheOpenGL::BlitSurfaces(const Surface& src_surface, | ||||||
|                         draw_framebuffer.handle); |                         draw_framebuffer.handle); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void RasterizerCacheOpenGL::ConvertD24S8toABGR(GLuint src_tex, | ||||||
|  |                                                const MathUtil::Rectangle<u32>& src_rect, | ||||||
|  |                                                GLuint dst_tex, | ||||||
|  |                                                const MathUtil::Rectangle<u32>& dst_rect) { | ||||||
|  |     OpenGLState prev_state = OpenGLState::GetCurState(); | ||||||
|  |     SCOPE_EXIT({ prev_state.Apply(); }); | ||||||
|  | 
 | ||||||
|  |     OpenGLState state; | ||||||
|  |     state.draw.read_framebuffer = read_framebuffer.handle; | ||||||
|  |     state.draw.draw_framebuffer = draw_framebuffer.handle; | ||||||
|  |     state.Apply(); | ||||||
|  | 
 | ||||||
|  |     glBindBuffer(GL_PIXEL_PACK_BUFFER, d24s8_abgr_buffer.handle); | ||||||
|  | 
 | ||||||
|  |     GLsizeiptr target_pbo_size = src_rect.GetWidth() * src_rect.GetHeight() * 4; | ||||||
|  |     if (target_pbo_size > d24s8_abgr_buffer_size) { | ||||||
|  |         d24s8_abgr_buffer_size = target_pbo_size * 2; | ||||||
|  |         glBufferData(GL_PIXEL_PACK_BUFFER, d24s8_abgr_buffer_size, nullptr, GL_STREAM_COPY); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, src_tex, | ||||||
|  |                            0); | ||||||
|  |     glReadPixels(static_cast<GLint>(src_rect.left), static_cast<GLint>(src_rect.bottom), | ||||||
|  |                  static_cast<GLsizei>(src_rect.GetWidth()), | ||||||
|  |                  static_cast<GLsizei>(src_rect.GetHeight()), GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, | ||||||
|  |                  0); | ||||||
|  | 
 | ||||||
|  |     glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); | ||||||
|  | 
 | ||||||
|  |     // PBO now contains src_tex in RABG format
 | ||||||
|  |     state.draw.shader_program = d24s8_abgr_shader.handle; | ||||||
|  |     state.draw.vertex_array = attributeless_vao.handle; | ||||||
|  |     state.viewport.x = static_cast<GLint>(dst_rect.left); | ||||||
|  |     state.viewport.y = static_cast<GLint>(dst_rect.bottom); | ||||||
|  |     state.viewport.width = static_cast<GLsizei>(dst_rect.GetWidth()); | ||||||
|  |     state.viewport.height = static_cast<GLsizei>(dst_rect.GetHeight()); | ||||||
|  |     state.Apply(); | ||||||
|  | 
 | ||||||
|  |     OGLTexture tbo; | ||||||
|  |     tbo.Create(); | ||||||
|  |     glActiveTexture(GL_TEXTURE0); | ||||||
|  |     glBindTexture(GL_TEXTURE_BUFFER, tbo.handle); | ||||||
|  |     glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA8, d24s8_abgr_buffer.handle); | ||||||
|  | 
 | ||||||
|  |     glUniform2f(d24s8_abgr_tbo_size_u_id, static_cast<GLfloat>(src_rect.GetWidth()), | ||||||
|  |                 static_cast<GLfloat>(src_rect.GetHeight())); | ||||||
|  |     glUniform4f(d24s8_abgr_viewport_u_id, static_cast<GLfloat>(state.viewport.x), | ||||||
|  |                 static_cast<GLfloat>(state.viewport.y), static_cast<GLfloat>(state.viewport.width), | ||||||
|  |                 static_cast<GLfloat>(state.viewport.height)); | ||||||
|  | 
 | ||||||
|  |     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_tex, 0); | ||||||
|  |     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||||||
|  |     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||||||
|  | 
 | ||||||
|  |     glBindTexture(GL_TEXTURE_BUFFER, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale, | Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale, | ||||||
|                                           bool load_if_create) { |                                           bool load_if_create) { | ||||||
|     if (params.addr == 0 || params.height * params.width == 0) { |     if (params.addr == 0 || params.height * params.width == 0) { | ||||||
|  | @ -988,6 +1091,15 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc | ||||||
|             if (expandable != nullptr && expandable->res_scale > target_res_scale) { |             if (expandable != nullptr && expandable->res_scale > target_res_scale) { | ||||||
|                 target_res_scale = expandable->res_scale; |                 target_res_scale = expandable->res_scale; | ||||||
|             } |             } | ||||||
|  |             // Keep res_scale when reinterpreting d24s8 -> rgba8
 | ||||||
|  |             if (params.pixel_format == PixelFormat::RGBA8) { | ||||||
|  |                 find_params.pixel_format = PixelFormat::D24S8; | ||||||
|  |                 expandable = FindMatch<MatchFlags::Expand | MatchFlags::Invalid>( | ||||||
|  |                     surface_cache, find_params, match_res_scale); | ||||||
|  |                 if (expandable != nullptr && expandable->res_scale > target_res_scale) { | ||||||
|  |                     target_res_scale = expandable->res_scale; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         SurfaceParams new_params = params; |         SurfaceParams new_params = params; | ||||||
|         new_params.res_scale = target_res_scale; |         new_params.res_scale = target_res_scale; | ||||||
|  | @ -1305,6 +1417,27 @@ void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, PAddr addr, | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         // D24S8 to RGBA8
 | ||||||
|  |         if (surface->pixel_format == PixelFormat::RGBA8) { | ||||||
|  |             params.pixel_format = PixelFormat::D24S8; | ||||||
|  |             Surface reinterpret_surface = | ||||||
|  |                 FindMatch<MatchFlags::Copy>(surface_cache, params, ScaleMatch::Ignore, interval); | ||||||
|  |             if (reinterpret_surface != nullptr) { | ||||||
|  |                 ASSERT(reinterpret_surface->pixel_format == PixelFormat::D24S8); | ||||||
|  | 
 | ||||||
|  |                 SurfaceInterval convert_interval = params.GetCopyableInterval(reinterpret_surface); | ||||||
|  |                 SurfaceParams convert_params = surface->FromInterval(convert_interval); | ||||||
|  |                 auto src_rect = reinterpret_surface->GetScaledSubRect(convert_params); | ||||||
|  |                 auto dest_rect = surface->GetScaledSubRect(convert_params); | ||||||
|  | 
 | ||||||
|  |                 ConvertD24S8toABGR(reinterpret_surface->texture.handle, src_rect, | ||||||
|  |                                    surface->texture.handle, dest_rect); | ||||||
|  | 
 | ||||||
|  |                 surface->invalid_regions.erase(convert_interval); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         // Load data from 3DS memory
 |         // Load data from 3DS memory
 | ||||||
|         FlushRegion(params.addr, params.size); |         FlushRegion(params.addr, params.size); | ||||||
|         surface->LoadGLBuffer(params.addr, params.end); |         surface->LoadGLBuffer(params.addr, params.end); | ||||||
|  |  | ||||||
|  | @ -305,6 +305,9 @@ public: | ||||||
|     bool BlitSurfaces(const Surface& src_surface, const MathUtil::Rectangle<u32>& src_rect, |     bool BlitSurfaces(const Surface& src_surface, const MathUtil::Rectangle<u32>& src_rect, | ||||||
|                       const Surface& dst_surface, const MathUtil::Rectangle<u32>& dst_rect); |                       const Surface& dst_surface, const MathUtil::Rectangle<u32>& dst_rect); | ||||||
| 
 | 
 | ||||||
|  |     void ConvertD24S8toABGR(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, | ||||||
|  |                             GLuint dst_tex, const MathUtil::Rectangle<u32>& dst_rect); | ||||||
|  | 
 | ||||||
|     /// Copy one surface's region to another
 |     /// Copy one surface's region to another
 | ||||||
|     void CopySurface(const Surface& src_surface, const Surface& dst_surface, |     void CopySurface(const Surface& src_surface, const Surface& dst_surface, | ||||||
|                      SurfaceInterval copy_interval); |                      SurfaceInterval copy_interval); | ||||||
|  | @ -365,4 +368,11 @@ private: | ||||||
| 
 | 
 | ||||||
|     OGLFramebuffer read_framebuffer; |     OGLFramebuffer read_framebuffer; | ||||||
|     OGLFramebuffer draw_framebuffer; |     OGLFramebuffer draw_framebuffer; | ||||||
|  | 
 | ||||||
|  |     OGLVertexArray attributeless_vao; | ||||||
|  |     OGLBuffer d24s8_abgr_buffer; | ||||||
|  |     GLsizeiptr d24s8_abgr_buffer_size; | ||||||
|  |     OGLShader d24s8_abgr_shader; | ||||||
|  |     GLint d24s8_abgr_tbo_size_u_id; | ||||||
|  |     GLint d24s8_abgr_viewport_u_id; | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue