mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-15 12:00:06 +00:00
D24S8 to RGBA8 conversion
This commit is contained in:
parent
db21154142
commit
d813bc5eb5
@ -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…
Reference in New Issue
Block a user