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() { | ||||
|     read_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() { | ||||
|  | @ -963,6 +1009,63 @@ bool RasterizerCacheOpenGL::BlitSurfaces(const Surface& src_surface, | |||
|                         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, | ||||
|                                           bool load_if_create) { | ||||
|     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) { | ||||
|                 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; | ||||
|         new_params.res_scale = target_res_scale; | ||||
|  | @ -1305,6 +1417,27 @@ void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, PAddr addr, | |||
|             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
 | ||||
|         FlushRegion(params.addr, params.size); | ||||
|         surface->LoadGLBuffer(params.addr, params.end); | ||||
|  |  | |||
|  | @ -305,6 +305,9 @@ public: | |||
|     bool BlitSurfaces(const Surface& src_surface, const MathUtil::Rectangle<u32>& src_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
 | ||||
|     void CopySurface(const Surface& src_surface, const Surface& dst_surface, | ||||
|                      SurfaceInterval copy_interval); | ||||
|  | @ -365,4 +368,11 @@ private: | |||
| 
 | ||||
|     OGLFramebuffer read_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