diff options
Diffstat (limited to 'src/osd/modules/render/drawd3d.cpp')
-rw-r--r-- | src/osd/modules/render/drawd3d.cpp | 1087 |
1 files changed, 498 insertions, 589 deletions
diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp index fd1331c47eb..542e2f8955d 100644 --- a/src/osd/modules/render/drawd3d.cpp +++ b/src/osd/modules/render/drawd3d.cpp @@ -8,25 +8,137 @@ // MAME headers #include "emu.h" +#include "emuopts.h" #include "render.h" - #include "rendutil.h" -#include "emuopts.h" -#include "aviio.h" +#include "screen.h" // MAMEOS headers -#include "winmain.h" -#include "window.h" #include "drawd3d.h" -#include "modules/render/d3d/d3dhlsl.h" + +#include "d3d/d3dhlsl.h" + +#include "render_module.h" + +// from OSD implementation +#include "window.h" +#include "winmain.h" + +// general OSD headers #include "modules/monitor/monitor_module.h" + +// lib/util +#include "aviio.h" + #include <utility> + +//============================================================ +// OSD MODULE +//============================================================ + +namespace osd { + +namespace { + +class video_d3d : public osd_module, public render_module +{ +public: + video_d3d() + : osd_module(OSD_RENDERER_PROVIDER, "d3d") + , m_options(nullptr) + { + } + + virtual bool probe() override; + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE; } + +private: + using d3d9_create_fn = IDirect3D9 *(WINAPI *)(UINT); + + dynamic_module::ptr m_d3d9_dll; + Microsoft::WRL::ComPtr<IDirect3D9> m_d3dobj; + osd_options const *m_options; +}; + + +//============================================================ +// video_d3d::probe +//============================================================ + +bool video_d3d::probe() +{ + // do a dry run of loading the Direct3D 9 DLL + return dynamic_module::open({ "d3d9.dll" })->bind<d3d9_create_fn>("Direct3DCreate9") != nullptr; +} + + +//============================================================ +// video_d3d::init +//============================================================ + +int video_d3d::init(osd_interface &osd, osd_options const &options) +{ + m_options = &options; + + m_d3d9_dll = dynamic_module::open({ "d3d9.dll" }); + auto const d3d9_create_ptr = m_d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9"); + if (!d3d9_create_ptr) + { + osd_printf_warning("Direct3D: Could not find Direct3DCreate9 function in d3d9.dll\n"); + m_d3d9_dll.reset(); + m_options = nullptr; + return -1; + } + + m_d3dobj.Attach((d3d9_create_ptr)(D3D_SDK_VERSION)); + if (!m_d3dobj) + { + osd_printf_warning("Direct3D: Unable to initialize Direct3D 9\n"); + m_d3d9_dll.reset(); + m_options = nullptr; + return -1; + } + + osd_printf_verbose("Direct3D: Using Direct3D 9\n"); + + return 0; +} + + +//============================================================ +// video_d3d::exit //============================================================ -// TYPE DEFINITIONS + +void video_d3d::exit() +{ + m_d3dobj.Reset(); + m_d3d9_dll.reset(); + m_options = nullptr; +} + + //============================================================ +// video_d3d::create +//============================================================ + +std::unique_ptr<osd_renderer> video_d3d::create(osd_window &window) +{ + return std::make_unique<renderer_d3d9>(window, m_d3dobj); +} + +} // anonymous namespace + +} // namespace osd + +MODULE_DEFINITION(RENDERER_D3D, osd::video_d3d) -typedef IDirect3D9* (WINAPI *d3d9_create_fn)(UINT); //============================================================ @@ -115,13 +227,6 @@ static inline uint32_t ycc_to_rgb(uint8_t y, uint8_t cb, uint8_t cr) //============================================================ -// drawd3d_init -//============================================================ - -static d3d_base * d3dintf; // FIX ME - - -//============================================================ // drawd3d_window_init //============================================================ @@ -173,56 +278,22 @@ void renderer_d3d9::save() render_primitive_list *renderer_d3d9::get_primitives() { RECT client; - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - - HWND hWnd = std::static_pointer_cast<win_window_info>(win)->platform_window(); + HWND hWnd = dynamic_cast<win_window_info &>(window()).platform_window(); if (IsIconic(hWnd)) return nullptr; - GetClientRectExceptMenu(hWnd, &client, win->fullscreen()); + GetClientRectExceptMenu(hWnd, &client, window().fullscreen()); if (rect_width(&client) > 0 && rect_height(&client) > 0) { - win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect()); - win->target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); + window().target()->set_bounds(rect_width(&client), rect_height(&client), window().pixel_aspect()); + window().target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); } if (m_shaders != nullptr) { // do not transform primitives (scale, offset) if shaders are enabled, the shaders will handle the transformation - win->target()->set_transform_container(!m_shaders->enabled()); + window().target()->set_transform_container(!m_shaders->enabled()); } - return &win->target()->get_primitives(); -} - - -//============================================================ -// renderer_d3d9::init -//============================================================ - -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<d3d9_create_fn>("Direct3DCreate9"); - if (d3d9_create_ptr == nullptr) - { - osd_printf_verbose("Direct3D: Unable to find Direct3D 9 runtime library\n"); - return true; - } - - d3dintf->d3dobj = (*d3d9_create_ptr)(D3D_SDK_VERSION); - if (d3dintf->d3dobj == nullptr) - { - osd_printf_verbose("Direct3D: Unable to initialize Direct3D 9\n"); - return true; - } - - osd_printf_verbose("Direct3D: Using Direct3D 9\n"); - - return false; + return &window().target()->get_primitives(); } @@ -237,7 +308,12 @@ int renderer_d3d9::draw(const int update) return check; begin_frame(); + + // reset blend mode + set_blendmode(BLENDMODE_NONE); + process_primitives(); + end_frame(); return 0; @@ -249,8 +325,12 @@ void renderer_d3d9::set_texture(texture_info *texture) { m_last_texture = texture; m_last_texture_flags = (texture == nullptr ? 0 : texture->get_flags()); + if (m_shaders->enabled()) + { + m_shaders->set_texture(texture); + } + HRESULT result = m_device->SetTexture(0, (texture == nullptr) ? get_default_texture()->get_finaltex() : texture->get_finaltex()); - m_shaders->set_texture(texture); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device set_texture call\n", result); } @@ -348,15 +428,20 @@ void renderer_d3d9::set_blendmode(int blendmode) } // adjust the bits that changed + bool new_blend_enable = false; if (blendenable != m_last_blendenable) { m_last_blendenable = blendenable; + if (blendenable) + { + new_blend_enable = true; + } HRESULT result = m_device->SetRenderState(D3DRS_ALPHABLENDENABLE, blendenable); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result); } - if (blendop != m_last_blendop) + if (blendop != m_last_blendop || new_blend_enable) { m_last_blendop = blendop; HRESULT result = m_device->SetRenderState(D3DRS_BLENDOP, blendop); @@ -364,7 +449,7 @@ void renderer_d3d9::set_blendmode(int blendmode) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result); } - if (blendsrc != m_last_blendsrc) + if (blendsrc != m_last_blendsrc || new_blend_enable) { m_last_blendsrc = blendsrc; HRESULT result = m_device->SetRenderState(D3DRS_SRCBLEND, blendsrc); @@ -372,7 +457,7 @@ void renderer_d3d9::set_blendmode(int blendmode) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result); } - if (blenddst != m_last_blenddst) + if (blenddst != m_last_blenddst || new_blend_enable) { m_last_blenddst = blenddst; HRESULT result = m_device->SetRenderState(D3DRS_DESTBLEND, blenddst); @@ -393,27 +478,15 @@ void renderer_d3d9::reset_render_states() m_last_wrap = (D3DTEXTUREADDRESS)-1; } -d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d) +d3d_texture_manager::d3d_texture_manager(renderer_d3d9 &d3d, IDirect3D9 *d3dobj) + : m_renderer(d3d) + , m_default_texture(nullptr) { - m_renderer = d3d; - - m_default_texture = nullptr; - D3DCAPS9 caps; - HRESULT result = d3dintf->d3dobj->GetDeviceCaps(d3d->get_adapter(), D3DDEVTYPE_HAL, &caps); + HRESULT result = d3dobj->GetDeviceCaps(d3d.get_adapter(), D3DDEVTYPE_HAL, &caps); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result); - // check for dynamic texture support - m_dynamic_supported = ((caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0); - if (m_dynamic_supported) - osd_printf_verbose("Direct3D: Using dynamic textures\n"); - - // check for stretchrect support - m_stretch_supported = ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) != 0); - if (m_stretch_supported && video_config.prescale > 1) - osd_printf_verbose("Direct3D: Using StretchRect for prescaling\n"); - // get texture caps m_texture_caps = caps.TextureCaps; m_texture_max_aspect = caps.MaxTextureAspectRatio; @@ -422,35 +495,30 @@ d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d) // pick a YUV texture format m_yuv_format = D3DFMT_UYVY; - result = d3dintf->d3dobj->CheckDeviceFormat(d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY); + result = d3dobj->CheckDeviceFormat(d3d.get_adapter(), D3DDEVTYPE_HAL, d3d.get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY); if (FAILED(result)) { m_yuv_format = D3DFMT_YUY2; - result = d3dintf->d3dobj->CheckDeviceFormat(d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); + result = d3dobj->CheckDeviceFormat(d3d.get_adapter(), D3DDEVTYPE_HAL, d3d.get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); if (FAILED(result)) m_yuv_format = D3DFMT_A8R8G8B8; } osd_printf_verbose("Direct3D: YUV format = %s\n", (m_yuv_format == D3DFMT_YUY2) ? "YUY2" : (m_yuv_format == D3DFMT_UYVY) ? "UYVY" : "RGB"); - auto win = d3d->assert_window(); - // set the max texture size - win->target()->set_max_texture_size(m_texture_max_width, m_texture_max_height); - osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", (int)m_texture_max_width, (int)m_texture_max_height); + d3d.window().target()->set_max_texture_size(m_texture_max_width, m_texture_max_height); + osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", m_texture_max_width, m_texture_max_height); } void d3d_texture_manager::create_resources() { - auto win = m_renderer->assert_window(); - m_default_bitmap.allocate(8, 8); - m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); - if (m_default_bitmap.valid()) { - render_texinfo texture; + m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); // fake in the basic data so it looks like it came from render.c + render_texinfo texture; texture.base = m_default_bitmap.raw_pixptr(0); texture.rowpixels = m_default_bitmap.rowpixels(); texture.width = m_default_bitmap.width(); @@ -461,7 +529,7 @@ void d3d_texture_manager::create_resources() texture.old_id = ~0ULL; // now create it - auto tex = std::make_unique<texture_info>(this, &texture, win->prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*this, &texture, m_renderer.window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); m_default_texture = tex.get(); m_texture_list.push_back(std::move(tex)); } @@ -470,7 +538,6 @@ void d3d_texture_manager::create_resources() void d3d_texture_manager::delete_resources() { // is part of m_texlist and will be free'd there - //global_free(m_default_texture); m_default_texture = nullptr; // free all textures @@ -484,16 +551,16 @@ uint32_t d3d_texture_manager::texture_compute_hash(const render_texinfo *texture texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, uint32_t flags) { - uint32_t hash = texture_compute_hash(texinfo, flags); + const uint32_t hash = texture_compute_hash(texinfo, flags); // find a match for (auto it = m_texture_list.begin(); it != m_texture_list.end(); it++) { - uint32_t test_screen = (uint32_t)((*it)->get_texinfo().unique_id >> 57); - uint32_t test_page = (uint32_t)((*it)->get_texinfo().unique_id >> 56) & 1; - uint32_t prim_screen = (uint32_t)(texinfo->unique_id >> 57); - uint32_t prim_page = (uint32_t)(texinfo->unique_id >> 56) & 1; - if (test_screen != prim_screen || test_page != prim_page) + const uint32_t test_screen = uint32_t((*it)->get_texinfo().unique_id >> 57); + const uint32_t test_page = uint32_t((*it)->get_texinfo().unique_id >> 56) & 1; + const uint32_t prim_screen = uint32_t(texinfo->unique_id >> 57); + const uint32_t prim_page = uint32_t(texinfo->unique_id >> 56) & 1; + if ((test_screen != prim_screen) || (test_page != prim_page)) continue; if ((*it)->get_hash() == hash && @@ -509,11 +576,35 @@ texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, u return nullptr; } -renderer_d3d9::renderer_d3d9(std::shared_ptr<osd_window> 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_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_shaders(nullptr), m_texture_manager(nullptr) +renderer_d3d9::renderer_d3d9(osd_window &window, const IDirect3D9Ptr &d3dobj) + : osd_renderer(window) + , m_d3dobj(d3dobj) + , m_adapter(0) + , m_width(0) + , m_height(0) + , m_refresh(0) + , m_create_error_count(0) + , m_post_fx_available(true) + , m_gamma_supported(0) + , m_pixformat() + , 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_shaders(nullptr) + , m_texture_manager() { } @@ -528,8 +619,7 @@ int renderer_d3d9::initialize() } // 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(std::static_pointer_cast<win_window_info>(win->main_window())->platform_window())) + if (window().fullscreen() && device_create(dynamic_cast<win_window_info &>(window()).main_window()->platform_window())) { return false; } @@ -539,10 +629,8 @@ int renderer_d3d9::initialize() int renderer_d3d9::pre_window_draw_check() { - auto win = assert_window(); - // if we're in the middle of resizing, leave things alone - if (win->m_resize_state == RESIZE_STATE_RESIZING) + if (dynamic_cast<win_window_info &>(window()).m_resize_state == win_window_info::RESIZE_STATE_RESIZING) return 0; // check if shaders should be toggled @@ -566,7 +654,7 @@ int renderer_d3d9::pre_window_draw_check() } // if we have a device, check the cooperative level - if (m_device != nullptr) + if (m_device) { if (device_test_cooperative()) { @@ -575,14 +663,14 @@ int renderer_d3d9::pre_window_draw_check() } // in window mode, we need to track the window size - if (!win->fullscreen() || m_device == nullptr) + if (!window().fullscreen() || !m_device) { // if the size changes, skip this update since the render target will be out of date if (update_window_size()) return 0; // if we have no device, after updating the size, return an error so GDI can try - if (m_device == nullptr) + if (!m_device) return 1; } @@ -591,18 +679,16 @@ int renderer_d3d9::pre_window_draw_check() void d3d_texture_manager::update_textures() { - auto win = m_renderer->assert_window(); - - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *m_renderer.window().m_primlist) { if (prim.texture.base != nullptr) { texture_info *texture = find_texinfo(&prim.texture, prim.flags); if (texture == nullptr) { - int prescale = m_renderer->get_shaders()->enabled() ? 1 : win->prescale(); + const int prescale = m_renderer.get_shaders()->enabled() ? 1 : m_renderer.window().prescale(); - auto tex = std::make_unique<texture_info>(this, &prim.texture, prescale, prim.flags); + auto tex = std::make_unique<texture_info>(*this, &prim.texture, prescale, prim.flags); texture = tex.get(); m_texture_list.push_back(std::move(tex)); } @@ -618,21 +704,19 @@ void d3d_texture_manager::update_textures() } } - if (!m_renderer->get_shaders()->enabled()) - { + if (!m_renderer.get_shaders()->enabled()) return; - } int screen_index = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *m_renderer.window().m_primlist) { if (PRIMFLAG_GET_SCREENTEX(prim.flags)) { - if (!m_renderer->get_shaders()->get_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) + if (!m_renderer.get_shaders()->get_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) { - if (!m_renderer->get_shaders()->create_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) + if (!m_renderer.get_shaders()->create_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) { - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); break; } } @@ -640,11 +724,11 @@ void d3d_texture_manager::update_textures() } else if (PRIMFLAG_GET_VECTORBUF(prim.flags)) { - if (!m_renderer->get_shaders()->get_vector_target(&prim, screen_index)) + if (!m_renderer.get_shaders()->get_vector_target(&prim, screen_index)) { - if (!m_renderer->get_shaders()->create_vector_target(&prim, screen_index)) + if (!m_renderer.get_shaders()->create_vector_target(&prim, screen_index)) { - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); break; } } @@ -655,13 +739,11 @@ void d3d_texture_manager::update_textures() void renderer_d3d9::begin_frame() { - auto win = assert_window(); - - HRESULT result = m_device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); + HRESULT result = m_device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0xff,0,0,0), 0, 0); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result); - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // first update any textures m_texture_manager->update_textures(); @@ -672,16 +754,17 @@ void renderer_d3d9::begin_frame() osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result); if (m_shaders->enabled()) - m_shaders->init_fsfx_quad(); + m_shaders->begin_frame(window().m_primlist); + + // set an initial default texture + set_texture(nullptr); } void renderer_d3d9::process_primitives() { - auto win = assert_window(); - // loop over line primitives int vector_count = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { if (prim.type == render_primitive::LINE && PRIMFLAG_GET_VECTOR(prim.flags)) { @@ -690,7 +773,7 @@ void renderer_d3d9::process_primitives() } // Rotating index for vector time offsets - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { switch (prim.type) { @@ -721,13 +804,14 @@ void renderer_d3d9::process_primitives() void renderer_d3d9::end_frame() { - auto win = assert_window(); - - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); // flush any pending polygons primitive_flush_pending(); + if (m_shaders->enabled()) + m_shaders->end_frame(); + // finish the scene HRESULT result = m_device->EndScene(); if (FAILED(result)) @@ -741,8 +825,6 @@ void renderer_d3d9::end_frame() 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; @@ -750,14 +832,14 @@ void renderer_d3d9::update_presentation_parameters() m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1; m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE; m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD; - m_presentation.hDeviceWindow = std::static_pointer_cast<win_window_info>(win)->platform_window(); - m_presentation.Windowed = !win->fullscreen() || win->win_has_menu(); + m_presentation.hDeviceWindow = dynamic_cast<win_window_info &>(window()).platform_window(); + m_presentation.Windowed = !window().fullscreen(); 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.triplebuf && window().fullscreen()) || video_config.waitvsync || video_config.syncrefresh) ? D3DPRESENT_INTERVAL_ONE @@ -772,13 +854,11 @@ void renderer_d3d9::update_gamma_ramp() return; } - auto win = assert_window(); - // set the gamma if we need to - if (win->fullscreen()) + if (window().fullscreen()) { // only set the gamma if it's not 1.0 - windows_options &options = downcast<windows_options &>(win->machine().options()); + auto &options = downcast<windows_options &>(window().machine().options()); float brightness = options.full_screen_brightness(); float contrast = options.full_screen_contrast(); float gamma = options.full_screen_gamma(); @@ -801,44 +881,30 @@ void renderer_d3d9::update_gamma_ramp() // device_create //============================================================ -int renderer_d3d9::device_create(HWND device_hwnd) +int renderer_d3d9::device_create(HWND hwnd) { + // identify the actual window; this is needed so that -attach_window + // can work on a non-root HWND + HWND device_hwnd = GetAncestor(hwnd, GA_ROOT); + // if a device exists, free it - if (m_device != nullptr) - { + if (m_device) device_delete(); - } // verify the caps if (!device_verify_caps()) - { return 1; - } - m_texture_manager = global_alloc(d3d_texture_manager(this)); + m_texture_manager = std::make_unique<d3d_texture_manager>(*this, m_d3dobj.Get()); -try_again: // try for XRGB first m_screen_format = D3DFMT_X8R8G8B8; - 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); + HRESULT result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, 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); - if (FAILED(result) && m_texture_manager->is_dynamic_supported()) - { - m_texture_manager->set_dynamic_supported(false); - goto try_again; - } + result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); if (FAILED(result)) { osd_printf_error("Error: unable to configure a screen texture format\n"); @@ -850,8 +916,13 @@ try_again: 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 = m_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 @@ -884,16 +955,13 @@ 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<shaders>(); - } + if (!m_shaders) + m_shaders = std::make_unique<shaders>(); - if (m_shaders->init(d3dintf, &win->machine(), this)) + if (m_shaders->init(m_d3dobj.Get(), &window().machine(), this)) { + m_post_fx_available = true; m_shaders->init_slider_list(); m_sliders_dirty = true; } @@ -907,12 +975,12 @@ int renderer_d3d9::device_create_resources() // 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()) - ? D3DFVF_XYZW - : D3DFVF_XYZRHW), - D3DPOOL_DEFAULT, &m_vertexbuf, nullptr); + sizeof(vertex) * VERTEX_BUFFER_SIZE, + D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, + VERTEX_BASE_FORMAT | (m_shaders->enabled() ? D3DFVF_XYZW : D3DFVF_XYZRHW), + D3DPOOL_DEFAULT, + &m_vertexbuf, + nullptr); if (FAILED(result)) { osd_printf_error("Error creating vertex buffer (%08X)\n", (uint32_t)result); @@ -921,9 +989,7 @@ int renderer_d3d9::device_create_resources() // set the vertex format result = m_device->SetFVF( - (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled()) - ? D3DFVF_XYZW - : D3DFVF_XYZRHW))); + D3DFORMAT(VERTEX_BASE_FORMAT | (m_shaders->enabled() ? D3DFVF_XYZW : D3DFVF_XYZRHW))); if (FAILED(result)) { osd_printf_error("Error setting vertex format (%08X)\n", (uint32_t)result); @@ -975,23 +1041,6 @@ int renderer_d3d9::device_create_resources() renderer_d3d9::~renderer_d3d9() { device_delete(); - - // 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() -{ - if (d3dintf != nullptr) - { - d3dintf->d3dobj->Release(); - global_free(d3dintf); - } } void renderer_d3d9::device_delete() @@ -1001,18 +1050,10 @@ void renderer_d3d9::device_delete() // we do not delete the HLSL interface here - if (m_texture_manager != nullptr) - { - global_free(m_texture_manager); - m_texture_manager = nullptr; - } + m_texture_manager.reset(); // free the device itself - if (m_device != nullptr) - { - m_device->Release(); - m_device = nullptr; - } + m_device.Reset(); } @@ -1022,22 +1063,14 @@ void renderer_d3d9::device_delete() void renderer_d3d9::device_delete_resources() { - if (m_shaders != nullptr) - { + if (m_shaders) m_shaders->delete_resources(); - } - if (m_texture_manager != nullptr) - { + if (m_texture_manager) m_texture_manager->delete_resources(); - } // free the vertex buffer - if (m_vertexbuf != nullptr) - { - m_vertexbuf->Release(); - m_vertexbuf = nullptr; - } + m_vertexbuf.Reset(); } @@ -1050,7 +1083,7 @@ bool renderer_d3d9::device_verify_caps() bool success = true; D3DCAPS9 caps; - HRESULT result = d3dintf->d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps); + HRESULT result = m_d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps); if (FAILED(result)) { osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result); @@ -1060,7 +1093,7 @@ bool renderer_d3d9::device_verify_caps() if (caps.MaxPixelShader30InstructionSlots < 512) { osd_printf_verbose("Direct3D: Warning - Device does not support Pixel Shader 3.0, falling back to non-PS rendering\n"); - d3dintf->post_fx_available = false; + set_post_fx_unavailable(); } // verify presentation capabilities @@ -1115,7 +1148,7 @@ bool renderer_d3d9::device_verify_caps() } // verify texture formats - result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); + result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); if (FAILED(result)) { osd_printf_error("Direct3D Error: Your graphics card does not support the A8R8G8B8 texture format.\n"); @@ -1191,7 +1224,7 @@ int renderer_d3d9::config_adapter_mode() // get the identifier D3DADAPTER_IDENTIFIER9 id; - HRESULT result = d3dintf->d3dobj->GetAdapterIdentifier(m_adapter, 0, &id); + HRESULT result = m_d3dobj->GetAdapterIdentifier(m_adapter, 0, &id); if (FAILED(result)) { osd_printf_error("Error getting identifier for adapter #%d\n", m_adapter); @@ -1201,22 +1234,20 @@ int renderer_d3d9::config_adapter_mode() osd_printf_verbose("Direct3D: Configuring adapter #%d = %s\n", m_adapter, id.Description); // get the current display mode - result = d3dintf->d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode); + result = m_d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode); if (FAILED(result)) { osd_printf_error("Error getting mode for adapter #%d\n", m_adapter); return 1; } - auto win = assert_window(); - - // choose a resolution: window mode case - if (!win->fullscreen() || !video_config.switchres || win->win_has_menu()) + if (!window().fullscreen() || !video_config.switchres) { - RECT client; + // choose a resolution: window mode case // bounds are from the window client rect - GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen()); + RECT client; + GetClientRectExceptMenu(dynamic_cast<win_window_info &>(window()).platform_window(), &client, window().fullscreen()); m_width = client.right - client.left; m_height = client.bottom - client.top; @@ -1227,14 +1258,14 @@ int renderer_d3d9::config_adapter_mode() // make sure it's a pixel format we can get behind if (m_pixformat != D3DFMT_X1R5G5B5 && m_pixformat != D3DFMT_R5G6B5 && m_pixformat != D3DFMT_X8R8G8B8) { - osd_printf_error("Device %s currently in an unsupported mode\n", win->monitor()->devicename().c_str()); + osd_printf_error("Device %s currently in an unsupported mode\n", window().monitor()->devicename()); return 1; } } - - // choose a resolution: full screen mode case else { + // choose a resolution: full screen mode case + // default to the current mode exactly m_width = m_origmode.Width; m_height = m_origmode.Height; @@ -1247,10 +1278,10 @@ int renderer_d3d9::config_adapter_mode() } // see if we can handle the device type - result = d3dintf->d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !win->fullscreen()); + result = m_d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !window().fullscreen()); if (FAILED(result)) { - osd_printf_error("Proposed video mode not supported on device %s\n", win->monitor()->devicename().c_str()); + osd_printf_error("Proposed video mode not supported on device %s\n", window().monitor()->devicename()); return 1; } @@ -1264,18 +1295,16 @@ int renderer_d3d9::config_adapter_mode() int renderer_d3d9::get_adapter_for_monitor() { - int maxadapter = d3dintf->d3dobj->GetAdapterCount(); - - auto win = assert_window(); + int maxadapter = m_d3dobj->GetAdapterCount(); // iterate over adapters until we error or find a match for (int adapternum = 0; adapternum < maxadapter; adapternum++) { // get the monitor for this adapter - HMONITOR curmonitor = d3dintf->d3dobj->GetAdapterMonitor(adapternum); + HMONITOR curmonitor = m_d3dobj->GetAdapterMonitor(adapternum); // if we match the proposed monitor, this is it - if (curmonitor == reinterpret_cast<HMONITOR>(win->monitor()->oshandle())) + if (curmonitor == reinterpret_cast<HMONITOR>(window().monitor()->oshandle())) { return adapternum; } @@ -1296,10 +1325,8 @@ void renderer_d3d9::pick_best_mode() int32_t minwidth, minheight; float best_score = 0.0f; - auto win = assert_window(); - // determine the refresh rate of the primary screen - const screen_device *primary_screen = screen_device_iterator(win->machine().root_device()).first(); + const screen_device *primary_screen = screen_device_enumerator(window().machine().root_device()).first(); if (primary_screen != nullptr) { target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); @@ -1309,14 +1336,14 @@ void renderer_d3d9::pick_best_mode() // note: technically we should not be calling this from an alternate window // thread; however, it is only done during init time, and the init code on // the main thread is waiting for us to finish, so it is safe to do so here - win->target()->compute_minimum_size(minwidth, minheight); + window().target()->compute_minimum_size(minwidth, minheight); // use those as the target for now int32_t target_width = minwidth; int32_t target_height = minheight; // determine the maximum number of modes - int maxmodes = d3dintf->d3dobj->GetAdapterModeCount(m_adapter, D3DFMT_X8R8G8B8); + int maxmodes = m_d3dobj->GetAdapterModeCount(m_adapter, D3DFMT_X8R8G8B8); // enumerate all the video modes and find the best match osd_printf_verbose("Direct3D: Selecting video mode...\n"); @@ -1324,7 +1351,7 @@ void renderer_d3d9::pick_best_mode() { // check this mode D3DDISPLAYMODE mode; - HRESULT result = d3dintf->d3dobj->EnumAdapterModes(m_adapter, D3DFMT_X8R8G8B8, modenum, &mode); + HRESULT result = m_d3dobj->EnumAdapterModes(m_adapter, D3DFMT_X8R8G8B8, modenum, &mode); if (FAILED(result)) break; @@ -1344,7 +1371,7 @@ void renderer_d3d9::pick_best_mode() size_score *= 0.1f; // if we're looking for a particular mode, that's a winner - if (mode.Width == win->m_win_config.width && mode.Height == win->m_win_config.height) + if (mode.Width == window().m_win_config.width && mode.Height == window().m_win_config.height) size_score = 2.0f; // compute refresh score @@ -1355,7 +1382,7 @@ void renderer_d3d9::pick_best_mode() refresh_score *= 0.1f; // if we're looking for a particular refresh, make sure it matches - if (mode.RefreshRate == win->m_win_config.refresh) + if (mode.RefreshRate == window().m_win_config.refresh) refresh_score = 2.0f; // weight size and refresh equally @@ -1382,33 +1409,32 @@ void renderer_d3d9::pick_best_mode() bool renderer_d3d9::update_window_size() { - auto win = assert_window(); - // get the current window bounds + auto &win = dynamic_cast<win_window_info &>(window()); RECT client; - GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen()); + GetClientRectExceptMenu(win.platform_window(), &client, window().fullscreen()); // if we have a device and matching width/height, nothing to do - if (m_device != nullptr && rect_width(&client) == m_width && rect_height(&client) == m_height) + if (m_device && rect_width(&client) == m_width && rect_height(&client) == m_height) { // clear out any pending resizing if the area didn't change - if (win->m_resize_state == RESIZE_STATE_PENDING) - win->m_resize_state = RESIZE_STATE_NORMAL; + if (win.m_resize_state == win_window_info::RESIZE_STATE_PENDING) + win.m_resize_state = win_window_info::RESIZE_STATE_NORMAL; return false; } // if we're in the middle of resizing, leave it alone as well - if (win->m_resize_state == RESIZE_STATE_RESIZING) + if (win.m_resize_state == win_window_info::RESIZE_STATE_RESIZING) return false; // set the new bounds and create the device again m_width = rect_width(&client); m_height = rect_height(&client); - if (device_create(std::static_pointer_cast<win_window_info>(win->main_window())->platform_window())) + if (device_create(win.main_window()->platform_window())) return false; // reset the resize state to normal, and indicate we made a change - win->m_resize_state = RESIZE_STATE_NORMAL; + win.m_resize_state = win_window_info::RESIZE_STATE_NORMAL; return true; } @@ -1419,8 +1445,6 @@ bool renderer_d3d9::update_window_size() void renderer_d3d9::batch_vectors(int vector_count) { - auto win = assert_window(); - float quad_width = 0.0f; float quad_height = 0.0f; float target_width = 0.0f; @@ -1430,9 +1454,10 @@ void renderer_d3d9::batch_vectors(int vector_count) int triangle_count = vector_count * 2; m_vectorbatch = mesh_alloc(vertex_count); m_batchindex = 0; + uint32_t tint = 0xffffffff; uint32_t cached_flags = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { switch (prim.type) { @@ -1441,6 +1466,12 @@ void renderer_d3d9::batch_vectors(int vector_count) { batch_vector(prim); cached_flags = prim.flags; + + const uint8_t a = (uint8_t)std::round(prim.color.a * 255); + const uint8_t r = (uint8_t)std::round(prim.color.r * 255); + const uint8_t g = (uint8_t)std::round(prim.color.g * 255); + const uint8_t b = (uint8_t)std::round(prim.color.b * 255); + tint = (a << 24) | (b << 16) | (g << 8) | r; } break; @@ -1451,6 +1482,12 @@ void renderer_d3d9::batch_vectors(int vector_count) quad_height = prim.get_quad_height(); target_width = prim.get_full_quad_width(); target_height = prim.get_full_quad_height(); + + const uint8_t a = (uint8_t)std::round(prim.color.a * 255); + const uint8_t r = (uint8_t)std::round(prim.color.r * 255); + const uint8_t g = (uint8_t)std::round(prim.color.g * 255); + const uint8_t b = (uint8_t)std::round(prim.color.b * 255); + tint = (a << 24) | (b << 16) | (g << 8) | r; } break; @@ -1464,15 +1501,15 @@ void renderer_d3d9::batch_vectors(int vector_count) if (m_shaders->enabled()) { bool orientation_swap_xy = - (win->machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; + (window().machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; bool rotation_swap_xy = - (win->target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; + (window().target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; bool swap_xy = orientation_swap_xy ^ rotation_swap_xy; - bool rotation_0 = win->target()->orientation() == ROT0; - bool rotation_90 = win->target()->orientation() == ROT90; - bool rotation_180 = win->target()->orientation() == ROT180; - bool rotation_270 = win->target()->orientation() == ROT270; + bool rotation_0 = window().target()->orientation() == ROT0; + bool rotation_90 = window().target()->orientation() == ROT90; + bool rotation_180 = window().target()->orientation() == ROT180; + bool rotation_270 = window().target()->orientation() == ROT270; bool flip_x = ((rotation_0 || rotation_270) && orientation_swap_xy) || ((rotation_180 || rotation_270) && !orientation_swap_xy); @@ -1480,8 +1517,8 @@ void renderer_d3d9::batch_vectors(int vector_count) ((rotation_0 || rotation_90) && orientation_swap_xy) || ((rotation_180 || rotation_90) && !orientation_swap_xy); - float screen_width = float(this->get_width()); - float screen_height = float(this->get_height()); + auto screen_width = float(this->get_width()); + auto screen_height = float(this->get_height()); float half_screen_width = screen_width * 0.5f; float half_screen_height = screen_height * 0.5f; float screen_swap_x_factor = 1.0f / screen_width * screen_height; @@ -1528,7 +1565,7 @@ void renderer_d3d9::batch_vectors(int vector_count) } // now add a polygon entry - m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, triangle_count, vertex_count, cached_flags, nullptr, D3DTOP_MODULATE, quad_width, quad_height); + m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, triangle_count, vertex_count, cached_flags, nullptr, D3DTOP_MODULATE, quad_width, quad_height, tint); m_numpolys++; } @@ -1541,15 +1578,10 @@ void renderer_d3d9::batch_vector(const render_primitive &prim) } // compute the effective width based on the direction of the line - float effwidth = prim.width; - if (effwidth < 2.0f) - { - effwidth = 2.0f; - } + float effwidth = std::max(prim.width, 2.0f); // determine the bounds of a quad to draw this line - render_bounds b0, b1; - render_line_to_quad(&prim.bounds, effwidth, effwidth, &b0, &b1); + auto [b0, b1] = render_line_to_quad(prim.bounds, effwidth, effwidth); float lx = b1.x1 - b0.x1; float ly = b1.y1 - b0.y1; @@ -1610,10 +1642,10 @@ void renderer_d3d9::batch_vector(const render_primitive &prim) } // determine the color of the line - int32_t r = (int32_t)(prim.color.r * 255.0f); - int32_t g = (int32_t)(prim.color.g * 255.0f); - int32_t b = (int32_t)(prim.color.b * 255.0f); - int32_t a = (int32_t)(prim.color.a * 255.0f); + auto r = (int32_t)(prim.color.r * 255.0f); + auto g = (int32_t)(prim.color.g * 255.0f); + auto b = (int32_t)(prim.color.b * 255.0f); + auto a = (int32_t)(prim.color.a * 255.0f); DWORD color = D3DCOLOR_ARGB(a, r, g, b); // set the color, Z parameters to standard values @@ -1648,15 +1680,10 @@ void renderer_d3d9::draw_line(const render_primitive &prim) } // compute the effective width based on the direction of the line - float effwidth = prim.width; - if (effwidth < 1.0f) - { - effwidth = 1.0f; - } + float effwidth = std::max(prim.width, 1.0f); // determine the bounds of a quad to draw this line - render_bounds b0, b1; - render_line_to_quad(&prim.bounds, effwidth, 0.0f, &b0, &b1); + auto [b0, b1] = render_line_to_quad(prim.bounds, effwidth, 0.0f); vertex[0].x = b0.x0; vertex[0].y = b0.y0; @@ -1680,10 +1707,10 @@ void renderer_d3d9::draw_line(const render_primitive &prim) vertex[3].v0 = stop.c.y; // determine the color of the line - int32_t r = (int32_t)(prim.color.r * 255.0f); - int32_t g = (int32_t)(prim.color.g * 255.0f); - int32_t b = (int32_t)(prim.color.b * 255.0f); - int32_t a = (int32_t)(prim.color.a * 255.0f); + auto r = (int32_t)std::round(prim.color.r * 255.0f); + auto g = (int32_t)std::round(prim.color.g * 255.0f); + auto b = (int32_t)std::round(prim.color.b * 255.0f); + auto a = (int32_t)std::round(prim.color.a * 255.0f); DWORD color = D3DCOLOR_ARGB(a, r, g, b); // set the color, Z parameters to standard values @@ -1695,7 +1722,7 @@ void renderer_d3d9::draw_line(const render_primitive &prim) } // now add a polygon entry - m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, nullptr, D3DTOP_MODULATE, 0.0f, 0.0f); + m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, nullptr, D3DTOP_MODULATE, 0.0f, 0.0f, (uint32_t)color); m_numpolys++; } @@ -1749,10 +1776,10 @@ void renderer_d3d9::draw_quad(const render_primitive &prim) } // determine the color, allowing for over modulation - int32_t r = (int32_t)(prim.color.r * 255.0f); - int32_t g = (int32_t)(prim.color.g * 255.0f); - int32_t b = (int32_t)(prim.color.b * 255.0f); - int32_t a = (int32_t)(prim.color.a * 255.0f); + auto r = (int32_t)std::round(prim.color.r * 255.0f); + auto g = (int32_t)std::round(prim.color.g * 255.0f); + auto b = (int32_t)std::round(prim.color.b * 255.0f); + auto a = (int32_t)std::round(prim.color.a * 255.0f); DWORD color = D3DCOLOR_ARGB(a, r, g, b); // adjust half pixel X/Y offset, set the color, Z parameters to standard values @@ -1766,7 +1793,7 @@ void renderer_d3d9::draw_quad(const render_primitive &prim) } // now add a polygon entry - m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, texture, D3DTOP_MODULATE, quad_width, quad_height); + m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, texture, D3DTOP_MODULATE, quad_width, quad_height, (uint32_t)color); m_numpolys++; } @@ -1826,7 +1853,7 @@ void renderer_d3d9::primitive_flush_pending() m_lockedbuf = nullptr; // set the stream - result = m_device->SetStreamSource(0, m_vertexbuf, 0, sizeof(vertex)); + result = m_device->SetStreamSource(0, m_vertexbuf.Get(), 0, sizeof(vertex)); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result); @@ -1854,9 +1881,17 @@ void renderer_d3d9::primitive_flush_pending() newfilter = FALSE; if (PRIMFLAG_GET_SCREENTEX(flags)) newfilter = video_config.filter; - set_filter(newfilter); - set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); - set_modmode(m_poly[polynum].modmode()); + + if (m_shaders->enabled()) + { + m_shaders->set_filter(newfilter); + } + else + { + set_filter(newfilter); + set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); + set_modmode(m_poly[polynum].modmode()); + } } if (vertnum + m_poly[polynum].numverts() > m_numverts) @@ -1869,9 +1904,6 @@ void renderer_d3d9::primitive_flush_pending() if(m_shaders->enabled()) { - // reset blend mode (handled by shader passes) - set_blendmode(BLENDMODE_NONE); - m_shaders->render_quad(&m_poly[polynum], vertnum); } else @@ -1924,19 +1956,6 @@ void renderer_d3d9::set_sliders_dirty() texture_info::~texture_info() { - if (m_d3dfinaltex != nullptr) - { - if (m_d3dtex == m_d3dfinaltex) - m_d3dtex = nullptr; - - m_d3dfinaltex->Release(); - } - - if (m_d3dtex != nullptr) - m_d3dtex->Release(); - - if (m_d3dsurface != nullptr) - m_d3dsurface->Release(); } @@ -1944,181 +1963,117 @@ texture_info::~texture_info() // texture_info constructor //============================================================ -texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* texsource, int prescale, uint32_t flags) +texture_info::texture_info(d3d_texture_manager &manager, const render_texinfo* texsource, int prescale, uint32_t flags) + : m_texture_manager(manager) + , m_renderer(manager.get_d3d()) + , m_hash(manager.texture_compute_hash(texsource, flags)) + , m_flags(flags) + , m_texinfo(*texsource) + , m_type(!PRIMFLAG_GET_SCREENTEX(flags) ? TEXTURE_TYPE_PLAIN : TEXTURE_TYPE_DYNAMIC) // required to compute texture size + , m_xprescale(PRIMFLAG_GET_SCREENTEX(flags) ? prescale : 1) + , m_yprescale(PRIMFLAG_GET_SCREENTEX(flags) ? prescale : 1) { - HRESULT result; - - // fill in the core data - m_texture_manager = manager; - m_renderer = m_texture_manager->get_d3d(); - m_hash = m_texture_manager->texture_compute_hash(texsource, flags); - m_flags = flags; - m_texinfo = *texsource; - m_xprescale = prescale; - m_yprescale = prescale; - - m_d3dtex = nullptr; - m_d3dsurface = nullptr; - m_d3dfinaltex = nullptr; - - // determine texture type, required to compute texture size - if (!PRIMFLAG_GET_SCREENTEX(flags)) - { - m_type = TEXTURE_TYPE_PLAIN; - } - else - { - if ((m_xprescale == 1 && m_yprescale == 1) || m_renderer->get_shaders()->enabled()) - { - m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; - } - else - { - if (m_texture_manager->is_stretch_supported() && PRIMFLAG_GET_TEXFORMAT(flags) != TEXFORMAT_YUY16) - { - m_type = TEXTURE_TYPE_SURFACE; - } - else - { - m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; - } - } - } - // compute the size compute_size(texsource->width, texsource->height); - // non-screen textures are easy if (!PRIMFLAG_GET_SCREENTEX(flags)) { + // non-screen textures are easy assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16); - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex, nullptr); + const HRESULT result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex, nullptr); if (FAILED(result)) goto error; + m_d3dfinaltex = m_d3dtex; } - - // screen textures are allocated differently else { - D3DFORMAT format; - DWORD usage = m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0; - D3DPOOL pool = m_texture_manager->is_dynamic_supported() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; - int maxdim = std::max(m_renderer->get_presentation()->BackBufferWidth, m_renderer->get_presentation()->BackBufferHeight); + // screen textures are allocated differently // pick the format + const DWORD usage = D3DUSAGE_DYNAMIC; + const D3DPOOL pool = D3DPOOL_DEFAULT; + D3DFORMAT format; if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_YUY16) - { - format = m_texture_manager->get_yuv_format(); - } + format = m_texture_manager.get_yuv_format(); else if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_ARGB32) - { format = D3DFMT_A8R8G8B8; - } else - { - format = m_renderer->get_screen_format(); - } + format = m_renderer.get_screen_format(); // don't prescale above screen size - while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale >= 2 * maxdim) - { + const int maxdim = std::max( + m_renderer.get_presentation()->BackBufferWidth, + m_renderer.get_presentation()->BackBufferHeight); + + while ((m_xprescale > 1) && ((m_rawdims.c.x * m_xprescale) >= (2 * maxdim))) m_xprescale--; - } - while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale > manager->get_max_texture_width()) - { + while ((m_xprescale > 1) && ((m_rawdims.c.x * m_xprescale) > manager.get_max_texture_width())) m_xprescale--; - } - while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale >= 2 * maxdim) - { + + while ((m_yprescale > 1) && ((m_rawdims.c.y * m_yprescale) >= (2 * maxdim))) m_yprescale--; - } - while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale > manager->get_max_texture_height()) - { + while ((m_yprescale > 1) && ((m_rawdims.c.y * m_yprescale) > manager.get_max_texture_height())) m_yprescale--; - } - - auto win = m_renderer->assert_window(); - int prescale = win->prescale(); - if (m_xprescale != prescale || m_yprescale != prescale) - { + const int prescale = m_renderer.window().prescale(); + if ((m_xprescale != prescale) || (m_yprescale != prescale)) osd_printf_verbose("Direct3D: adjusting prescale from %dx%d to %dx%d\n", prescale, prescale, m_xprescale, m_yprescale); - } // loop until we allocate something or error + HRESULT result; for (int attempt = 0; attempt < 2; attempt++) { - // second attempt is always 1:1 - if (attempt == 1) + if ((m_xprescale == 1) && (m_yprescale == 1)) { - m_xprescale = m_yprescale = 1; - } - - // screen textures with no prescaling are pretty easy - if (m_xprescale == 1 && m_yprescale == 1) - { - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); + // screen textures with no prescaling are pretty easy + result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); if (result == D3D_OK) { m_d3dfinaltex = m_d3dtex; break; } } - // screen textures with prescaling require two allocations else { - // use an offscreen plain surface for stretching if supported - // (won't work for YUY textures) - if (m_texture_manager->is_stretch_supported() && PRIMFLAG_GET_TEXFORMAT(flags) != TEXFORMAT_YUY16) - { - result = m_renderer->get_device()->CreateOffscreenPlainSurface(m_rawdims.c.x, m_rawdims.c.y, format, D3DPOOL_DEFAULT, &m_d3dsurface, nullptr); - if (FAILED(result)) - { - continue; - } - } - // otherwise, we allocate a dynamic texture for the source - else + // screen textures with prescaling require two allocations + result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); + if (result == D3D_OK) { - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); - if (FAILED(result)) - { - continue; - } - } + // for the target surface, we allocate a render target texture + const int scwidth = m_rawdims.c.x * m_xprescale; + const int scheight = m_rawdims.c.y * m_yprescale; - // for the target surface, we allocate a render target texture - int scwidth = m_rawdims.c.x * m_xprescale; - int scheight = m_rawdims.c.y * m_yprescale; + // target surfaces typically cannot be YCbCr, so we always pick RGB in that case + const D3DFORMAT finalfmt = (format != m_texture_manager.get_yuv_format()) ? format : D3DFMT_A8R8G8B8; - // target surfaces typically cannot be YCbCr, so we always pick RGB in that case - D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8; + result = m_renderer.get_device()->CreateTexture(scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex, nullptr); + if (result == D3D_OK) + break; - result = m_renderer->get_device()->CreateTexture(scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex, nullptr); - if (result == D3D_OK) - { - break; + m_d3dtex.Reset(); } - - m_d3dtex->Release(); - m_d3dtex = nullptr; } + + // second attempt is always 1:1 + m_xprescale = m_yprescale = 1; } + if (FAILED(result)) + goto error; } // copy the data to the texture + assert(m_d3dtex); + assert(m_d3dfinaltex); set_data(texsource, flags); return; error: - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); osd_printf_error("Direct3D: Critical warning: A texture failed to allocate. Expect things to get bad quickly.\n"); - if (m_d3dsurface != nullptr) - m_d3dsurface->Release(); - if (m_d3dtex != nullptr) - m_d3dtex->Release(); + m_d3dsurface.Reset(); + m_d3dtex.Reset(); } @@ -2132,11 +2087,11 @@ void texture_info::compute_size_subroutine(int texwidth, int texheight, int* p_w int finalwidth = texwidth; // adjust the aspect ratio if we need to - while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect()) + while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager.get_max_texture_aspect()) { finalwidth *= 2; } - while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect()) + while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager.get_max_texture_aspect()) { finalheight *= 2; } @@ -2158,7 +2113,7 @@ void texture_info::compute_size(int texwidth, int texheight) m_xborderpix = 0; m_yborderpix = 0; - bool shaders_enabled = m_renderer->get_shaders()->enabled(); + bool shaders_enabled = m_renderer.get_shaders()->enabled(); bool wrap_texture = (m_flags & PRIMFLAG_TEXWRAP_MASK) == PRIMFLAG_TEXWRAP_MASK; // skip border when shaders are enabled @@ -2168,8 +2123,8 @@ void texture_info::compute_size(int texwidth, int texheight) if (!wrap_texture) { // note we need 2 pixels in X for YUY textures - m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1; - m_yborderpix = 1; + //m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1; + //m_yborderpix = 1; } } @@ -2182,7 +2137,7 @@ void texture_info::compute_size(int texwidth, int texheight) compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight); // if we added pixels for the border, and that just barely pushed us over, take it back - if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) + if (finalwidth > m_texture_manager.get_max_texture_width() || finalheight > m_texture_manager.get_max_texture_height()) { finalheight = texheight; finalwidth = texwidth; @@ -2195,10 +2150,18 @@ void texture_info::compute_size(int texwidth, int texheight) } // if we're above the max width/height, do what? - if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) + if (finalwidth > m_texture_manager.get_max_texture_width() || finalheight > m_texture_manager.get_max_texture_height()) { static bool printed = false; - if (!printed) osd_printf_warning("Texture too big! (wanted: %dx%d, max is %dx%d)\n", finalwidth, finalheight, (int)m_texture_manager->get_max_texture_width(), (int)m_texture_manager->get_max_texture_height()); + if (!printed) + { + osd_printf_warning( + "Texture too big! (wanted: %dx%d, max is %dx%d)\n", + finalwidth, + finalheight, + m_texture_manager.get_max_texture_width(), + m_texture_manager.get_max_texture_height()); + } printed = true; } @@ -2451,9 +2414,9 @@ void texture_info::set_data(const render_texinfo *texsource, uint32_t flags) break; case TEXFORMAT_YUY16: - if (m_texture_manager->get_yuv_format() == D3DFMT_YUY2) + if (m_texture_manager.get_yuv_format() == D3DFMT_YUY2) copyline_yuy16_to_yuy2((uint16_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); - else if (m_texture_manager->get_yuv_format() == D3DFMT_UYVY) + else if (m_texture_manager.get_yuv_format() == D3DFMT_UYVY) copyline_yuy16_to_uyvy((uint16_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); else copyline_yuy16_to_argb((uint32_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); @@ -2488,132 +2451,109 @@ void texture_info::set_data(const render_texinfo *texsource, uint32_t flags) void texture_info::prescale() { - IDirect3DSurface9 *scale_surface; - HRESULT result; - int i; - // if we don't need to, just skip it - if (m_d3dtex == m_d3dfinaltex) + if (m_d3dtex.Get() == m_d3dfinaltex.Get()) + { + assert(m_xprescale == 1); + assert(m_yprescale == 1); return; + } + + assert(m_d3dtex); + assert((m_xprescale > 1) || (m_yprescale > 1)); + HRESULT result; // for all cases, we need to get the surface of the render target + Microsoft::WRL::ComPtr<IDirect3DSurface9> scale_surface; result = m_d3dfinaltex->GetSurfaceLevel(0, &scale_surface); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during texture GetSurfaceLevel call\n", result); // if we have an offscreen plain surface, we can just StretchRect to it - if (m_type == TEXTURE_TYPE_SURFACE) - { - assert(m_d3dsurface != nullptr); - // set the source bounds - RECT source; - source.left = source.top = 0; - source.right = m_texinfo.width + 2 * m_xborderpix; - source.bottom = m_texinfo.height + 2 * m_yborderpix; + // first remember the original render target and set the new one + Microsoft::WRL::ComPtr<IDirect3DSurface9> backbuffer; + result = m_renderer.get_device()->GetRenderTarget(0, &backbuffer); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during device GetRenderTarget call\n", result); + result = m_renderer.get_device()->SetRenderTarget(0, scale_surface.Get()); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 1\n", result); + m_renderer.reset_render_states(); - // set the target bounds - RECT dest; - dest = source; - dest.right *= m_xprescale; - dest.bottom *= m_yprescale; + // start the scene + result = m_renderer.get_device()->BeginScene(); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result); - // do the stretchrect - result = m_renderer->get_device()->StretchRect(m_d3dsurface, &source, scale_surface, &dest, D3DTEXF_POINT); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device stretct_rect call\n", result); - } + // configure the rendering pipeline + m_renderer.set_filter(FALSE); + m_renderer.set_blendmode(BLENDMODE_NONE); + result = m_renderer.get_device()->SetTexture(0, m_d3dtex.Get()); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during device SetTexture call\n", result); - // if we are using a texture render target, we need to do more preparations - else + // lock the vertex buffer + vertex *lockedbuf; + result = m_renderer.get_vertex_buffer()->Lock(0, 0, (VOID **)&lockedbuf, D3DLOCK_DISCARD); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during vertex buffer lock call\n", result); + + // configure the X/Y coordinates on the target surface + lockedbuf[0].x = -0.5f; + lockedbuf[0].y = -0.5f; + lockedbuf[1].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f; + lockedbuf[1].y = -0.5f; + lockedbuf[2].x = -0.5f; + lockedbuf[2].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f; + lockedbuf[3].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f; + lockedbuf[3].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f; + + // configure the U/V coordintes on the source texture + lockedbuf[0].u0 = 0.0f; + lockedbuf[0].v0 = 0.0f; + lockedbuf[1].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x; + lockedbuf[1].v0 = 0.0f; + lockedbuf[2].u0 = 0.0f; + lockedbuf[2].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; + lockedbuf[3].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x; + lockedbuf[3].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; + + // reset the remaining vertex parameters + for (int i = 0; i < 4; i++) { - IDirect3DSurface9 *backbuffer; - - assert(m_d3dtex != nullptr); - - // first remember the original render target and set the new one - result = m_renderer->get_device()->GetRenderTarget(0, &backbuffer); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device GetRenderTarget call\n", result); - result = m_renderer->get_device()->SetRenderTarget(0, scale_surface); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 1\n", result); - m_renderer->reset_render_states(); - - // start the scene - result = m_renderer->get_device()->BeginScene(); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result); - - // configure the rendering pipeline - m_renderer->set_filter(FALSE); - m_renderer->set_blendmode(BLENDMODE_NONE); - result = m_renderer->get_device()->SetTexture(0, m_d3dtex); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device SetTexture call\n", result); - - // lock the vertex buffer - vertex *lockedbuf; - result = m_renderer->get_vertex_buffer()->Lock(0, 0, (VOID **)&lockedbuf, D3DLOCK_DISCARD); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during vertex buffer lock call\n", result); - - // configure the X/Y coordinates on the target surface - lockedbuf[0].x = -0.5f; - lockedbuf[0].y = -0.5f; - lockedbuf[1].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f; - lockedbuf[1].y = -0.5f; - lockedbuf[2].x = -0.5f; - lockedbuf[2].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f; - lockedbuf[3].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f; - lockedbuf[3].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f; - - // configure the U/V coordintes on the source texture - lockedbuf[0].u0 = 0.0f; - lockedbuf[0].v0 = 0.0f; - lockedbuf[1].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x; - lockedbuf[1].v0 = 0.0f; - lockedbuf[2].u0 = 0.0f; - lockedbuf[2].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; - lockedbuf[3].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x; - lockedbuf[3].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; - - // reset the remaining vertex parameters - for (i = 0; i < 4; i++) - { - lockedbuf[i].z = 0.0f; - lockedbuf[i].rhw = 1.0f; - lockedbuf[i].color = D3DCOLOR_ARGB(0xff,0xff,0xff,0xff); - } + lockedbuf[i].z = 0.0f; + lockedbuf[i].rhw = 1.0f; + lockedbuf[i].color = D3DCOLOR_ARGB(0xff,0xff,0xff,0xff); + } - // unlock the vertex buffer - result = m_renderer->get_vertex_buffer()->Unlock(); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during vertex buffer unlock call\n", result); + // unlock the vertex buffer + result = m_renderer.get_vertex_buffer()->Unlock(); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during vertex buffer unlock call\n", result); - // set the stream and draw the triangle strip - result = m_renderer->get_device()->SetStreamSource(0, m_renderer->get_vertex_buffer(), 0, sizeof(vertex)); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result); - result = m_renderer->get_device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result); + // set the stream and draw the triangle strip + result = m_renderer.get_device()->SetStreamSource(0, m_renderer.get_vertex_buffer(), 0, sizeof(vertex)); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result); + result = m_renderer.get_device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result); - // end the scene - result = m_renderer->get_device()->EndScene(); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device end_scene call\n", result); + // end the scene + result = m_renderer.get_device()->EndScene(); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during device end_scene call\n", result); - // reset the render target and release our reference to the backbuffer - result = m_renderer->get_device()->SetRenderTarget(0, backbuffer); - if (FAILED(result)) - osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 2\n", result); - backbuffer->Release(); - m_renderer->reset_render_states(); - } + // reset the render target and release our reference to the backbuffer + result = m_renderer.get_device()->SetRenderTarget(0, backbuffer.Get()); + if (FAILED(result)) + osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 2\n", result); + backbuffer.Reset(); + m_renderer.reset_render_states(); // release our reference to the target surface - scale_surface->Release(); + scale_surface.Reset(); } @@ -2623,35 +2563,6 @@ void texture_info::prescale() d3d_render_target::~d3d_render_target() { - for (int index = 0; index < MAX_BLOOM_COUNT; index++) - { - if (bloom_texture[index] != nullptr) - bloom_texture[index]->Release(); - - if (bloom_surface[index] != nullptr) - bloom_surface[index]->Release(); - } - - for (int index = 0; index < 2; index++) - { - if (source_texture[index] != nullptr) - source_texture[index]->Release(); - - if (source_surface[index] != nullptr) - source_surface[index]->Release(); - - if (target_texture[index] != nullptr) - target_texture[index]->Release(); - - if (target_surface[index] != nullptr) - target_surface[index]->Release(); - } - - if (cache_texture != nullptr) - cache_texture->Release(); - - if (cache_surface != nullptr) - cache_surface->Release(); } @@ -2692,9 +2603,7 @@ bool d3d_render_target::init(renderer_d3d9 *d3d, int source_width, int source_he cache_texture->GetSurfaceLevel(0, &cache_surface); - auto win = d3d->assert_window(); - - const screen_device *first_screen = screen_device_iterator(win->machine().root_device()).first(); + const screen_device *first_screen = screen_device_enumerator(d3d->window().machine().root_device()).first(); bool vector_screen = first_screen != nullptr && first_screen->screen_type() == SCREEN_TYPE_VECTOR; @@ -2702,8 +2611,8 @@ bool d3d_render_target::init(renderer_d3d9 *d3d, int source_width, int source_he float scale_factor = 0.75f; int scale_count = vector_screen ? MAX_BLOOM_COUNT : HALF_BLOOM_COUNT; - float bloom_width = (float)source_width; - float bloom_height = (float)source_height; + auto bloom_width = (float)source_width; + auto bloom_height = (float)source_height; float bloom_size = bloom_width < bloom_height ? bloom_width : bloom_height; for (int bloom_index = 0; bloom_index < scale_count && bloom_size >= 2.0f; bloom_size *= scale_factor) { |