mirror of
https://github.com/libretro/RetroArch
synced 2025-02-25 12:41:18 +00:00
Avoid complete reinit on apply_state_changes.
Clean up multi-pass logic a bit in D3D9.
This commit is contained in:
parent
068beedf3c
commit
8bb4cbae46
@ -329,28 +329,9 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool D3DVideo::viewport_need_restore()
|
||||
{
|
||||
const rarch_viewport_t &custom = g_extern.console.screen.viewports.custom_vp;
|
||||
if (memcmp(&viewport_state.custom, &custom, sizeof(custom)))
|
||||
return true;
|
||||
if (viewport_state.scale_integer != g_settings.video.scale_integer)
|
||||
return true;
|
||||
if (fabs(viewport_state.aspect_ratio - g_extern.system.aspect_ratio) > 0.0001)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void D3DVideo::calculate_rect(unsigned width, unsigned height,
|
||||
bool keep, float desired_aspect)
|
||||
{
|
||||
const rarch_viewport_t &custom = g_extern.console.screen.viewports.custom_vp;
|
||||
|
||||
viewport_state.custom = custom;
|
||||
viewport_state.scale_integer = g_settings.video.scale_integer;
|
||||
viewport_state.aspect_ratio = desired_aspect;
|
||||
|
||||
if (g_settings.video.scale_integer)
|
||||
{
|
||||
struct rarch_viewport vp = {0};
|
||||
@ -363,6 +344,7 @@ void D3DVideo::calculate_rect(unsigned width, unsigned height,
|
||||
{
|
||||
if (g_settings.video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
|
||||
{
|
||||
const rarch_viewport_t &custom = g_extern.console.screen.viewports.custom_vp;
|
||||
set_viewport(custom.x, custom.y, custom.width, custom.height);
|
||||
}
|
||||
else
|
||||
@ -438,6 +420,7 @@ D3DVideo::D3DVideo(const video_info_t *info) :
|
||||
g_pD3D(nullptr), dev(nullptr), font(nullptr),
|
||||
rotation(0), needs_restore(false), cgCtx(nullptr)
|
||||
{
|
||||
should_resize = false;
|
||||
gfx_set_dwm();
|
||||
|
||||
#ifdef HAVE_OVERLAY
|
||||
@ -611,6 +594,22 @@ bool D3DVideo::frame(const void *frame,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (should_resize)
|
||||
{
|
||||
calculate_rect(screen_width, screen_height, video_info.force_aspect, g_extern.system.aspect_ratio);
|
||||
chain->set_final_viewport(final_viewport);
|
||||
recompute_pass_sizes();
|
||||
|
||||
// render_chain() only clears out viewport, clear out everything.
|
||||
D3DRECT clear_rect;
|
||||
clear_rect.x1 = clear_rect.y1 = 0;
|
||||
clear_rect.x2 = screen_width;
|
||||
clear_rect.y2 = screen_height;
|
||||
dev->Clear(1, &clear_rect, D3DCLEAR_TARGET, 0, 1, 0);
|
||||
|
||||
should_resize = false;
|
||||
}
|
||||
|
||||
if (!chain->render(frame, width, height, pitch, rotation))
|
||||
{
|
||||
RARCH_ERR("[D3D9]: Failed to render scene.\n");
|
||||
@ -803,6 +802,22 @@ void D3DVideo::init_multipass()
|
||||
shader.pass[i].fbo.type_x = shader.pass[i].fbo.type_y = RARCH_SCALE_INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
bool use_extra_pass = shader.passes < GFX_MAX_SHADERS && shader.pass[shader.passes - 1].fbo.valid;
|
||||
if (use_extra_pass)
|
||||
{
|
||||
shader.passes++;
|
||||
gfx_shader_pass &dummy_pass = shader.pass[shader.passes - 1];
|
||||
dummy_pass.fbo.scale_x = dummy_pass.fbo.scale_y = 1.0f;
|
||||
dummy_pass.fbo.type_x = dummy_pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
||||
dummy_pass.filter = RARCH_FILTER_UNSPEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx_shader_pass &pass = shader.pass[shader.passes - 1];
|
||||
pass.fbo.scale_x = pass.fbo.scale_y = 1.0f;
|
||||
pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
||||
}
|
||||
}
|
||||
|
||||
bool D3DVideo::set_shader(const std::string &path)
|
||||
@ -839,6 +854,43 @@ void D3DVideo::process_shader()
|
||||
init_singlepass();
|
||||
}
|
||||
|
||||
void D3DVideo::recompute_pass_sizes()
|
||||
{
|
||||
try
|
||||
{
|
||||
LinkInfo link_info = {0};
|
||||
link_info.pass = &shader.pass[0];
|
||||
link_info.tex_w = link_info.tex_h = video_info.input_scale * RARCH_SCALE_BASE;
|
||||
|
||||
unsigned current_width = link_info.tex_w;
|
||||
unsigned current_height = link_info.tex_h;
|
||||
unsigned out_width = 0;
|
||||
unsigned out_height = 0;
|
||||
|
||||
chain->set_pass_size(0, current_width, current_height);
|
||||
for (unsigned i = 1; i < shader.passes; i++)
|
||||
{
|
||||
RenderChain::convert_geometry(link_info,
|
||||
out_width, out_height,
|
||||
current_width, current_height, final_viewport);
|
||||
|
||||
link_info.tex_w = next_pow2(out_width);
|
||||
link_info.tex_h = next_pow2(out_height);
|
||||
|
||||
chain->set_pass_size(i, link_info.tex_w, link_info.tex_h);
|
||||
|
||||
current_width = out_width;
|
||||
current_height = out_height;
|
||||
|
||||
link_info.pass = &shader.pass[i];
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
RARCH_ERR("[D3D9]: Render chain error: (%s).\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool D3DVideo::init_chain(const video_info_t &video_info)
|
||||
{
|
||||
try
|
||||
@ -846,14 +898,6 @@ bool D3DVideo::init_chain(const video_info_t &video_info)
|
||||
// Setup information for first pass.
|
||||
LinkInfo link_info = {0};
|
||||
|
||||
if (shader.passes == 1 && !shader.pass[0].fbo.valid)
|
||||
{
|
||||
gfx_shader_pass &pass = shader.pass[0];
|
||||
pass.filter = video_info.smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
||||
pass.fbo.scale_x = pass.fbo.scale_y = 1.0f;
|
||||
pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
||||
}
|
||||
|
||||
link_info.pass = &shader.pass[0];
|
||||
link_info.tex_w = link_info.tex_h = video_info.input_scale * RARCH_SCALE_BASE;
|
||||
|
||||
@ -870,8 +914,6 @@ bool D3DVideo::init_chain(const video_info_t &video_info)
|
||||
unsigned out_width = 0;
|
||||
unsigned out_height = 0;
|
||||
|
||||
bool use_extra_pass = shader.pass[shader.passes - 1].fbo.valid;
|
||||
|
||||
for (unsigned i = 1; i < shader.passes; i++)
|
||||
{
|
||||
RenderChain::convert_geometry(link_info,
|
||||
@ -885,32 +927,6 @@ bool D3DVideo::init_chain(const video_info_t &video_info)
|
||||
current_width = out_width;
|
||||
current_height = out_height;
|
||||
|
||||
if (i == shader.passes - 1 && !use_extra_pass)
|
||||
{
|
||||
gfx_shader_pass &pass = shader.pass[i];
|
||||
pass.filter = video_info.smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
||||
pass.fbo.scale_x = pass.fbo.scale_y = 1.0f;
|
||||
pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
||||
}
|
||||
|
||||
chain->add_pass(link_info);
|
||||
}
|
||||
|
||||
if (use_extra_pass)
|
||||
{
|
||||
RenderChain::convert_geometry(link_info,
|
||||
out_width, out_height,
|
||||
current_width, current_height, final_viewport);
|
||||
|
||||
gfx_shader_pass &pass = shader.pass[shader.passes - 1];
|
||||
pass.filter = video_info.smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
||||
pass.fbo.scale_x = pass.fbo.scale_y = 1.0f;
|
||||
pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
||||
|
||||
link_info.pass = &pass;
|
||||
link_info.tex_w = next_pow2(out_width);
|
||||
link_info.tex_h = next_pow2(out_height);
|
||||
|
||||
chain->add_pass(link_info);
|
||||
}
|
||||
|
||||
@ -1409,15 +1425,14 @@ static void d3d9_set_aspect_ratio(void *data, unsigned aspect_ratio_idx)
|
||||
|
||||
g_extern.system.aspect_ratio = aspectratio_lut[aspect_ratio_idx].value;
|
||||
d3d->info().force_aspect = true;
|
||||
d3d->restore();
|
||||
d3d->should_resize = true;
|
||||
return;
|
||||
}
|
||||
|
||||
static void d3d9_apply_state_changes(void *data)
|
||||
{
|
||||
D3DVideo *d3d = reinterpret_cast<D3DVideo*>(data);
|
||||
if (d3d->viewport_need_restore())
|
||||
d3d->restore();
|
||||
d3d->should_resize = true;
|
||||
}
|
||||
|
||||
static void d3d9_set_osd_msg(void *data, const char *msg, void *userdata)
|
||||
|
@ -95,7 +95,7 @@ class D3DVideo
|
||||
bool restore();
|
||||
void render_msg(const char *msg, font_params_t *params = nullptr);
|
||||
|
||||
bool viewport_need_restore();
|
||||
bool should_resize;
|
||||
inline video_info_t& info() { return video_info; }
|
||||
|
||||
private:
|
||||
@ -106,13 +106,7 @@ class D3DVideo
|
||||
IDirect3DDevice9 *dev;
|
||||
LPD3DXFONT font;
|
||||
|
||||
struct
|
||||
{
|
||||
rarch_viewport_t custom;
|
||||
float aspect_ratio;
|
||||
bool scale_integer;
|
||||
} viewport_state;
|
||||
|
||||
void recompute_pass_sizes();
|
||||
void calculate_rect(unsigned width, unsigned height, bool keep, float aspect);
|
||||
void set_viewport(int x, int y, unsigned width, unsigned height);
|
||||
unsigned screen_width;
|
||||
|
@ -108,6 +108,36 @@ void RenderChain::clear()
|
||||
luts.clear();
|
||||
}
|
||||
|
||||
void RenderChain::set_final_viewport(const D3DVIEWPORT9& final_viewport)
|
||||
{
|
||||
this->final_viewport = final_viewport;
|
||||
}
|
||||
|
||||
void RenderChain::set_pass_size(unsigned pass_index, unsigned width, unsigned height)
|
||||
{
|
||||
Pass &pass = passes[pass_index];
|
||||
if (width != pass.info.tex_w || height != pass.info.tex_h)
|
||||
{
|
||||
pass.tex->Release();
|
||||
pass.info.tex_w = width;
|
||||
pass.info.tex_h = height;
|
||||
|
||||
if (FAILED(dev->CreateTexture(width, height, 1,
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
passes.back().info.pass->fbo.fp_fbo ? D3DFMT_A32B32G32R32F : D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT,
|
||||
&pass.tex, nullptr)))
|
||||
{
|
||||
throw std::runtime_error("Failed to create texture ...");
|
||||
}
|
||||
|
||||
dev->SetTexture(0, pass.tex);
|
||||
dev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
|
||||
dev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
|
||||
dev->SetTexture(0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderChain::add_pass(const LinkInfo &info)
|
||||
{
|
||||
Pass pass;
|
||||
@ -620,7 +650,18 @@ void RenderChain::render_pass(Pass &pass, unsigned pass_index)
|
||||
bind_luts(pass);
|
||||
bind_tracker(pass, pass_index);
|
||||
|
||||
dev->Clear(0, 0, D3DCLEAR_TARGET, 0, 1, 0);
|
||||
// Clear out whole framebuffer incase we change viewports mid-way to avoid stale garbage.
|
||||
if (pass_index < passes.size())
|
||||
{
|
||||
D3DRECT clear_rect;
|
||||
clear_rect.x1 = clear_rect.y1 = 0;
|
||||
clear_rect.x2 = passes[pass_index].info.tex_w;
|
||||
clear_rect.y2 = passes[pass_index].info.tex_h;
|
||||
dev->Clear(1, &clear_rect, D3DCLEAR_TARGET, 0, 1, 0);
|
||||
}
|
||||
else
|
||||
dev->Clear(0, 0, D3DCLEAR_TARGET, 0, 1, 0);
|
||||
|
||||
if (SUCCEEDED(dev->BeginScene()))
|
||||
{
|
||||
dev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
|
@ -51,6 +51,8 @@ class RenderChain
|
||||
PixelFormat fmt,
|
||||
const D3DVIEWPORT9 &final_viewport);
|
||||
|
||||
void set_pass_size(unsigned pass, unsigned width, unsigned height);
|
||||
void set_final_viewport(const D3DVIEWPORT9 &final_viewport);
|
||||
void add_pass(const LinkInfo &info);
|
||||
void add_lut(const std::string &id, const std::string &path, bool smooth);
|
||||
void add_state_tracker(std::shared_ptr<state_tracker_t> tracker);
|
||||
|
Loading…
x
Reference in New Issue
Block a user