mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 21:41:26 +12:00
gl: Implement display output format correction
This commit is contained in:
parent
acd3fd0c3e
commit
bc141831f7
3 changed files with 60 additions and 26 deletions
|
@ -416,9 +416,9 @@ void GLGSRender::on_exit()
|
||||||
m_flip_fbo.remove();
|
m_flip_fbo.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_flip_tex_color)
|
for (auto& flip_tex_image : m_flip_tex_color)
|
||||||
{
|
{
|
||||||
m_flip_tex_color.reset();
|
flip_tex_image.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_vao)
|
if (m_vao)
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace gl
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
u32 pitch;
|
u32 pitch;
|
||||||
|
u8 eye;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +126,7 @@ class GLGSRender : public GSRender, public ::rsx::reports::ZCULL_control
|
||||||
gl::fbo* m_draw_fbo = nullptr;
|
gl::fbo* m_draw_fbo = nullptr;
|
||||||
std::list<gl::framebuffer_holder> m_framebuffer_cache;
|
std::list<gl::framebuffer_holder> m_framebuffer_cache;
|
||||||
gl::fbo m_flip_fbo;
|
gl::fbo m_flip_fbo;
|
||||||
std::unique_ptr<gl::texture> m_flip_tex_color;
|
std::unique_ptr<gl::texture> m_flip_tex_color[2];
|
||||||
|
|
||||||
//vaos are mandatory for core profile
|
//vaos are mandatory for core profile
|
||||||
gl::vao m_vao;
|
gl::vao m_vao;
|
||||||
|
|
|
@ -24,12 +24,29 @@ namespace gl
|
||||||
glCopyImageSubData(visual->id(), target, 0, 0, 0, 0, g_vis_texture->id(), target, 0, 0, 0, 0, visual->width(), visual->height(), 1);
|
glCopyImageSubData(visual->id(), target, 0, 0, 0, 0, g_vis_texture->id(), target, 0, 0, 0, 0, visual->width(), visual->height(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum RSX_display_format_to_gl_format(u8 format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
rsx_log.error("Unhandled video output format 0x%x", static_cast<s32>(format));
|
||||||
|
[[fallthrough]];
|
||||||
|
case CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8:
|
||||||
|
return GL_BGRA8;
|
||||||
|
case CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8B8G8R8:
|
||||||
|
return GL_RGBA8;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, const rsx::avconf& avconfig)
|
gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, const rsx::avconf& avconfig)
|
||||||
{
|
{
|
||||||
gl::texture* image = nullptr;
|
gl::texture* image = nullptr;
|
||||||
|
|
||||||
|
// @FIXME: This implementation needs to merge into the texture cache's upload_texture routine.
|
||||||
|
// See notes on the vulkan implementation on what needs to happen before that is viable.
|
||||||
|
|
||||||
// Check the surface store first
|
// Check the surface store first
|
||||||
gl::command_context cmd = { gl_state };
|
gl::command_context cmd = { gl_state };
|
||||||
const auto format_bpp = rsx::get_format_block_size_in_bytes(info->format);
|
const auto format_bpp = rsx::get_format_block_size_in_bytes(info->format);
|
||||||
|
@ -83,6 +100,17 @@ gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, cons
|
||||||
if (const auto tex = surface->get_raw_texture(); tex) image = tex;
|
if (const auto tex = surface->get_raw_texture(); tex) image = tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GLenum expected_format = gl::RSX_display_format_to_gl_format(avconfig.format);
|
||||||
|
std::unique_ptr<gl::texture>& flip_image = m_flip_tex_color[info->eye];
|
||||||
|
|
||||||
|
auto initialize_scratch_image = [&]()
|
||||||
|
{
|
||||||
|
if (!flip_image || flip_image->size2D() != sizeu{ info->width, info->height })
|
||||||
|
{
|
||||||
|
flip_image = std::make_unique<gl::texture>(GL_TEXTURE_2D, info->width, info->height, 1, 1, expected_format);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (!image)
|
if (!image)
|
||||||
{
|
{
|
||||||
rsx_log.warning("Flip texture was not found in cache. Uploading surface from CPU");
|
rsx_log.warning("Flip texture was not found in cache. Uploading surface from CPU");
|
||||||
|
@ -90,31 +118,32 @@ gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, cons
|
||||||
gl::pixel_unpack_settings unpack_settings;
|
gl::pixel_unpack_settings unpack_settings;
|
||||||
unpack_settings.alignment(1).row_length(info->pitch / 4);
|
unpack_settings.alignment(1).row_length(info->pitch / 4);
|
||||||
|
|
||||||
if (!m_flip_tex_color || m_flip_tex_color->size2D() != sizeu{info->width, info->height})
|
initialize_scratch_image();
|
||||||
{
|
|
||||||
m_flip_tex_color = std::make_unique<gl::texture>(GL_TEXTURE_2D, info->width, info->height, 1, 1, GL_RGBA8);
|
|
||||||
}
|
|
||||||
|
|
||||||
gl::command_context cmd{ gl_state };
|
gl::command_context cmd{ gl_state };
|
||||||
const auto range = utils::address_range::start_length(info->address, info->pitch * info->height);
|
const auto range = utils::address_range::start_length(info->address, info->pitch * info->height);
|
||||||
m_gl_texture_cache.invalidate_range(cmd, range, rsx::invalidation_cause::read);
|
m_gl_texture_cache.invalidate_range(cmd, range, rsx::invalidation_cause::read);
|
||||||
|
|
||||||
gl::texture::format fmt;
|
flip_image->copy_from(vm::base(info->address), static_cast<gl::texture::format>(expected_format), gl::texture::type::uint_8_8_8_8, unpack_settings);
|
||||||
switch (avconfig.format)
|
image = flip_image.get();
|
||||||
|
}
|
||||||
|
else if (image->get_internal_format() != static_cast<gl::texture::internal_format>(expected_format))
|
||||||
|
{
|
||||||
|
initialize_scratch_image();
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
if (gl::formats_are_bitcast_compatible(flip_image.get(), image))
|
||||||
{
|
{
|
||||||
default:
|
const position3u offset{};
|
||||||
rsx_log.error("Unhandled video output format 0x%x", avconfig.format);
|
gl::g_hw_blitter->copy_image(cmd, image, flip_image.get(), 0, 0, offset, offset, { info->width, info->height, 1 });
|
||||||
[[fallthrough]];
|
}
|
||||||
case CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8:
|
else
|
||||||
fmt = gl::texture::format::bgra;
|
{
|
||||||
break;
|
const coord3u region = { {/* offsets */}, { info->width, info->height, 1 } };
|
||||||
case CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8B8G8R8:
|
gl::copy_typeless(cmd, flip_image.get(), image, region, region);
|
||||||
fmt = gl::texture::format::rgba;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_flip_tex_color->copy_from(vm::base(info->address), fmt, gl::texture::type::uint_8_8_8_8, unpack_settings);
|
image = flip_image.get();
|
||||||
image = m_flip_tex_color.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
|
@ -172,12 +201,15 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
||||||
if (info.buffer < display_buffers_count && buffer_width && buffer_height)
|
if (info.buffer < display_buffers_count && buffer_width && buffer_height)
|
||||||
{
|
{
|
||||||
// Find the source image
|
// Find the source image
|
||||||
gl::present_surface_info present_info;
|
gl::present_surface_info present_info
|
||||||
present_info.width = buffer_width;
|
{
|
||||||
present_info.height = buffer_height;
|
.address = rsx::get_address(display_buffers[info.buffer].offset, CELL_GCM_LOCATION_LOCAL),
|
||||||
present_info.pitch = buffer_pitch;
|
.format = av_format,
|
||||||
present_info.format = av_format;
|
.width = buffer_width,
|
||||||
present_info.address = rsx::get_address(display_buffers[info.buffer].offset, CELL_GCM_LOCATION_LOCAL);
|
.height = buffer_height,
|
||||||
|
.pitch = buffer_pitch,
|
||||||
|
.eye = 0
|
||||||
|
};
|
||||||
|
|
||||||
const auto image_to_flip_ = get_present_source(&present_info, avconfig);
|
const auto image_to_flip_ = get_present_source(&present_info, avconfig);
|
||||||
image_to_flip = image_to_flip_->id();
|
image_to_flip = image_to_flip_->id();
|
||||||
|
@ -192,6 +224,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
||||||
present_info.width = buffer_width;
|
present_info.width = buffer_width;
|
||||||
present_info.height = buffer_height;
|
present_info.height = buffer_height;
|
||||||
present_info.address = rsx::get_address(image_offset, CELL_GCM_LOCATION_LOCAL);
|
present_info.address = rsx::get_address(image_offset, CELL_GCM_LOCATION_LOCAL);
|
||||||
|
present_info.eye = 1;
|
||||||
|
|
||||||
image_to_flip2 = get_present_source(&present_info, avconfig)->id();
|
image_to_flip2 = get_present_source(&present_info, avconfig)->id();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue