From f056b622bcad7c19a521a9a5a181471ff301f5f2 Mon Sep 17 00:00:00 2001 From: ImJezze Date: Sun, 19 Jun 2016 14:18:40 +0200 Subject: [PATCH] Fixed crash of D3D when sliders menu is openend and resizing the window or switching between window and full screen mode --- src/osd/modules/render/d3d/d3dhlsl.cpp | 215 +++++++-------- src/osd/modules/render/d3d/d3dhlsl.h | 20 +- src/osd/modules/render/drawd3d.cpp | 345 +++++++++++++++---------- src/osd/modules/render/drawd3d.h | 19 +- 4 files changed, 322 insertions(+), 277 deletions(-) diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 9dcb3f06f8e..be7138bfe6f 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -43,23 +43,13 @@ static void get_vector(const char *data, int count, float *out, bool report_erro //============================================================ shaders::shaders() : - d3dintf(nullptr), machine(nullptr), d3d(nullptr), num_screens(0), curr_screen(0), - avi_output_file(nullptr), avi_frame(0), avi_copy_surface(nullptr), avi_copy_texture(nullptr), avi_final_target(nullptr), avi_final_texture(nullptr), + d3dintf(nullptr), machine(nullptr), d3d(nullptr), post_fx_enable(false), oversampling_enable(false), paused(true), num_screens(0), curr_screen(0), lastidx(-1), + shadow_texture(nullptr), options(nullptr), avi_output_file(nullptr), avi_frame(0), avi_copy_surface(nullptr), avi_copy_texture(nullptr), avi_final_target(nullptr), avi_final_texture(nullptr), black_surface(nullptr), black_texture(nullptr), render_snap(false), snap_rendered(false), snap_copy_target(nullptr), snap_copy_texture(nullptr), snap_target(nullptr), snap_texture(nullptr), - snap_width(0), snap_height(0), lines_pending(false), backbuffer(nullptr), curr_effect(nullptr), default_effect(nullptr), prescale_effect(nullptr), post_effect(nullptr), distortion_effect(nullptr), - focus_effect(nullptr), phosphor_effect(nullptr), deconverge_effect(nullptr), color_effect(nullptr), ntsc_effect(nullptr), bloom_effect(nullptr), - downsample_effect(nullptr), vector_effect(nullptr), fsfx_vertices(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr) + snap_width(0), snap_height(0), lines_pending(false), initialized(false), backbuffer(nullptr), curr_effect(nullptr), default_effect(nullptr), prescale_effect(nullptr), post_effect(nullptr), + distortion_effect(nullptr), focus_effect(nullptr), phosphor_effect(nullptr), deconverge_effect(nullptr), color_effect(nullptr), ntsc_effect(nullptr), bloom_effect(nullptr), + downsample_effect(nullptr), vector_effect(nullptr), fsfx_vertices(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr), targethead(nullptr), cachehead(nullptr) { - master_enable = false; - vector_enable = true; - oversampling_enable = false; - shadow_texture = nullptr; - options = nullptr; - paused = true; - lastidx = -1; - targethead = nullptr; - cachehead = nullptr; - initialized = false; } @@ -74,6 +64,12 @@ shaders::~shaders() delete slider; } + if (options != nullptr) + { + global_free(options); + options = nullptr; + } + cache_target *currcache = cachehead; while(cachehead != nullptr) { @@ -98,7 +94,7 @@ shaders::~shaders() void shaders::window_save() { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -130,7 +126,7 @@ void shaders::window_save() void shaders::window_record() { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -155,7 +151,7 @@ void shaders::window_record() void shaders::avi_update_snap(IDirect3DSurface9 *surface) { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -208,7 +204,7 @@ void shaders::avi_update_snap(IDirect3DSurface9 *surface) void shaders::render_snapshot(IDirect3DSurface9 *surface) { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -310,7 +306,7 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) void shaders::record_texture() { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -353,7 +349,7 @@ void shaders::record_texture() void shaders::end_avi_recording() { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -368,53 +364,13 @@ void shaders::end_avi_recording() } -//============================================================ -// shaders::toggle -//============================================================ - -void shaders::toggle(std::vector& sliders) -{ - if (master_enable) - { - if (initialized) - { - // free shader resources before renderer resources - delete_resources(false); - } - - master_enable = !master_enable; - - // free shader resources and re-create - d3d->device_delete_resources(); - d3d->device_create_resources(); - } - else - { - master_enable = !master_enable; - - // free shader resources and re-create - d3d->device_delete_resources(); - d3d->device_create_resources(); - - if (!initialized) - { - // re-create shader resources after renderer resources - bool failed = create_resources(false, sliders); - if (failed) - { - master_enable = false; - } - } - } -} - //============================================================ // shaders::begin_avi_recording //============================================================ void shaders::begin_avi_recording(const char *name) { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -573,7 +529,7 @@ void shaders::remove_render_target(d3d_render_target *rt) void shaders::set_texture(texture_info *texture) { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -602,53 +558,64 @@ void shaders::set_texture(texture_info *texture) // shaders::init //============================================================ -void shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer) +bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer) { + osd_printf_verbose("Direct3D: Initialize HLSL\n"); + + if (initialized) + { + return false; + } + + // check if no driver loaded (not all settings might be loaded yet) + if (&machine->system() == &GAME_NAME(___empty)) + { + return false; + } + + // check if another driver is loaded and reset last options + if (std::strcmp(machine->system().name, last_system_name) != 0) + { + strncpy(last_system_name, machine->system().name, sizeof(last_system_name)); + + last_options.params_init = false; + } + d3dx9_dll = osd::dynamic_module::open({ "d3dx9_43.dll" }); d3dx_create_effect_from_file_ptr = d3dx9_dll->bind("D3DXCreateEffectFromFileW"); if (!d3dx_create_effect_from_file_ptr) { osd_printf_verbose("Direct3D: Unable to find D3DXCreateEffectFromFileW\n"); - d3dintf->post_fx_available = false; - return; + return false; } d3dintf->post_fx_available = true; + this->d3dintf = d3dintf; this->machine = machine; this->d3d = renderer; - this->options = renderer->get_shaders_options(); - - // check if no driver loaded (not all settings might be loaded yet) - if (&machine->system() == &GAME_NAME(___empty)) - { - return; - } - - // check if another driver is loaded - if (std::strcmp(machine->system().name, last_system_name) != 0) - { - strncpy(last_system_name, machine->system().name, sizeof(last_system_name)); - - options->params_init = false; - last_options.params_init = false; - } enumerate_screens(); windows_options &winoptions = downcast(machine->options()); - master_enable = winoptions.d3d_hlsl_enable(); + post_fx_enable = winoptions.d3d_hlsl_enable(); oversampling_enable = winoptions.d3d_hlsl_oversampling(); snap_width = winoptions.d3d_snap_width(); snap_height = winoptions.d3d_snap_height(); + this->options = (hlsl_options*)global_alloc_clear(); + this->options->params_init = false; + + // copy last options if initialized if (last_options.params_init) { + osd_printf_verbose("Direct3D: First restore options\n"); options = &last_options; } + // read options if not initialized if (!options->params_init) { strncpy(options->shadow_mask_texture, winoptions.screen_shadow_mask_texture(), sizeof(options->shadow_mask_texture)); @@ -719,9 +686,19 @@ void shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r options->bloom_level8_weight = winoptions.screen_bloom_lvl8_weight(); options->params_init = true; + + osd_printf_verbose("Direct3D: First store options\n"); + last_options = *options; + options = &last_options; } options->params_dirty = true; + + initialized = true; + + osd_printf_verbose("Direct3D: HLSL initialized\n"); + + return true; } @@ -734,7 +711,7 @@ void shaders::init_fsfx_quad(void *vertbuf) // Called at the start of each frame by the D3D code in order to reserve two triangles // that are guaranteed to be at a fixed position so as to simply use D3DPT_TRIANGLELIST, 0, 2 // instead of having to do bookkeeping about a specific screen quad - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -805,15 +782,16 @@ void shaders::init_fsfx_quad(void *vertbuf) // shaders::create_resources //============================================================ -int shaders::create_resources(bool reset, std::vector& sliders) +int shaders::create_resources() { - if (!master_enable || !d3dintf->post_fx_available) + if (!initialized || !enabled()) { return 0; } if (last_options.params_init) { + osd_printf_verbose("Direct3D: Restore options\n"); options = &last_options; } @@ -982,11 +960,6 @@ int shaders::create_resources(bool reset, std::vector& sliders) distortion_effect->add_uniform("SmoothBorderAmount", uniform::UT_FLOAT, uniform::CU_POST_SMOOTH_BORDER); distortion_effect->add_uniform("ReflectionAmount", uniform::UT_FLOAT, uniform::CU_POST_REFLECTION); - initialized = true; - - std::vector my_sliders = init_slider_list(); - sliders.insert(sliders.end(), my_sliders.begin(), my_sliders.end()); - return 0; } @@ -997,7 +970,7 @@ int shaders::create_resources(bool reset, std::vector& sliders) void shaders::begin_draw() { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -1094,7 +1067,7 @@ void shaders::blit( void shaders::end_frame() { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -1587,7 +1560,7 @@ void shaders::ui_pass(poly_info *poly, int vertnum) void shaders::render_quad(poly_info *poly, int vertnum) { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -1644,7 +1617,7 @@ void shaders::render_quad(poly_info *poly, int vertnum) curr_screen++; } - else if (PRIMFLAG_GET_VECTOR(poly->get_flags()) && vector_enable) + else if (PRIMFLAG_GET_VECTOR(poly->get_flags())) { lines_pending = true; @@ -1673,7 +1646,7 @@ void shaders::render_quad(poly_info *poly, int vertnum) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); } } - else if (PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable) + else if (PRIMFLAG_GET_VECTORBUF(poly->get_flags())) { curr_screen = curr_screen < num_screens ? curr_screen : 0; @@ -1748,7 +1721,7 @@ void shaders::render_quad(poly_info *poly, int vertnum) void shaders::end_draw() { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return; } @@ -1790,6 +1763,11 @@ bool shaders::add_cache_target(renderer_d3d9* d3d, texture_info* texture, int so d3d_render_target* shaders::get_texture_target(render_primitive *prim, texture_info *texture) { + if (!enabled()) + { + return nullptr; + } + auto win = d3d->assert_window(); int target_width = int(prim->get_quad_width() + 0.5f); @@ -1810,7 +1788,7 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, texture_i // check if the size of the screen quad has changed if (target->target_width != target_width || target->target_height != target_height) { - osd_printf_verbose("get_texture_target() - invalid size\n"); + osd_printf_verbose("Direct3D: Get texture target - invalid size\n"); return nullptr; } } @@ -1821,7 +1799,7 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, texture_i d3d_render_target* shaders::get_vector_target(render_primitive *prim) { - if (!vector_enable) + if (!enabled()) { return nullptr; } @@ -1850,7 +1828,7 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim) // check if the size of the screen quad has changed if (target->target_width != target_width || target->target_height != target_height) { - osd_printf_verbose("get_vector_target() - invalid size\n"); + osd_printf_verbose("Direct3D: Get vector target - invalid size\n"); return nullptr; } } @@ -1859,8 +1837,13 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim) return target; } -void shaders::create_vector_target(render_primitive *prim) +bool shaders::create_vector_target(render_primitive *prim) { + if (!enabled()) + { + return false; + } + auto win = d3d->assert_window(); // source and target size are the same for vector targets @@ -1876,11 +1859,13 @@ void shaders::create_vector_target(render_primitive *prim) std::swap(target_width, target_height); } - osd_printf_verbose("create_vector_target() - %d, %d\n", target_width, target_height); + osd_printf_verbose("Direct3D: Create vector target - %dx%d\n", target_width, target_height); if (!add_render_target(d3d, prim, nullptr, source_width, source_height, target_width, target_height)) { - vector_enable = false; + return false; } + + return true; } @@ -1966,7 +1951,7 @@ void shaders::enumerate_screens() bool shaders::register_texture(render_primitive *prim, texture_info *texture) { - if (!master_enable || !d3dintf->post_fx_available) + if (!enabled()) { return false; } @@ -1985,7 +1970,7 @@ bool shaders::register_texture(render_primitive *prim, texture_info *texture) std::swap(target_width, target_height); } - osd_printf_verbose("register_texture() - %d, %d\n", target_width, target_height); + osd_printf_verbose("Direct3D: Register texture - %dx%d\n", target_width, target_height); if (!add_render_target(d3d, prim, texture, source_width, source_height, target_width, target_height)) { return false; @@ -1999,21 +1984,21 @@ bool shaders::register_texture(render_primitive *prim, texture_info *texture) // shaders::delete_resources //============================================================ -void shaders::delete_resources(bool reset) +void shaders::delete_resources() { - if (!master_enable || !d3dintf->post_fx_available) + if (!initialized || !enabled()) { return; } + end_avi_recording(); + if (options != nullptr) { + osd_printf_verbose("Direct3D: Store options\n"); last_options = *options; - options = nullptr; } - initialized = false; - cache_target *currcache = cachehead; while(cachehead != nullptr) { @@ -2490,9 +2475,9 @@ void *shaders::get_slider_option(int id, int index) return nullptr; } -std::vector shaders::init_slider_list() +void shaders::init_slider_list() { - std::vector sliders; + m_sliders.clear(); for (slider* slider : internal_sliders) { @@ -2503,7 +2488,7 @@ std::vector shaders::init_slider_list() auto first_screen = machine->first_screen(); if (first_screen == nullptr) { - return sliders; + return; } int screen_type = first_screen->screen_type(); @@ -2559,12 +2544,10 @@ std::vector shaders::init_slider_list() item.flags = 0; item.ref = core_slider; item.type = ui::menu_item_type::SLIDER; - sliders.push_back(item); + m_sliders.push_back(item); } } } - - return sliders; } diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h index 3c9daa3c6ad..1b3fdc1fa2d 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.h +++ b/src/osd/modules/render/d3d/d3dhlsl.h @@ -301,14 +301,13 @@ public: shaders(); ~shaders(); - void init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer); + bool init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer); - bool enabled() { return master_enable; } - void toggle(std::vector& sliders); + bool enabled() { return post_fx_enable && d3dintf->post_fx_available; } + void toggle() { post_fx_enable = initialized && !post_fx_enable; } - bool vector_enabled() { return master_enable && vector_enable; } d3d_render_target* get_vector_target(render_primitive *prim); - void create_vector_target(render_primitive *prim); + bool create_vector_target(render_primitive *prim); void begin_frame(); void end_frame(); @@ -339,13 +338,14 @@ public: void remove_render_target(int source_width, int source_height, UINT32 screen_index, UINT32 page_index); void remove_render_target(d3d_render_target *rt); - int create_resources(bool reset, std::vector& sliders); - void delete_resources(bool reset); + int create_resources(); + void delete_resources(); // slider-related functions virtual INT32 slider_changed(running_machine &machine, void *arg, int /*id*/, std::string *str, INT32 newval) override; slider_state* slider_alloc(running_machine &machine, int id, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, void *arg); - std::vector init_slider_list(); + void init_slider_list(); + std::vector get_slider_list() { return m_sliders; } void *get_slider_option(int id, int index = 0); private: @@ -382,8 +382,7 @@ private: running_machine * machine; renderer_d3d9 * d3d; // D3D renderer - bool master_enable; // overall enable flag - bool vector_enable; // vector post-processing enable flag + bool post_fx_enable; // overall enable flag bool oversampling_enable; // oversampling enable flag bool paused; // whether or not rendering is currently paused int num_screens; // number of emulated physical screens @@ -442,6 +441,7 @@ private: cache_target * cachehead; std::vector internal_sliders; + std::vector m_sliders; static slider_desc s_sliders[]; static hlsl_options last_options; // last used options diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp index 4fb1696a1eb..ce024866319 100644 --- a/src/osd/modules/render/drawd3d.cpp +++ b/src/osd/modules/render/drawd3d.cpp @@ -137,7 +137,7 @@ int renderer_d3d9::create() void renderer_d3d9::toggle_fsfx() { - set_restarting(true); + set_toggle(true); } void renderer_d3d9::record() @@ -184,14 +184,14 @@ render_primitive_list *renderer_d3d9::get_primitives() bool renderer_d3d9::init(running_machine &machine) { d3dintf = global_alloc(d3d_base); - + d3dintf->d3d9_dll = osd::dynamic_module::open({ "d3d9.dll" }); d3d9_create_fn d3d9_create_ptr = d3dintf->d3d9_dll->bind("Direct3DCreate9"); if (d3d9_create_ptr == nullptr) { osd_printf_verbose("Direct3D: Unable to find Direct3D 9 runtime library\n"); - return true; + return true; } d3dintf->d3dobj = (*d3d9_create_ptr)(D3D_SDK_VERSION); @@ -520,21 +520,23 @@ texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, U renderer_d3d9::renderer_d3d9(std::shared_ptr window) : osd_renderer(window, FLAG_NONE), m_adapter(0), m_width(0), m_height(0), m_refresh(0), m_create_error_count(0), m_device(nullptr), m_gamma_supported(0), m_pixformat(), - m_vertexbuf(nullptr), m_lockedbuf(nullptr), m_numverts(0), m_vectorbatch(nullptr), m_batchindex(0), m_numpolys(0), m_restarting(false), m_mod2x_supported(0), m_mod4x_supported(0), + m_vertexbuf(nullptr), m_lockedbuf(nullptr), m_numverts(0), m_vectorbatch(nullptr), m_batchindex(0), m_numpolys(0), m_toggle(false), m_screen_format(), m_last_texture(nullptr), m_last_texture_flags(0), m_last_blendenable(0), m_last_blendop(0), m_last_blendsrc(0), m_last_blenddst(0), m_last_filter(0), - m_last_wrap(), m_last_modmode(0), m_hlsl_buf(nullptr), m_shaders(nullptr), m_shaders_options(nullptr), m_texture_manager(nullptr) + m_last_wrap(), m_last_modmode(0), m_hlsl_buf(nullptr), m_shaders(nullptr), m_texture_manager(nullptr) { } int renderer_d3d9::initialize() { + osd_printf_verbose("Direct3D: Initialize\n"); + // configure the adapter for the mode we want if (config_adapter_mode()) { return false; } - // create the device immediately for the full screen case (defer for window mode) + // create the device immediately for the full screen case (defer for window mode in update_window_size()) auto win = assert_window(); if (win->fullscreen() && device_create(win->main_window()->platform_window())) { @@ -552,13 +554,24 @@ int renderer_d3d9::pre_window_draw_check() if (win->m_resize_state == RESIZE_STATE_RESIZING) return 0; - // if we're restarting the renderer, leave things alone - if (m_restarting) + // check if shaders should be toggled + if (m_toggle) { - m_sliders.clear(); - m_shaders->toggle(m_sliders); + m_toggle = false; - m_restarting = false; + // free resources + device_delete_resources(); + + m_shaders->toggle(); + m_sliders_dirty = true; + + // re-create resources + if (device_create_resources()) + { + osd_printf_verbose("Direct3D: failed to recreate resources for device; failing permanently\n"); + device_delete(); + return 1; + } } // if we have a device, check the cooperative level @@ -630,11 +643,14 @@ void d3d_texture_manager::update_textures() } else if(PRIMFLAG_GET_VECTORBUF(prim.flags)) { - if (m_renderer->get_shaders()->vector_enabled()) + if (m_renderer->get_shaders()->enabled()) { if (!m_renderer->get_shaders()->get_vector_target(&prim)) { - m_renderer->get_shaders()->create_vector_target(&prim); + if (!m_renderer->get_shaders()->create_vector_target(&prim)) + { + d3dintf->post_fx_available = false; + } } } } @@ -736,6 +752,65 @@ void renderer_d3d9::end_frame() osd_printf_verbose("Direct3D: Error %08lX during device present call\n", result); } +void renderer_d3d9::update_presentation_parameters() +{ + auto win = assert_window(); + + memset(&m_presentation, 0, sizeof(m_presentation)); + m_presentation.BackBufferWidth = m_width; + m_presentation.BackBufferHeight = m_height; + m_presentation.BackBufferFormat = m_pixformat; + m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1; + m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE; + m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD; + m_presentation.hDeviceWindow = win->platform_window(); + m_presentation.Windowed = !win->fullscreen() || win->win_has_menu(); + m_presentation.EnableAutoDepthStencil = FALSE; + m_presentation.AutoDepthStencilFormat = D3DFMT_D16; + m_presentation.Flags = 0; + m_presentation.FullScreen_RefreshRateInHz = m_refresh; + m_presentation.PresentationInterval = ( + (video_config.triplebuf && win->fullscreen()) + || video_config.waitvsync + || video_config.syncrefresh) + ? D3DPRESENT_INTERVAL_ONE + : D3DPRESENT_INTERVAL_IMMEDIATE; +} + + +void renderer_d3d9::update_gamma_ramp() +{ + if (m_gamma_supported) + { + return; + } + + auto win = assert_window(); + + // create a standard ramp + D3DGAMMARAMP ramp; + + // set the gamma if we need to + if (win->fullscreen()) + { + // only set the gamma if it's not 1.0 + windows_options &options = downcast(win->machine().options()); + float brightness = options.full_screen_brightness(); + float contrast = options.full_screen_contrast(); + float gamma = options.full_screen_gamma(); + if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f) + { + for (int i = 0; i < 256; i++) + { + ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8; + } + } + } + + m_device->SetGammaRamp(0, 0, &ramp); +} + + //============================================================ // device_create //============================================================ @@ -749,22 +824,8 @@ int renderer_d3d9::device_create(HWND device_hwnd) } // verify the caps - int verify = device_verify_caps(); - if (verify == 2) + if (device_verify_caps()) { - osd_printf_error("Error: Device does not meet minimum requirements for Direct3D rendering\n"); - return 1; - } - if (verify == 1) - { - osd_printf_warning("Warning: Device may not perform well for Direct3D rendering\n"); - } - - // verify texture formats - HRESULT result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); - if (FAILED(result)) - { - osd_printf_error("Error: A8R8G8B8 format textures not supported\n"); return 1; } @@ -773,12 +834,20 @@ int renderer_d3d9::device_create(HWND device_hwnd) try_again: // try for XRGB first m_screen_format = D3DFMT_X8R8G8B8; - result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0, D3DRTYPE_TEXTURE, m_screen_format); + HRESULT result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, + m_texture_manager->is_dynamic_supported() + ? D3DUSAGE_DYNAMIC + : 0, + D3DRTYPE_TEXTURE, m_screen_format); if (FAILED(result)) { // if not, try for ARGB m_screen_format = D3DFMT_A8R8G8B8; - result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0, D3DRTYPE_TEXTURE, m_screen_format); + result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, + m_texture_manager->is_dynamic_supported() + ? D3DUSAGE_DYNAMIC + : 0, + D3DRTYPE_TEXTURE, m_screen_format); if (FAILED(result) && m_texture_manager->is_dynamic_supported()) { m_texture_manager->set_dynamic_supported(FALSE); @@ -791,29 +860,12 @@ try_again: } } - auto win = assert_window(); - // initialize the D3D presentation parameters - memset(&m_presentation, 0, sizeof(m_presentation)); - m_presentation.BackBufferWidth = m_width; - m_presentation.BackBufferHeight = m_height; - m_presentation.BackBufferFormat = m_pixformat; - m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1; - m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE; - m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD; - m_presentation.hDeviceWindow = win->platform_window(); - m_presentation.Windowed = !win->fullscreen() || win->win_has_menu(); - m_presentation.EnableAutoDepthStencil = FALSE; - m_presentation.AutoDepthStencilFormat = D3DFMT_D16; - m_presentation.Flags = 0; - m_presentation.FullScreen_RefreshRateInHz = m_refresh; - m_presentation.PresentationInterval = ((video_config.triplebuf && win->fullscreen()) || - video_config.waitvsync || video_config.syncrefresh) ? - D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + update_presentation_parameters(); // create the D3D device - result = d3dintf->d3dobj->CreateDevice(m_adapter, D3DDEVTYPE_HAL, device_hwnd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device); + result = d3dintf->d3dobj->CreateDevice( + m_adapter, D3DDEVTYPE_HAL, device_hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device); if (FAILED(result)) { // if we got a "DEVICELOST" error, it may be transitory; count it and only fail if @@ -834,52 +886,7 @@ try_again: m_create_error_count = 0; osd_printf_verbose("Direct3D: Device created at %dx%d\n", m_width, m_height); - // set the gamma if we need to - if (win->fullscreen()) - { - // only set the gamma if it's not 1.0f - windows_options &options = downcast(win->machine().options()); - float brightness = options.full_screen_brightness(); - float contrast = options.full_screen_contrast(); - float gamma = options.full_screen_gamma(); - if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f) - { - // warn if we can't do it - if (!m_gamma_supported) - { - osd_printf_warning("Direct3D: Warning - device does not support full screen gamma correction.\n"); - } - else - { - // create a standard ramp and set it - D3DGAMMARAMP ramp; - for (int i = 0; i < 256; i++) - { - ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8; - } - m_device->SetGammaRamp(0, 0, &ramp); - } - } - } - - // create shader options only once - if (m_shaders_options == nullptr) - { - m_shaders_options = (hlsl_options*)global_alloc_clear(); - m_shaders_options->params_init = false; - } - - m_shaders = (shaders*)global_alloc_clear(); - m_shaders->init(d3dintf, &win->machine(), this); - - m_sliders.clear(); - int failed = m_shaders->create_resources(false, m_sliders); - if (failed) - { - return failed; - } - - m_sliders_dirty = true; + update_gamma_ramp(); return device_create_resources(); } @@ -891,11 +898,35 @@ try_again: int renderer_d3d9::device_create_resources() { + auto win = assert_window(); + + // create shaders only once + if (m_shaders == nullptr) + { + m_shaders = (shaders*)global_alloc_clear(); + } + + if (m_shaders->init(d3dintf, &win->machine(), this)) + { + m_shaders->init_slider_list(); + m_sliders_dirty = true; + } + + // create resources + if (m_shaders->create_resources()) + { + osd_printf_verbose("Direct3D: failed to create HLSL resources for device\n"); + return 1; + } + // allocate a vertex buffer to use - HRESULT result = m_device->CreateVertexBuffer(sizeof(vertex) * VERTEX_BUFFER_SIZE, - D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, - VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW), - D3DPOOL_DEFAULT, &m_vertexbuf, nullptr); + HRESULT result = m_device->CreateVertexBuffer( + sizeof(vertex) * VERTEX_BUFFER_SIZE, + D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, + VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available) + ? D3DFVF_XYZW + : D3DFVF_XYZRHW), + D3DPOOL_DEFAULT, &m_vertexbuf, nullptr); if (FAILED(result)) { osd_printf_error("Error creating vertex buffer (%08X)\n", (UINT32)result); @@ -903,8 +934,10 @@ int renderer_d3d9::device_create_resources() } // set the vertex format - result = m_device->SetFVF((D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled() && - d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW))); + result = m_device->SetFVF( + (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available) + ? D3DFVF_XYZW + : D3DFVF_XYZRHW))); if (FAILED(result)) { osd_printf_error("Error setting vertex format (%08X)\n", (UINT32)result); @@ -955,16 +988,15 @@ int renderer_d3d9::device_create_resources() renderer_d3d9::~renderer_d3d9() { - if (get_shaders() != nullptr && get_shaders()->recording()) - get_shaders()->window_record(); - device_delete(); - if (m_shaders_options != nullptr) - { - global_free(m_shaders_options); - m_shaders_options = nullptr; - } + // todo: throws error when switching from full screen to window mode + //if (m_shaders != nullptr) + //{ + // // delete the HLSL interface + // global_free(m_shaders); + // m_shaders = nullptr; + //} } void renderer_d3d9::exit() @@ -978,19 +1010,11 @@ void renderer_d3d9::exit() void renderer_d3d9::device_delete() { - if (m_shaders != nullptr) - { - // free our effects - m_sliders.clear(); - m_shaders->delete_resources(false); - - // delete the HLSL interface - global_free(m_shaders); - } - // free our base resources device_delete_resources(); + // we do not delete the HLSL interface here + if (m_texture_manager != nullptr) { global_free(m_texture_manager); @@ -1012,6 +1036,11 @@ void renderer_d3d9::device_delete() void renderer_d3d9::device_delete_resources() { + if (m_shaders != nullptr) + { + m_shaders->delete_resources(); + } + if (m_texture_manager != nullptr) { m_texture_manager->delete_resources(); @@ -1032,12 +1061,14 @@ void renderer_d3d9::device_delete_resources() int renderer_d3d9::device_verify_caps() { - int retval = 0; + int verify = 0; D3DCAPS9 caps; HRESULT result = d3dintf->d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps); if (FAILED(result)) + { osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result); + } if (caps.MaxPixelShader30InstructionSlots < 512) { @@ -1049,40 +1080,59 @@ int renderer_d3d9::device_verify_caps() if (!(caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)) { osd_printf_verbose("Direct3D: Error - Device does not support immediate presentations\n"); - retval = 2; + verify = 2; } if (!(caps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)) { osd_printf_verbose("Direct3D: Error - Device does not support per-refresh presentations\n"); - retval = 2; + verify = 2; } // verify device capabilities if (!(caps.DevCaps & D3DDEVCAPS_CANRENDERAFTERFLIP)) { osd_printf_verbose("Direct3D: Warning - Device does not support queued rendering after a page flip\n"); - retval = 1; + verify = 1; } if (!(caps.DevCaps & D3DDEVCAPS_HWRASTERIZATION)) { osd_printf_verbose("Direct3D: Warning - Device does not support hardware rasterization\n"); - retval = 1; + verify = 1; } // verify texture operation capabilities if (!(caps.TextureOpCaps & D3DTEXOPCAPS_MODULATE)) { osd_printf_verbose("Direct3D: Warning - Device does not support texture modulation\n"); - retval = 1; + verify = 1; } - // set a simpler flag to indicate mod2x and mod4x texture modes - m_mod2x_supported = ((caps.TextureOpCaps & D3DTEXOPCAPS_MODULATE2X) != 0); - m_mod4x_supported = ((caps.TextureOpCaps & D3DTEXOPCAPS_MODULATE4X) != 0); - m_gamma_supported = ((caps.Caps2 & D3DCAPS2_FULLSCREENGAMMA) != 0); + if (!m_gamma_supported) + { + osd_printf_warning("Direct3D: Warning - device does not support full screen gamma correction.\n"); + } - return retval; + // verify texture formats + result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); + if (FAILED(result)) + { + osd_printf_error("Error: A8R8G8B8 format textures not supported\n"); + verify = 2; + } + + if (verify == 2) + { + osd_printf_error("Error: Device does not meet minimum requirements for Direct3D rendering\n"); + return 1; + } + if (verify == 1) + { + osd_printf_warning("Warning: Device may not perform well for Direct3D rendering\n"); + return 1; + } + + return 0; } @@ -1103,8 +1153,6 @@ int renderer_d3d9::device_test_cooperative() osd_printf_verbose("Direct3D: resetting device\n"); // free all existing resources and call reset on the device - m_sliders.clear(); - m_shaders->delete_resources(true); device_delete_resources(); result = m_device->Reset(&m_presentation); @@ -1122,15 +1170,8 @@ int renderer_d3d9::device_test_cooperative() device_delete(); return 1; } - - m_sliders.clear(); - if (m_shaders->create_resources(true, m_sliders)) - { - osd_printf_verbose("Direct3D: failed to recreate HLSL resources for device; failing permanently\n"); - device_delete(); - return 1; - } } + return 0; } @@ -1870,6 +1911,28 @@ void renderer_d3d9::primitive_flush_pending() } +std::vector renderer_d3d9::get_slider_list() +{ + m_sliders_dirty = false; + + std::vector sliders; + sliders.insert(sliders.end(), m_sliders.begin(), m_sliders.end()); + + if (m_shaders != nullptr && m_shaders->enabled()) + { + std::vector s_slider = m_shaders->get_slider_list(); + sliders.insert(sliders.end(), s_slider.begin(), s_slider.end()); + } + + return sliders; +} + +void renderer_d3d9::set_sliders_dirty() +{ + m_sliders_dirty = true; +} + + //============================================================ // texture_info destructor //============================================================ diff --git a/src/osd/modules/render/drawd3d.h b/src/osd/modules/render/drawd3d.h index 1c044299b36..61ea0bc4a65 100644 --- a/src/osd/modules/render/drawd3d.h +++ b/src/osd/modules/render/drawd3d.h @@ -23,6 +23,7 @@ #undef interface #include "d3d/d3dcomm.h" +#include "sliderdirtynotifier.h" #include "modules/lib/osdlib.h" //============================================================ @@ -49,7 +50,7 @@ class shaders; struct hlsl_options; /* renderer is the information about Direct3D for the current screen */ -class renderer_d3d9 : public osd_renderer +class renderer_d3d9 : public osd_renderer, public slider_dirty_notifier { public: renderer_d3d9(std::shared_ptr window); @@ -64,6 +65,8 @@ public: virtual void save() override; virtual void record() override; virtual void toggle_fsfx() override; + virtual std::vector get_slider_list() override; + virtual void set_sliders_dirty() override; int initialize(); @@ -71,6 +74,8 @@ public: int device_create_resources(); void device_delete(); void device_delete_resources(); + void update_presentation_parameters(); + void update_gamma_ramp(); int device_verify_caps(); int device_test_cooperative(); @@ -117,9 +122,7 @@ public: VOID ** get_locked_buffer_ptr()const { return (VOID **)&m_lockedbuf; } void set_locked_buffer(vertex *lockedbuf) { m_lockedbuf = lockedbuf; } - void set_restarting(bool restarting) { m_restarting = restarting; } - bool is_mod2x_supported() const { return (bool)m_mod2x_supported; } - bool is_mod4x_supported() const { return (bool)m_mod4x_supported; } + void set_toggle(bool toggle) { m_toggle = toggle; } D3DFORMAT get_screen_format() const { return m_screen_format; } D3DFORMAT get_pixel_format() const { return m_pixformat; } @@ -131,7 +134,6 @@ public: texture_info * get_default_texture(); shaders * get_shaders() const { return m_shaders; } - hlsl_options * get_shaders_options() const { return m_shaders_options; } private: int m_adapter; // ordinal adapter number @@ -156,10 +158,8 @@ private: poly_info m_poly[VERTEX_BUFFER_SIZE/3];// array to hold polygons as they are created int m_numpolys; // number of accumulated polygons - bool m_restarting; // if we're restarting + bool m_toggle; // if we're toggle fsfx - int m_mod2x_supported; // is D3DTOP_MODULATE2X supported? - int m_mod4x_supported; // is D3DTOP_MODULATE4X supported? D3DFORMAT m_screen_format; // format to use for screen textures texture_info * m_last_texture; // previous texture @@ -174,9 +174,8 @@ private: void * m_hlsl_buf; // HLSL vertex data shaders * m_shaders; // HLSL interface - hlsl_options * m_shaders_options; // HLSL options - d3d_texture_manager * m_texture_manager; // texture manager + d3d_texture_manager * m_texture_manager; // texture manager }; #endif // OSD_WINDOWS