diff --git a/Makefile.common b/Makefile.common index 527f728b50..bcd6522d5d 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1743,7 +1743,9 @@ ifeq ($(HAVE_D3D9), 1) OBJ += gfx/drivers_font/d3d_w32_font.o ifeq ($(HAVE_CG), 1) LIBS += -lcgD3D9 + OBJ += gfx/drivers/d3d9cg.o OBJ += gfx/drivers_renderchain/d3d9_cg_renderchain.o + OBJ += gfx/drivers_display/gfx_display_d3d9cg.o endif endif @@ -1813,9 +1815,7 @@ endif ifeq ($(HAVE_D3D9), 1) DEFINES += -DHAVE_D3D9 - OBJ += gfx/drivers/d3d9.o OBJ += gfx/common/d3d9_common.o - OBJ += gfx/drivers_display/gfx_display_d3d9.o endif ifeq ($(HAVE_D3D_COMMON), 1) @@ -1836,7 +1836,9 @@ endif ifeq ($(HAVE_HLSL),1) DEFINES += -DHAVE_HLSL + OBJ += gfx/drivers/d3d9hlsl.o OBJ += gfx/drivers_renderchain/d3d9_hlsl_renderchain.o + OBJ += gfx/drivers_display/gfx_display_d3d9hlsl.o endif ifeq ($(HAVE_SLANG),1) diff --git a/configuration.c b/configuration.c index 8720d33ccb..f60909093a 100644 --- a/configuration.c +++ b/configuration.c @@ -88,7 +88,8 @@ enum video_driver_enum VIDEO_CTR, VIDEO_SWITCH, VIDEO_D3D8, - VIDEO_D3D9, + VIDEO_D3D9_CG, + VIDEO_D3D9_HLSL, VIDEO_D3D10, VIDEO_D3D11, VIDEO_D3D12, @@ -960,8 +961,10 @@ const char *config_get_default_video(void) return "xenon360"; case VIDEO_D3D8: return "d3d8"; - case VIDEO_D3D9: - return "d3d9"; + case VIDEO_D3D9_CG: + return "d3d9_cg"; + case VIDEO_D3D9_HLSL: + return "d3d9_hlsl"; case VIDEO_D3D10: return "d3d10"; case VIDEO_D3D11: @@ -2991,9 +2994,9 @@ static bool check_menu_driver_compatibility(settings_t *settings) /* TODO/FIXME - maintenance hazard */ if (string_starts_with_size(video_driver, "d3d", STRLEN_CONST("d3d"))) if ( - string_is_equal(video_driver, "d3d9") || - string_is_equal(video_driver, "d3d10") || - string_is_equal(video_driver, "d3d11") || + string_is_equal(video_driver, "d3d9_hlsl") || + string_is_equal(video_driver, "d3d10") || + string_is_equal(video_driver, "d3d11") || string_is_equal(video_driver, "d3d12") ) return true; diff --git a/gfx/drivers/d3d9cg.c b/gfx/drivers/d3d9cg.c new file mode 100644 index 0000000000..dd93888f5c --- /dev/null +++ b/gfx/drivers/d3d9cg.c @@ -0,0 +1,898 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * Copyright (C) 2012-2014 - OV2 + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +/* Direct3D 9 driver with Cg runtime backend. + * + * Minimum version : Direct3D 9.0 (2002) + * Minimum OS : Windows 98, Windows 2000, Windows ME + * Recommended OS : Windows XP + * Requirements : Cg runtime + */ + +#define CINTERFACE + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + +#include +#include "../common/d3d_common.h" +#include "../common/d3d9_common.h" +#include "../video_coord_array.h" +#include "../../configuration.h" +#include "../../dynamic.h" +#include "../../frontend/frontend_driver.h" + +#include "../common/win32_common.h" + +#ifdef HAVE_MENU +#include "../../menu/menu_driver.h" +#endif +#ifdef HAVE_GFX_WIDGETS +#include "../gfx_widgets.h" +#endif + +#include "../font_driver.h" + +#include "../../core.h" +#include "../../verbosity.h" +#include "../../retroarch.h" + +#ifdef __WINRT__ +#error "UWP does not support D3D9" +#endif + +/* TODO/FIXME - Temporary workaround for D3D9 not being able to poll flags during init */ +static gfx_ctx_driver_t d3d9_cg_fake_context; + +extern d3d9_renderchain_driver_t cg_d3d9_renderchain; + +static uint32_t d3d9_cg_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION); + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); + BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_CG); + + return flags; +} + +static void d3d9_cg_deinit_chain(d3d9_video_t *d3d) +{ + if (!d3d || !d3d->renderchain_driver) + return; + + if (d3d->renderchain_driver->chain_free) + d3d->renderchain_driver->chain_free(d3d->renderchain_data); + + d3d->renderchain_driver = NULL; + d3d->renderchain_data = NULL; +} + +static void d3d9_cg_deinitialize(d3d9_video_t *d3d) +{ + if (!d3d) + return; + + font_driver_free_osd(); + + d3d9_cg_deinit_chain(d3d); + d3d9_vertex_buffer_free(d3d->menu_display.buffer, + d3d->menu_display.decl); + + d3d->menu_display.buffer = NULL; + d3d->menu_display.decl = NULL; +} + +static bool d3d9_cg_init_base(d3d9_video_t *d3d, const video_info_t *info) +{ + D3DPRESENT_PARAMETERS d3dpp; + HWND focus_window = win32_get_window(); + + memset(&d3dpp, 0, sizeof(d3dpp)); + + g_pD3D9 = (LPDIRECT3D9)d3d9_create(); + + /* this needs g_pD3D9 created first */ + d3d9_make_d3dpp(d3d, info, &d3dpp); + + if (!g_pD3D9) + return false; + if (!d3d9_create_device(&d3d->dev, &d3dpp, + g_pD3D9, + focus_window, + d3d->cur_mon_id) + ) + return false; + return true; +} + +static bool renderchain_d3d_cg_init_first( + enum gfx_ctx_api api, + const d3d9_renderchain_driver_t **renderchain_driver, + void **renderchain_handle) +{ + switch (api) + { + case GFX_CTX_DIRECT3D9_API: + { + static const d3d9_renderchain_driver_t *renderchain_d3d_drivers[] = + { + &cg_d3d9_renderchain, + NULL + }; + unsigned i; + + for (i = 0; renderchain_d3d_drivers[i]; i++) + { + void *data = renderchain_d3d_drivers[i]->chain_new(); + + if (!data) + continue; + + *renderchain_driver = renderchain_d3d_drivers[i]; + *renderchain_handle = data; + + return true; + } + } + break; + case GFX_CTX_NONE: + default: + break; + } + + return false; +} + +static bool d3d9_cg_init_chain(d3d9_video_t *d3d, + unsigned input_scale, + bool rgb32) +{ + unsigned i = 0; + struct LinkInfo link_info; + unsigned current_width, current_height, out_width, out_height; + + /* Setup information for first pass. */ + link_info.pass = NULL; + link_info.tex_w = input_scale * RARCH_SCALE_BASE; + link_info.tex_h = input_scale * RARCH_SCALE_BASE; + link_info.pass = &d3d->shader.pass[0]; + + if (!renderchain_d3d_cg_init_first(GFX_CTX_DIRECT3D9_API, + &d3d->renderchain_driver, + &d3d->renderchain_data)) + { + RARCH_ERR("[D3D9]: Renderchain could not be initialized.\n"); + return false; + } + + if (!d3d->renderchain_driver || !d3d->renderchain_data) + return false; + + if ( + !d3d->renderchain_driver->init( + d3d, + d3d->dev, &d3d->final_viewport, &link_info, + rgb32) + ) + { + RARCH_ERR("[D3D9]: Failed to init render chain.\n"); + return false; + } + + RARCH_LOG("[D3D9]: Renderchain driver: \"%s\".\n", d3d->renderchain_driver->ident); + d3d9_log_info(&link_info); + + current_width = link_info.tex_w; + current_height = link_info.tex_h; + out_width = 0; + out_height = 0; + + for (i = 1; i < d3d->shader.passes; i++) + { + d3d9_convert_geometry( + &link_info, + &out_width, &out_height, + current_width, current_height, &d3d->final_viewport); + + link_info.pass = &d3d->shader.pass[i]; + link_info.tex_w = next_pow2(out_width); + link_info.tex_h = next_pow2(out_height); + + current_width = out_width; + current_height = out_height; + + if (!d3d->renderchain_driver->add_pass( + d3d->renderchain_data, &link_info)) + { + RARCH_ERR("[D3D9]: Failed to add pass.\n"); + return false; + } + d3d9_log_info(&link_info); + } + + if (d3d->renderchain_driver) + { + if (d3d->renderchain_driver->add_lut) + { + unsigned i; + settings_t *settings = config_get_ptr(); + bool video_smooth = settings->bools.video_smooth; + + for (i = 0; i < d3d->shader.luts; i++) + { + if (!d3d->renderchain_driver->add_lut( + d3d->renderchain_data, + d3d->shader.lut[i].id, d3d->shader.lut[i].path, + d3d->shader.lut[i].filter == RARCH_FILTER_UNSPEC + ? video_smooth + : (d3d->shader.lut[i].filter == RARCH_FILTER_LINEAR))) + { + RARCH_ERR("[D3D9]: Failed to init LUTs.\n"); + return false; + } + } + } + } + + return true; +} + +static bool d3d9_cg_initialize(d3d9_video_t *d3d, const video_info_t *info) +{ + unsigned width, height; + bool ret = true; + settings_t *settings = config_get_ptr(); + + if (!g_pD3D9) + ret = d3d9_cg_init_base(d3d, info); + else if (d3d->needs_restore) + { + D3DPRESENT_PARAMETERS d3dpp; + + d3d9_make_d3dpp(d3d, info, &d3dpp); + + /* the D3DX font driver uses POOL_DEFAULT resources + * and will prevent a clean reset here + * another approach would be to keep track of all created D3D + * font objects and free/realloc them around the d3d_reset call */ +#ifdef HAVE_MENU + menu_driver_ctl(RARCH_MENU_CTL_DEINIT, NULL); +#endif + + if (!d3d9_reset(d3d->dev, &d3dpp)) + { + d3d9_cg_deinitialize(d3d); + d3d9_device_free(NULL, g_pD3D9); + g_pD3D9 = NULL; + + ret = d3d9_cg_init_base(d3d, info); + if (ret) + RARCH_LOG("[D3D9]: Recovered from dead state.\n"); + } + +#ifdef HAVE_MENU + menu_driver_init(info->is_threaded); +#endif + } + + if (!ret) + return ret; + + if (!d3d9_cg_init_chain(d3d, info->input_scale, info->rgb32)) + { + RARCH_ERR("[D3D9]: Failed to initialize render chain.\n"); + return false; + } + + video_driver_get_size(&width, &height); + d3d9_set_viewport(d3d, + width, height, false, true); + + font_driver_init_osd(d3d, info, + false, + info->is_threaded, + FONT_DRIVER_RENDER_D3D9_API); + + { + static const D3DVERTEXELEMENT9 VertexElements[4] = { + {0, offsetof(Vertex, x), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, + D3DDECLUSAGE_POSITION, 0}, + {0, offsetof(Vertex, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, + D3DDECLUSAGE_TEXCOORD, 0}, + {0, offsetof(Vertex, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, + D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + if (!d3d9_vertex_declaration_new(d3d->dev, + (void*)VertexElements, (void**)&d3d->menu_display.decl)) + return false; + } + + d3d->menu_display.offset = 0; + d3d->menu_display.size = 1024; + d3d->menu_display.buffer = d3d9_vertex_buffer_new( + d3d->dev, d3d->menu_display.size * sizeof(Vertex), + D3DUSAGE_WRITEONLY, + D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, + D3DPOOL_DEFAULT, + NULL); + + if (!d3d->menu_display.buffer) + return false; + + d3d_matrix_ortho_off_center_lh(&d3d->mvp_transposed, 0, 1, 0, 1, 0, 1); + d3d_matrix_transpose(&d3d->mvp, &d3d->mvp_transposed); + + d3d9_set_render_state(d3d->dev, D3DRS_CULLMODE, D3DCULL_NONE); + d3d9_set_render_state(d3d->dev, D3DRS_SCISSORTESTENABLE, TRUE); + + return true; +} + +static bool d3d9_cg_restore(d3d9_video_t *d3d) +{ + d3d9_cg_deinitialize(d3d); + + if (!d3d9_cg_initialize(d3d, &d3d->video_info)) + { + RARCH_ERR("[D3D9]: Restore error.\n"); + return false; + } + + d3d->needs_restore = false; + + return true; +} + +static bool d3d9_cg_set_shader(void *data, + enum rarch_shader_type type, const char *path) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return false; + + if (!string_is_empty(d3d->shader_path)) + free(d3d->shader_path); + d3d->shader_path = NULL; + + switch (type) + { + case RARCH_SHADER_CG: + case RARCH_SHADER_HLSL: + if (!string_is_empty(path)) + d3d->shader_path = strdup(path); + break; + case RARCH_SHADER_NONE: + break; + default: + RARCH_WARN("[D3D9]: Only Cg shaders are supported. Falling back to stock.\n"); + } + + if (!d3d9_process_shader(d3d) || !d3d9_cg_restore(d3d)) + { + RARCH_ERR("[D3D9]: Failed to set shader.\n"); + return false; + } + + return true; +} + +static bool d3d9_cg_init_internal(d3d9_video_t *d3d, + const video_info_t *info, input_driver_t **input, + void **input_data) +{ +#ifdef HAVE_MONITOR + bool windowed_full; + RECT mon_rect; + MONITORINFOEX current_mon; + HMONITOR hm_to_use; +#endif +#ifdef HAVE_WINDOW + DWORD style; + unsigned win_width = 0; + unsigned win_height = 0; + RECT rect = {0}; +#endif + unsigned full_x = 0; + unsigned full_y = 0; + settings_t *settings = config_get_ptr(); + overlay_t *menu = (overlay_t*)calloc(1, sizeof(*menu)); + + if (!menu) + return false; + + d3d->menu = menu; + d3d->cur_mon_id = 0; + d3d->menu->tex_coords[0] = 0; + d3d->menu->tex_coords[1] = 0; + d3d->menu->tex_coords[2] = 1; + d3d->menu->tex_coords[3] = 1; + d3d->menu->vert_coords[0] = 0; + d3d->menu->vert_coords[1] = 1; + d3d->menu->vert_coords[2] = 1; + d3d->menu->vert_coords[3] = -1; + +#ifdef HAVE_WINDOW + memset(&d3d->windowClass, 0, sizeof(d3d->windowClass)); + d3d->windowClass.lpfnWndProc = wnd_proc_d3d_common; +#ifdef HAVE_DINPUT + if (string_is_equal(settings->arrays.input_driver, "dinput")) + d3d->windowClass.lpfnWndProc = wnd_proc_d3d_dinput; +#endif +#ifdef HAVE_WINRAWINPUT + if (string_is_equal(settings->arrays.input_driver, "raw")) + d3d->windowClass.lpfnWndProc = wnd_proc_d3d_winraw; +#endif + win32_window_init(&d3d->windowClass, true, NULL); +#endif + +#ifdef HAVE_MONITOR + win32_monitor_info(¤t_mon, &hm_to_use, &d3d->cur_mon_id); + + mon_rect = current_mon.rcMonitor; + g_win32_resize_width = info->width; + g_win32_resize_height = info->height; + + windowed_full = settings->bools.video_windowed_fullscreen; + + full_x = (windowed_full || info->width == 0) ? + (mon_rect.right - mon_rect.left) : info->width; + full_y = (windowed_full || info->height == 0) ? + (mon_rect.bottom - mon_rect.top) : info->height; + + RARCH_LOG("[D3D9]: Monitor size: %dx%d.\n", + (int)(mon_rect.right - mon_rect.left), + (int)(mon_rect.bottom - mon_rect.top)); +#else + { + d3d9_get_video_size(d3d, &full_x, &full_y); + } +#endif + { + unsigned new_width = info->fullscreen ? full_x : info->width; + unsigned new_height = info->fullscreen ? full_y : info->height; + video_driver_set_size(new_width, new_height); + } + +#ifdef HAVE_WINDOW + video_driver_get_size(&win_width, &win_height); + + win32_set_style(¤t_mon, &hm_to_use, &win_width, &win_height, + info->fullscreen, windowed_full, &rect, &mon_rect, &style); + + win32_window_create(d3d, style, &mon_rect, win_width, + win_height, info->fullscreen); + + win32_set_window(&win_width, &win_height, info->fullscreen, + windowed_full, &rect); +#endif + + d3d->video_info = *info; + + if (!d3d9_cg_initialize(d3d, &d3d->video_info)) + return false; + + d3d9_cg_fake_context.get_flags = d3d9_cg_get_flags; + d3d9_cg_fake_context.get_metrics = win32_get_metrics; + video_context_driver_set(&d3d9_cg_fake_context); + { + const char *shader_preset = retroarch_get_shader_preset(); + enum rarch_shader_type type = video_shader_parse_type(shader_preset); + + d3d9_cg_set_shader(d3d, type, shader_preset); + } + + d3d_input_driver(settings->arrays.input_joypad_driver, + settings->arrays.input_joypad_driver, input, input_data); + + { + char version_str[128]; + D3DADAPTER_IDENTIFIER9 ident = {0}; + + IDirect3D9_GetAdapterIdentifier(g_pD3D9, 0, 0, &ident); + + version_str[0] = '\0'; + + snprintf(version_str, sizeof(version_str), "%u.%u.%u.%u", + HIWORD(ident.DriverVersion.HighPart), + LOWORD(ident.DriverVersion.HighPart), + HIWORD(ident.DriverVersion.LowPart), + LOWORD(ident.DriverVersion.LowPart)); + + RARCH_LOG("[D3D9]: Using GPU: \"%s\".\n", ident.Description); + RARCH_LOG("[D3D9]: GPU API Version: %s\n", version_str); + + video_driver_set_gpu_device_string(ident.Description); + video_driver_set_gpu_api_version_string(version_str); + } + + RARCH_LOG("[D3D9]: Init complete.\n"); + return true; +} + +static void *d3d9_cg_init(const video_info_t *info, + input_driver_t **input, void **input_data) +{ + d3d9_video_t *d3d = (d3d9_video_t*)calloc(1, sizeof(*d3d)); + + if (!d3d) + return NULL; + + if (!d3d9_initialize_symbols(GFX_CTX_DIRECT3D9_API)) + { + free(d3d); + return NULL; + } + + win32_window_reset(); + win32_monitor_init(); + + /* Default values */ + d3d->dev = NULL; + d3d->dev_rotation = 0; + d3d->needs_restore = false; +#ifdef HAVE_OVERLAY + d3d->overlays_enabled = false; +#endif + d3d->should_resize = false; + d3d->menu = NULL; + + if (!d3d9_cg_init_internal(d3d, info, input, input_data)) + { + RARCH_ERR("[D3D9]: Failed to init D3D.\n"); + free(d3d); + return NULL; + } + + d3d->keep_aspect = info->force_aspect; + + return d3d; +} + +static void d3d9_cg_free(void *data) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + +#ifdef HAVE_OVERLAY + d3d9_free_overlays(d3d); + if (d3d->overlays) + free(d3d->overlays); + d3d->overlays = NULL; + d3d->overlays_size = 0; +#endif + + d3d9_free_overlay(d3d, d3d->menu); + if (d3d->menu) + free(d3d->menu); + d3d->menu = NULL; + + d3d9_cg_deinitialize(d3d); + + if (!string_is_empty(d3d->shader_path)) + free(d3d->shader_path); + + d3d->shader_path = NULL; + d3d9_device_free(d3d->dev, g_pD3D9); + d3d->dev = NULL; + g_pD3D9 = NULL; + + d3d9_deinitialize_symbols(); + + win32_monitor_from_window(); + win32_destroy_window(); + free(d3d); +} + +static bool d3d9_cg_frame(void *data, const void *frame, + unsigned frame_width, unsigned frame_height, + uint64_t frame_count, unsigned pitch, + const char *msg, video_frame_info_t *video_info) +{ + D3DVIEWPORT9 screen_vp; + unsigned i = 0; + d3d9_video_t *d3d = (d3d9_video_t*)data; + unsigned width = video_info->width; + unsigned height = video_info->height; + bool statistics_show = video_info->statistics_show; + unsigned black_frame_insertion = video_info->black_frame_insertion; + struct font_params *osd_params = (struct font_params*) + &video_info->osd_stat_params; + const char *stat_text = video_info->stat_text; + bool menu_is_alive = video_info->menu_is_alive; + bool overlay_behind_menu = video_info->overlay_behind_menu; +#ifdef HAVE_GFX_WIDGETS + bool widgets_active = video_info->widgets_active; +#endif + + if (!frame) + return true; + + /* We cannot recover in fullscreen. */ + if (d3d->needs_restore) + { + HWND window = win32_get_window(); + if (IsIconic(window)) + return true; + + if (!d3d9_cg_restore(d3d)) + { + RARCH_ERR("[D3D9]: Failed to restore.\n"); + return false; + } + } + + if (d3d->should_resize) + { + d3d9_set_viewport(d3d, width, height, false, true); + if (d3d->renderchain_driver->set_final_viewport) + d3d->renderchain_driver->set_final_viewport(d3d, + d3d->renderchain_data, &d3d->final_viewport); + + d3d->should_resize = false; + } + + /* render_chain() only clears out viewport, + * clear out everything. */ + screen_vp.X = 0; + screen_vp.Y = 0; + screen_vp.MinZ = 0; + screen_vp.MaxZ = 1; + screen_vp.Width = width; + screen_vp.Height = height; + d3d9_set_viewports(d3d->dev, &screen_vp); + IDirect3DDevice9_Clear(d3d->dev, 0, 0, D3DCLEAR_TARGET, + 0, 1, 0); + + d3d9_set_vertex_shader_constantf(d3d->dev, 0, (const float*)&d3d->mvp_transposed, 4); + if (!d3d->renderchain_driver->render( + d3d, frame, frame_width, frame_height, + pitch, d3d->dev_rotation)) + { + RARCH_ERR("[D3D9]: Failed to render scene.\n"); + return false; + } + + if (black_frame_insertion && !d3d->menu->enabled) + { + unsigned n; + for (n = 0; n < video_info->black_frame_insertion; ++n) + { + bool ret = (IDirect3DDevice9_Present(d3d->dev, + NULL, NULL, NULL, NULL) != D3DERR_DEVICELOST); + if (!ret || d3d->needs_restore) + return true; + IDirect3DDevice9_Clear(d3d->dev, 0, 0, D3DCLEAR_TARGET, + 0, 1, 0); + } + } + +#ifdef HAVE_OVERLAY + if (d3d->overlays_enabled && overlay_behind_menu) + { + d3d9_set_vertex_shader_constantf(d3d->dev, 0, (const float*)&d3d->mvp_transposed, 4); + for (i = 0; i < d3d->overlays_size; i++) + d3d9_overlay_render(d3d, width, height, &d3d->overlays[i], true); + } +#endif + +#ifdef HAVE_MENU + if (d3d->menu && d3d->menu->enabled) + { + d3d9_set_vertex_shader_constantf(d3d->dev, 0, (const + float*)&d3d->mvp_transposed, 4); + d3d9_overlay_render(d3d, width, height, d3d->menu, false); + + d3d->menu_display.offset = 0; + d3d9_set_vertex_declaration(d3d->dev, (LPDIRECT3DVERTEXDECLARATION9)d3d->menu_display.decl); + d3d9_set_stream_source(d3d->dev, 0, (LPDIRECT3DVERTEXBUFFER9)d3d->menu_display.buffer, 0, sizeof(Vertex)); + + d3d9_set_viewports(d3d->dev, &screen_vp); + menu_driver_frame(menu_is_alive, video_info); + } + else if (statistics_show) + { + if (osd_params) + { + d3d9_set_viewports(d3d->dev, &screen_vp); + d3d9_begin_scene(d3d->dev); + font_driver_render_msg(d3d, stat_text, + (const struct font_params*)osd_params, NULL); + d3d9_end_scene(d3d->dev); + } + } +#endif + +#ifdef HAVE_OVERLAY + if (d3d->overlays_enabled && !overlay_behind_menu) + { + d3d9_set_vertex_shader_constantf(d3d->dev, 0, (const + float*)&d3d->mvp_transposed, 4); + for (i = 0; i < d3d->overlays_size; i++) + d3d9_overlay_render(d3d, width, height, &d3d->overlays[i], true); + } +#endif + +#ifdef HAVE_GFX_WIDGETS + if (widgets_active) + gfx_widgets_frame(video_info); +#endif + + if (msg && *msg) + { + d3d9_set_viewports(d3d->dev, &screen_vp); + d3d9_begin_scene(d3d->dev); + font_driver_render_msg(d3d, msg, NULL, NULL); + d3d9_end_scene(d3d->dev); + } + + win32_update_title(); + IDirect3DDevice9_Present(d3d->dev, NULL, NULL, NULL, NULL); + + return true; +} + +static const video_poke_interface_t d3d9_cg_poke_interface = { + d3d9_cg_get_flags, + d3d9_load_texture, + d3d9_unload_texture, + d3d9_set_video_mode, +#if defined(__WINRT__) + NULL, +#else + /* UWP does not expose this information easily */ + win32_get_refresh_rate, +#endif + NULL, + NULL, /* get_video_output_size */ + NULL, /* get_video_output_prev */ + NULL, /* get_video_output_next */ + NULL, /* get_current_framebuffer */ + NULL, /* get_proc_address */ + d3d9_set_aspect_ratio, + d3d9_apply_state_changes, + d3d9_set_menu_texture_frame, + d3d9_set_menu_texture_enable, + d3d9_set_osd_msg, + + win32_show_cursor, + NULL, /* grab_mouse_toggle */ + NULL, /* get_current_shader */ + NULL, /* get_current_software_framebuffer */ + NULL, /* get_hw_render_interface */ + NULL, /* set_hdr_max_nits */ + NULL, /* set_hdr_paper_white_nits */ + NULL, /* set_hdr_contrast */ + NULL /* set_hdr_expand_gamut */ +}; + +static void d3d9_cg_get_poke_interface(void *data, + const video_poke_interface_t **iface) +{ + *iface = &d3d9_cg_poke_interface; +} + +#ifdef HAVE_GFX_WIDGETS +static bool d3d9_cg_gfx_widgets_enabled(void *data) +{ + return false; /* currently disabled due to memory issues */ +} +#endif + +static void d3d9_cg_set_resize(d3d9_video_t *d3d, + unsigned new_width, unsigned new_height) +{ + /* No changes? */ + if ( (new_width == d3d->video_info.width) + && (new_height == d3d->video_info.height)) + return; + + d3d->video_info.width = new_width; + d3d->video_info.height = new_height; + video_driver_set_size(new_width, new_height); +} + +static bool d3d9_cg_alive(void *data) +{ + unsigned temp_width = 0; + unsigned temp_height = 0; + bool ret = false; + bool quit = false; + bool resize = false; + d3d9_video_t *d3d = (d3d9_video_t*)data; + + /* Needed because some context drivers don't track their sizes */ + video_driver_get_size(&temp_width, &temp_height); + + win32_check_window(NULL, &quit, &resize, &temp_width, &temp_height); + + if (quit) + d3d->quitting = quit; + + if (resize) + { + d3d->should_resize = true; + d3d9_cg_set_resize(d3d, temp_width, temp_height); + d3d9_cg_restore(d3d); + } + + ret = !quit; + + if ( temp_width != 0 && + temp_height != 0) + video_driver_set_size(temp_width, temp_height); + + return ret; +} + +static void d3d9_cg_set_nonblock_state(void *data, bool state, + bool adaptive_vsync_enabled, + unsigned swap_interval) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + + d3d->video_info.vsync = !state; + d3d->needs_restore = true; + d3d9_cg_restore(d3d); +} + +video_driver_t video_d3d9_cg = { + d3d9_cg_init, + d3d9_cg_frame, + d3d9_cg_set_nonblock_state, + d3d9_cg_alive, + NULL, /* focus */ + d3d9_suppress_screensaver, + d3d9_has_windowed, + d3d9_cg_set_shader, + d3d9_cg_free, + "d3d9_cg", + d3d9_set_viewport, + d3d9_set_rotation, + d3d9_viewport_info, + d3d9_read_viewport, + NULL, /* read_frame_raw */ +#ifdef HAVE_OVERLAY + d3d9_get_overlay_interface, +#endif +#ifdef HAVE_VIDEO_LAYOUT + NULL, +#endif + d3d9_cg_get_poke_interface, + NULL, /* wrap_type_to_enum */ +#ifdef HAVE_GFX_WIDGETS + d3d9_cg_gfx_widgets_enabled +#endif +}; diff --git a/gfx/drivers/d3d9.c b/gfx/drivers/d3d9hlsl.c similarity index 87% rename from gfx/drivers/d3d9.c rename to gfx/drivers/d3d9hlsl.c index 52dac50982..a966565ea2 100644 --- a/gfx/drivers/d3d9.c +++ b/gfx/drivers/d3d9hlsl.c @@ -15,11 +15,12 @@ * If not, see . */ -/* Direct3D 9 driver. +/* Direct3D 9 driver with HLSL runtime backend. * * Minimum version : Direct3D 9.0 (2002) * Minimum OS : Windows 98, Windows 2000, Windows ME * Recommended OS : Windows XP + * Requirements : HLSL or fixed function backend */ #define CINTERFACE @@ -70,29 +71,22 @@ #endif /* TODO/FIXME - Temporary workaround for D3D9 not being able to poll flags during init */ -static gfx_ctx_driver_t d3d9_fake_context; +static gfx_ctx_driver_t d3d9_hlsl_fake_context; -static enum rarch_shader_type supported_shader_type = RARCH_SHADER_NONE; - -extern d3d9_renderchain_driver_t cg_d3d9_renderchain; extern d3d9_renderchain_driver_t hlsl_d3d9_renderchain; -static uint32_t d3d9_get_flags(void *data) +static uint32_t d3d9_hlsl_get_flags(void *data) { uint32_t flags = 0; BIT32_SET(flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION); BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); - - if (supported_shader_type == RARCH_SHADER_CG) - BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_CG); - else if (supported_shader_type == RARCH_SHADER_HLSL) - BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_HLSL); + BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_HLSL); return flags; } -static void d3d9_deinit_chain(d3d9_video_t *d3d) +static void d3d9_hlsl_deinit_chain(d3d9_video_t *d3d) { if (!d3d || !d3d->renderchain_driver) return; @@ -104,14 +98,11 @@ static void d3d9_deinit_chain(d3d9_video_t *d3d) d3d->renderchain_data = NULL; } -static void d3d9_deinitialize(d3d9_video_t *d3d) +static void d3d9_hlsl_deinitialize(d3d9_video_t *d3d) { - if (!d3d) - return; - font_driver_free_osd(); - d3d9_deinit_chain(d3d); + d3d9_hlsl_deinit_chain(d3d); d3d9_vertex_buffer_free(d3d->menu_display.buffer, d3d->menu_display.decl); @@ -119,7 +110,7 @@ static void d3d9_deinitialize(d3d9_video_t *d3d) d3d->menu_display.decl = NULL; } -static bool d3d9_init_base(d3d9_video_t *d3d, const video_info_t *info) +static bool d3d9_hlsl_init_base(d3d9_video_t *d3d, const video_info_t *info) { D3DPRESENT_PARAMETERS d3dpp; #ifndef _XBOX @@ -144,7 +135,7 @@ static bool d3d9_init_base(d3d9_video_t *d3d, const video_info_t *info) return true; } -static bool renderchain_d3d_init_first( +static bool renderchain_d3d_hlsl_init_first( enum gfx_ctx_api api, const d3d9_renderchain_driver_t **renderchain_driver, void **renderchain_handle) @@ -155,12 +146,7 @@ static bool renderchain_d3d_init_first( { static const d3d9_renderchain_driver_t *renderchain_d3d_drivers[] = { -#if defined(_WIN32) && defined(HAVE_CG) - &cg_d3d9_renderchain, -#endif -#if defined(_WIN32) && defined(HAVE_HLSL) &hlsl_d3d9_renderchain, -#endif NULL }; unsigned i; @@ -175,11 +161,6 @@ static bool renderchain_d3d_init_first( *renderchain_driver = renderchain_d3d_drivers[i]; *renderchain_handle = data; - if (string_is_equal(renderchain_d3d_drivers[i]->ident, "cg_d3d9")) - supported_shader_type = RARCH_SHADER_CG; - else if (string_is_equal(renderchain_d3d_drivers[i]->ident, "hlsl_d3d9")) - supported_shader_type = RARCH_SHADER_HLSL; - return true; } } @@ -192,8 +173,7 @@ static bool renderchain_d3d_init_first( return false; } - -static bool d3d9_init_chain(d3d9_video_t *d3d, +static bool d3d9_hlsl_init_chain(d3d9_video_t *d3d, unsigned input_scale, bool rgb32) { @@ -209,7 +189,7 @@ static bool d3d9_init_chain(d3d9_video_t *d3d, link_info.tex_h = input_scale * RARCH_SCALE_BASE; link_info.pass = &d3d->shader.pass[0]; - if (!renderchain_d3d_init_first(GFX_CTX_DIRECT3D9_API, + if (!renderchain_d3d_hlsl_init_first(GFX_CTX_DIRECT3D9_API, &d3d->renderchain_driver, &d3d->renderchain_data)) { @@ -291,15 +271,14 @@ static bool d3d9_init_chain(d3d9_video_t *d3d, return true; } - -static bool d3d9_initialize(d3d9_video_t *d3d, const video_info_t *info) +static bool d3d9_hlsl_initialize(d3d9_video_t *d3d, const video_info_t *info) { unsigned width, height; bool ret = true; settings_t *settings = config_get_ptr(); if (!g_pD3D9) - ret = d3d9_init_base(d3d, info); + ret = d3d9_hlsl_init_base(d3d, info); else if (d3d->needs_restore) { D3DPRESENT_PARAMETERS d3dpp; @@ -316,11 +295,11 @@ static bool d3d9_initialize(d3d9_video_t *d3d, const video_info_t *info) if (!d3d9_reset(d3d->dev, &d3dpp)) { - d3d9_deinitialize(d3d); + d3d9_hlsl_deinitialize(d3d); d3d9_device_free(NULL, g_pD3D9); g_pD3D9 = NULL; - ret = d3d9_init_base(d3d, info); + ret = d3d9_hlsl_init_base(d3d, info); if (ret) RARCH_LOG("[D3D9]: Recovered from dead state.\n"); } @@ -333,7 +312,7 @@ static bool d3d9_initialize(d3d9_video_t *d3d, const video_info_t *info) if (!ret) return ret; - if (!d3d9_init_chain(d3d, info->input_scale, info->rgb32)) + if (!d3d9_hlsl_init_chain(d3d, info->input_scale, info->rgb32)) { RARCH_ERR("[D3D9]: Failed to initialize render chain.\n"); return false; @@ -388,12 +367,11 @@ static bool d3d9_initialize(d3d9_video_t *d3d, const video_info_t *info) return true; } - -static bool d3d9_restore(d3d9_video_t *d3d) +static bool d3d9_hlsl_restore(d3d9_video_t *d3d) { - d3d9_deinitialize(d3d); + d3d9_hlsl_deinitialize(d3d); - if (!d3d9_initialize(d3d, &d3d->video_info)) + if (!d3d9_hlsl_initialize(d3d, &d3d->video_info)) { RARCH_ERR("[D3D9]: Restore error.\n"); return false; @@ -404,11 +382,9 @@ static bool d3d9_restore(d3d9_video_t *d3d) return true; } - -static bool d3d9_set_shader(void *data, +static bool d3d9_hlsl_set_shader(void *data, enum rarch_shader_type type, const char *path) { -#if defined(HAVE_CG) || defined(HAVE_HLSL) d3d9_video_t *d3d = (d3d9_video_t*)data; if (!d3d) @@ -422,14 +398,6 @@ static bool d3d9_set_shader(void *data, { case RARCH_SHADER_CG: case RARCH_SHADER_HLSL: - - if (type != supported_shader_type) - { - RARCH_WARN("[D3D9]: Shader preset %s is using unsupported shader type %s, falling back to stock %s.\n", - path, video_shader_type_to_str(type), video_shader_type_to_str(supported_shader_type)); - break; - } - if (!string_is_empty(path)) d3d->shader_path = strdup(path); @@ -440,19 +408,16 @@ static bool d3d9_set_shader(void *data, RARCH_WARN("[D3D9]: Only Cg shaders are supported. Falling back to stock.\n"); } - if (!d3d9_process_shader(d3d) || !d3d9_restore(d3d)) + if (!d3d9_process_shader(d3d) || !d3d9_hlsl_restore(d3d)) { RARCH_ERR("[D3D9]: Failed to set shader.\n"); return false; } return true; -#else - return false; -#endif } -static bool d3d9_init_internal(d3d9_video_t *d3d, +static bool d3d9_hlsl_init_internal(d3d9_video_t *d3d, const video_info_t *info, input_driver_t **input, void **input_data) { @@ -544,22 +509,20 @@ static bool d3d9_init_internal(d3d9_video_t *d3d, d3d->video_info = *info; - if (!d3d9_initialize(d3d, &d3d->video_info)) + if (!d3d9_hlsl_initialize(d3d, &d3d->video_info)) return false; - d3d9_fake_context.get_flags = d3d9_get_flags; + d3d9_hlsl_fake_context.get_flags = d3d9_hlsl_get_flags; #ifndef _XBOX_ - d3d9_fake_context.get_metrics = win32_get_metrics; + d3d9_hlsl_fake_context.get_metrics = win32_get_metrics; #endif - video_context_driver_set(&d3d9_fake_context); -#if defined(HAVE_CG) || defined(HAVE_HLSL) + video_context_driver_set(&d3d9_hlsl_fake_context); { const char *shader_preset = retroarch_get_shader_preset(); enum rarch_shader_type type = video_shader_parse_type(shader_preset); - d3d9_set_shader(d3d, type, shader_preset); + d3d9_hlsl_set_shader(d3d, type, shader_preset); } -#endif d3d_input_driver(settings->arrays.input_joypad_driver, settings->arrays.input_joypad_driver, input, input_data); @@ -589,7 +552,7 @@ static bool d3d9_init_internal(d3d9_video_t *d3d, return true; } -static void *d3d9_init(const video_info_t *info, +static void *d3d9_hlsl_init(const video_info_t *info, input_driver_t **input, void **input_data) { d3d9_video_t *d3d = (d3d9_video_t*)calloc(1, sizeof(*d3d)); @@ -618,7 +581,7 @@ static void *d3d9_init(const video_info_t *info, d3d->should_resize = false; d3d->menu = NULL; - if (!d3d9_init_internal(d3d, info, input, input_data)) + if (!d3d9_hlsl_init_internal(d3d, info, input, input_data)) { RARCH_ERR("[D3D9]: Failed to init D3D.\n"); free(d3d); @@ -630,7 +593,7 @@ static void *d3d9_init(const video_info_t *info, return d3d; } -static void d3d9_free(void *data) +static void d3d9_hlsl_free(void *data) { d3d9_video_t *d3d = (d3d9_video_t*)data; @@ -650,7 +613,7 @@ static void d3d9_free(void *data) free(d3d->menu); d3d->menu = NULL; - d3d9_deinitialize(d3d); + d3d9_hlsl_deinitialize(d3d); if (!string_is_empty(d3d->shader_path)) free(d3d->shader_path); @@ -669,7 +632,7 @@ static void d3d9_free(void *data) free(d3d); } -static bool d3d9_frame(void *data, const void *frame, +static bool d3d9_hlsl_frame(void *data, const void *frame, unsigned frame_width, unsigned frame_height, uint64_t frame_count, unsigned pitch, const char *msg, video_frame_info_t *video_info) @@ -702,7 +665,7 @@ static bool d3d9_frame(void *data, const void *frame, return true; #endif - if (!d3d9_restore(d3d)) + if (!d3d9_hlsl_restore(d3d)) { RARCH_ERR("[D3D9]: Failed to restore.\n"); return false; @@ -824,8 +787,8 @@ static bool d3d9_frame(void *data, const void *frame, return true; } -static const video_poke_interface_t d3d9_poke_interface = { - d3d9_get_flags, +static const video_poke_interface_t d3d9_hlsl_poke_interface = { + d3d9_hlsl_get_flags, d3d9_load_texture, d3d9_unload_texture, d3d9_set_video_mode, @@ -858,20 +821,20 @@ static const video_poke_interface_t d3d9_poke_interface = { NULL /* set_hdr_expand_gamut */ }; -static void d3d9_get_poke_interface(void *data, +static void d3d9_hlsl_get_poke_interface(void *data, const video_poke_interface_t **iface) { - *iface = &d3d9_poke_interface; + *iface = &d3d9_hlsl_poke_interface; } #ifdef HAVE_GFX_WIDGETS -static bool d3d9_gfx_widgets_enabled(void *data) +static bool d3d9_hlsl_gfx_widgets_enabled(void *data) { return false; /* currently disabled due to memory issues */ } #endif -static void d3d9_set_resize(d3d9_video_t *d3d, +static void d3d9_hlsl_set_resize(d3d9_video_t *d3d, unsigned new_width, unsigned new_height) { /* No changes? */ @@ -884,7 +847,7 @@ static void d3d9_set_resize(d3d9_video_t *d3d, video_driver_set_size(new_width, new_height); } -static bool d3d9_alive(void *data) +static bool d3d9_hlsl_alive(void *data) { unsigned temp_width = 0; unsigned temp_height = 0; @@ -904,8 +867,8 @@ static bool d3d9_alive(void *data) if (resize) { d3d->should_resize = true; - d3d9_set_resize(d3d, temp_width, temp_height); - d3d9_restore(d3d); + d3d9_hlsl_set_resize(d3d, temp_width, temp_height); + d3d9_hlsl_restore(d3d); } ret = !quit; @@ -917,7 +880,7 @@ static bool d3d9_alive(void *data) return ret; } -static void d3d9_set_nonblock_state(void *data, bool state, +static void d3d9_hlsl_set_nonblock_state(void *data, bool state, bool adaptive_vsync_enabled, unsigned swap_interval) { @@ -944,21 +907,21 @@ static void d3d9_set_nonblock_state(void *data, bool state, ); #else d3d->needs_restore = true; - d3d9_restore(d3d); + d3d9_hlsl_restore(d3d); #endif } -video_driver_t video_d3d9 = { - d3d9_init, - d3d9_frame, - d3d9_set_nonblock_state, - d3d9_alive, +video_driver_t video_d3d9_hlsl = { + d3d9_hlsl_init, + d3d9_hlsl_frame, + d3d9_hlsl_set_nonblock_state, + d3d9_hlsl_alive, NULL, /* focus */ d3d9_suppress_screensaver, d3d9_has_windowed, - d3d9_set_shader, - d3d9_free, - "d3d9", + d3d9_hlsl_set_shader, + d3d9_hlsl_free, + "d3d9_hlsl", d3d9_set_viewport, d3d9_set_rotation, d3d9_viewport_info, @@ -970,9 +933,9 @@ video_driver_t video_d3d9 = { #ifdef HAVE_VIDEO_LAYOUT NULL, #endif - d3d9_get_poke_interface, + d3d9_hlsl_get_poke_interface, NULL, /* wrap_type_to_enum */ #ifdef HAVE_GFX_WIDGETS - d3d9_gfx_widgets_enabled + d3d9_hlsl_gfx_widgets_enabled #endif }; diff --git a/gfx/drivers_display/gfx_display_d3d9cg.c b/gfx/drivers_display/gfx_display_d3d9cg.c new file mode 100644 index 0000000000..604ca130ae --- /dev/null +++ b/gfx/drivers_display/gfx_display_d3d9cg.c @@ -0,0 +1,325 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#define CINTERFACE + +#include + +#include + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + +#include "../gfx_display.h" + +#include "../../retroarch.h" +#include "../common/d3d_common.h" +#include "../common/d3d9_common.h" + +static const float d3d9_cg_vertexes[] = { + 0, 0, + 1, 0, + 0, 1, + 1, 1 +}; + +static const float d3d9_cg_tex_coords[] = { + 0, 1, + 1, 1, + 0, 0, + 1, 0 +}; + +static const float *gfx_display_d3d9_cg_get_default_vertices(void) +{ + return &d3d9_cg_vertexes[0]; +} + +static const float *gfx_display_d3d9_cg_get_default_tex_coords(void) +{ + return &d3d9_cg_tex_coords[0]; +} + +static void *gfx_display_d3d9_cg_get_default_mvp(void *data) +{ + static float id[] = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + return &id; +} + +static INT32 gfx_display_prim_to_d3d9_cg_enum( + enum gfx_display_prim_type prim_type) +{ + switch (prim_type) + { + case GFX_DISPLAY_PRIM_TRIANGLES: + case GFX_DISPLAY_PRIM_TRIANGLESTRIP: + return D3DPT_COMM_TRIANGLESTRIP; + case GFX_DISPLAY_PRIM_NONE: + default: + break; + } + + /* TODO/FIXME - hack */ + return 0; +} + +static void gfx_display_d3d9_cg_blend_begin(void *data) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + + d3d9_enable_blend_func(d3d->dev); +} + +static void gfx_display_d3d9_cg_blend_end(void *data) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + + d3d9_disable_blend_func(d3d->dev); +} + +static void gfx_display_d3d9_cg_bind_texture(gfx_display_ctx_draw_t *draw, + d3d9_video_t *d3d) +{ + LPDIRECT3DDEVICE9 dev = d3d->dev; + + d3d9_set_texture(dev, 0, (LPDIRECT3DTEXTURE9)draw->texture); + d3d9_set_sampler_address_u(dev, 0, D3DTADDRESS_COMM_CLAMP); + d3d9_set_sampler_address_v(dev, 0, D3DTADDRESS_COMM_CLAMP); + d3d9_set_sampler_minfilter(dev, 0, D3DTEXF_COMM_LINEAR); + d3d9_set_sampler_magfilter(dev, 0, D3DTEXF_COMM_LINEAR); + d3d9_set_sampler_mipfilter(dev, 0, D3DTEXF_COMM_LINEAR); +} + +static void gfx_display_d3d9_cg_draw(gfx_display_ctx_draw_t *draw, + void *data, unsigned video_width, unsigned video_height) +{ + unsigned i; + math_matrix_4x4 mop, m1, m2; + LPDIRECT3DDEVICE9 dev; + d3d9_video_t *d3d = (d3d9_video_t*)data; + Vertex * pv = NULL; + const float *vertex = NULL; + const float *tex_coord = NULL; + const float *color = NULL; + + if (!d3d || !draw || draw->pipeline_id) + return; + + dev = d3d->dev; + + if ((d3d->menu_display.offset + draw->coords->vertices ) + > (unsigned)d3d->menu_display.size) + return; + + pv = (Vertex*) + d3d9_vertex_buffer_lock((LPDIRECT3DVERTEXBUFFER9) + d3d->menu_display.buffer); + + if (!pv) + return; + + pv += d3d->menu_display.offset; + vertex = draw->coords->vertex; + tex_coord = draw->coords->tex_coord; + color = draw->coords->color; + + if (!vertex) + vertex = &d3d9_cg_vertexes[0]; + if (!tex_coord) + tex_coord = &d3d9_cg_tex_coords[0]; + + for (i = 0; i < draw->coords->vertices; i++) + { + int colors[4]; + + colors[0] = *color++ * 0xFF; + colors[1] = *color++ * 0xFF; + colors[2] = *color++ * 0xFF; + colors[3] = *color++ * 0xFF; + + pv[i].x = *vertex++; + pv[i].y = *vertex++; + pv[i].z = 0.5f; + pv[i].u = *tex_coord++; + pv[i].v = *tex_coord++; + + pv[i].color = + D3DCOLOR_ARGB( + colors[3], /* A */ + colors[0], /* R */ + colors[1], /* G */ + colors[2] /* B */ + ); + } + d3d9_vertex_buffer_unlock((LPDIRECT3DVERTEXBUFFER9) + d3d->menu_display.buffer); + + if (!draw->matrix_data) + draw->matrix_data = gfx_display_d3d9_cg_get_default_mvp(d3d); + + /* ugh */ + matrix_4x4_scale(m1, 2.0, 2.0, 0); + matrix_4x4_translate(mop, -1.0, -1.0, 0); + matrix_4x4_multiply(m2, mop, m1); + matrix_4x4_multiply(m1, + *((math_matrix_4x4*)draw->matrix_data), m2); + matrix_4x4_scale(mop, + (draw->width / 2.0) / video_width, + (draw->height / 2.0) / video_height, 0); + matrix_4x4_multiply(m2, mop, m1); + matrix_4x4_translate(mop, + (draw->x + (draw->width / 2.0)) / video_width, + (draw->y + (draw->height / 2.0)) / video_height, + 0); + matrix_4x4_multiply(m1, mop, m2); + matrix_4x4_multiply(m2, d3d->mvp_transposed, m1); + + d3d9_set_vertex_shader_constantf(d3d->dev, 0, (const float*)&m2, 4); + + if (draw && draw->texture) + gfx_display_d3d9_cg_bind_texture(draw, d3d); + + d3d9_draw_primitive(dev, + (D3DPRIMITIVETYPE)gfx_display_prim_to_d3d9_cg_enum(draw->prim_type), + d3d->menu_display.offset, + draw->coords->vertices - + ((draw->prim_type == GFX_DISPLAY_PRIM_TRIANGLESTRIP) + ? 2 : 0)); + + d3d->menu_display.offset += draw->coords->vertices; +} + +static void gfx_display_d3d9_cg_draw_pipeline(gfx_display_ctx_draw_t *draw, + gfx_display_t *p_disp, + void *data, unsigned video_width, unsigned video_height) +{ +#if defined(HAVE_HLSL) || defined(HAVE_CG) + static float t = 0; + video_coord_array_t *ca = NULL; + + if (!draw) + return; + + ca = &p_disp->dispca; + + draw->x = 0; + draw->y = 0; + draw->coords = NULL; + draw->matrix_data = NULL; + + if (ca) + draw->coords = (struct video_coords*)&ca->coords; + + switch (draw->pipeline_id) + { + case VIDEO_SHADER_MENU: + case VIDEO_SHADER_MENU_2: + case VIDEO_SHADER_MENU_3: + { + struct uniform_info uniform_param = {0}; + t += 0.01; + + (void)uniform_param; + + uniform_param.enabled = true; + uniform_param.lookup.enable = true; + uniform_param.lookup.add_prefix = true; + uniform_param.lookup.idx = draw->pipeline_id; + uniform_param.lookup.type = SHADER_PROGRAM_VERTEX; + uniform_param.type = UNIFORM_1F; + uniform_param.lookup.ident = "time"; + uniform_param.result.f.v0 = t; + } + break; + } +#endif +} + +static bool gfx_display_d3d9_font_init_first( + void **font_handle, void *video_data, + const char *font_path, float menu_font_size, + bool is_threaded) +{ + font_data_t **handle = (font_data_t**)font_handle; + if (!(*handle = font_driver_init_first(video_data, + font_path, menu_font_size, true, + is_threaded, + FONT_DRIVER_RENDER_D3D9_API))) + return false; + return true; +} + +void gfx_display_d3d9_cg_scissor_begin( + void *data, + unsigned video_width, unsigned video_height, + int x, int y, unsigned width, unsigned height) +{ + RECT rect; + d3d9_video_t *d3d9 = (d3d9_video_t*)data; + + if (!d3d9 || !width || !height) + return; + + rect.left = x; + rect.top = y; + rect.right = width + x; + rect.bottom = height + y; + + d3d9_set_scissor_rect(d3d9->dev, &rect); +} + +void gfx_display_d3d9_cg_scissor_end(void *data, + unsigned video_width, unsigned video_height) +{ + RECT rect; + d3d9_video_t *d3d9 = (d3d9_video_t*)data; + + if (!d3d9) + return; + + rect.left = 0; + rect.top = 0; + rect.right = video_width; + rect.bottom = video_height; + + d3d9_set_scissor_rect(d3d9->dev, &rect); +} + +gfx_display_ctx_driver_t gfx_display_ctx_d3d9 = { + gfx_display_d3d9_cg_draw, + gfx_display_d3d9_cg_draw_pipeline, + gfx_display_d3d9_cg_blend_begin, + gfx_display_d3d9_cg_blend_end, + gfx_display_d3d9_cg_get_default_mvp, + gfx_display_d3d9_cg_get_default_vertices, + gfx_display_d3d9_cg_get_default_tex_coords, + gfx_display_d3d9_font_init_first, + GFX_VIDEO_DRIVER_DIRECT3D9_CG, + "d3d9_cg", + false, + gfx_display_d3d9_cg_scissor_begin, + gfx_display_d3d9_cg_scissor_end +}; diff --git a/gfx/drivers_display/gfx_display_d3d9.c b/gfx/drivers_display/gfx_display_d3d9hlsl.c similarity index 84% rename from gfx/drivers_display/gfx_display_d3d9.c rename to gfx/drivers_display/gfx_display_d3d9hlsl.c index 997f655526..b85d0b5cb8 100644 --- a/gfx/drivers_display/gfx_display_d3d9.c +++ b/gfx/drivers_display/gfx_display_d3d9hlsl.c @@ -29,31 +29,31 @@ #include "../common/d3d_common.h" #include "../common/d3d9_common.h" -static const float d3d9_vertexes[] = { +static const float d3d9_hlsl_vertexes[] = { 0, 0, 1, 0, 0, 1, 1, 1 }; -static const float d3d9_tex_coords[] = { +static const float d3d9_hlsl_tex_coords[] = { 0, 1, 1, 1, 0, 0, 1, 0 }; -static const float *gfx_display_d3d9_get_default_vertices(void) +static const float *gfx_display_d3d9_hlsl_get_default_vertices(void) { - return &d3d9_vertexes[0]; + return &d3d9_hlsl_vertexes[0]; } -static const float *gfx_display_d3d9_get_default_tex_coords(void) +static const float *gfx_display_d3d9_hlsl_get_default_tex_coords(void) { - return &d3d9_tex_coords[0]; + return &d3d9_hlsl_tex_coords[0]; } -static void *gfx_display_d3d9_get_default_mvp(void *data) +static void *gfx_display_d3d9_hlsl_get_default_mvp(void *data) { static float id[] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, @@ -80,7 +80,7 @@ static INT32 gfx_display_prim_to_d3d9_enum( return 0; } -static void gfx_display_d3d9_blend_begin(void *data) +static void gfx_display_d3d9_hlsl_blend_begin(void *data) { d3d9_video_t *d3d = (d3d9_video_t*)data; @@ -90,7 +90,7 @@ static void gfx_display_d3d9_blend_begin(void *data) d3d9_enable_blend_func(d3d->dev); } -static void gfx_display_d3d9_blend_end(void *data) +static void gfx_display_d3d9_hlsl_blend_end(void *data) { d3d9_video_t *d3d = (d3d9_video_t*)data; @@ -113,7 +113,7 @@ static void gfx_display_d3d9_bind_texture(gfx_display_ctx_draw_t *draw, d3d9_set_sampler_mipfilter(dev, 0, D3DTEXF_COMM_LINEAR); } -static void gfx_display_d3d9_draw(gfx_display_ctx_draw_t *draw, +static void gfx_display_d3d9_hlsl_draw(gfx_display_ctx_draw_t *draw, void *data, unsigned video_width, unsigned video_height) { unsigned i; @@ -147,9 +147,9 @@ static void gfx_display_d3d9_draw(gfx_display_ctx_draw_t *draw, color = draw->coords->color; if (!vertex) - vertex = &d3d9_vertexes[0]; + vertex = &d3d9_hlsl_vertexes[0]; if (!tex_coord) - tex_coord = &d3d9_tex_coords[0]; + tex_coord = &d3d9_hlsl_tex_coords[0]; for (i = 0; i < draw->coords->vertices; i++) { @@ -178,7 +178,7 @@ static void gfx_display_d3d9_draw(gfx_display_ctx_draw_t *draw, d3d->menu_display.buffer); if (!draw->matrix_data) - draw->matrix_data = gfx_display_d3d9_get_default_mvp(d3d); + draw->matrix_data = gfx_display_d3d9_hlsl_get_default_mvp(d3d); /* ugh */ matrix_4x4_scale(m1, 2.0, 2.0, 0); @@ -212,11 +212,10 @@ static void gfx_display_d3d9_draw(gfx_display_ctx_draw_t *draw, d3d->menu_display.offset += draw->coords->vertices; } -static void gfx_display_d3d9_draw_pipeline(gfx_display_ctx_draw_t *draw, +static void gfx_display_d3d9_hlsl_draw_pipeline(gfx_display_ctx_draw_t *draw, gfx_display_t *p_disp, void *data, unsigned video_width, unsigned video_height) { -#if defined(HAVE_HLSL) || defined(HAVE_CG) static float t = 0; video_coord_array_t *ca = NULL; @@ -255,7 +254,6 @@ static void gfx_display_d3d9_draw_pipeline(gfx_display_ctx_draw_t *draw, } break; } -#endif } static bool gfx_display_d3d9_font_init_first( @@ -272,7 +270,7 @@ static bool gfx_display_d3d9_font_init_first( return true; } -void gfx_display_d3d9_scissor_begin( +void gfx_display_d3d9_hlsl_scissor_begin( void *data, unsigned video_width, unsigned video_height, int x, int y, unsigned width, unsigned height) @@ -291,11 +289,11 @@ void gfx_display_d3d9_scissor_begin( d3d9_set_scissor_rect(d3d9->dev, &rect); } -void gfx_display_d3d9_scissor_end(void *data, +void gfx_display_d3d9_hlsl_scissor_end(void *data, unsigned video_width, unsigned video_height) { RECT rect; - d3d9_video_t *d3d9 = (d3d9_video_t*)data; + d3d9_video_t *d3d9 = (d3d9_video_t*)data; if (!d3d9) return; @@ -308,18 +306,18 @@ void gfx_display_d3d9_scissor_end(void *data, d3d9_set_scissor_rect(d3d9->dev, &rect); } -gfx_display_ctx_driver_t gfx_display_ctx_d3d9 = { - gfx_display_d3d9_draw, - gfx_display_d3d9_draw_pipeline, - gfx_display_d3d9_blend_begin, - gfx_display_d3d9_blend_end, - gfx_display_d3d9_get_default_mvp, - gfx_display_d3d9_get_default_vertices, - gfx_display_d3d9_get_default_tex_coords, +gfx_display_ctx_driver_t gfx_display_ctx_d3d9_hlsl = { + gfx_display_d3d9_hlsl_draw, + gfx_display_d3d9_hlsl_draw_pipeline, + gfx_display_d3d9_hlsl_blend_begin, + gfx_display_d3d9_hlsl_blend_end, + gfx_display_d3d9_hlsl_get_default_mvp, + gfx_display_d3d9_hlsl_get_default_vertices, + gfx_display_d3d9_hlsl_get_default_tex_coords, gfx_display_d3d9_font_init_first, - GFX_VIDEO_DRIVER_DIRECT3D9, - "d3d9", + GFX_VIDEO_DRIVER_DIRECT3D9_HLSL, + "d3d9_hlsl", false, - gfx_display_d3d9_scissor_begin, - gfx_display_d3d9_scissor_end + gfx_display_d3d9_hlsl_scissor_begin, + gfx_display_d3d9_hlsl_scissor_end }; diff --git a/gfx/gfx_display.c b/gfx/gfx_display.c index 33a118b1a3..832230dc6c 100644 --- a/gfx/gfx_display.c +++ b/gfx/gfx_display.c @@ -85,7 +85,12 @@ static gfx_display_ctx_driver_t *gfx_display_ctx_drivers[] = { &gfx_display_ctx_d3d8, #endif #ifdef HAVE_D3D9 - &gfx_display_ctx_d3d9, +#ifdef HAVE_HLSL + &gfx_display_ctx_d3d9_hlsl, +#endif +#ifdef HAVE_CG + &gfx_display_ctx_d3d9_cg, +#endif #endif #ifdef HAVE_D3D10 &gfx_display_ctx_d3d10, @@ -191,8 +196,12 @@ static bool gfx_display_check_compatibility( if (string_is_equal(video_driver, "d3d8")) return true; break; - case GFX_VIDEO_DRIVER_DIRECT3D9: - if (string_is_equal(video_driver, "d3d9")) + case GFX_VIDEO_DRIVER_DIRECT3D9_HLSL: + if (string_is_equal(video_driver, "d3d9_hlsl")) + return true; + break; + case GFX_VIDEO_DRIVER_DIRECT3D9_CG: + if (string_is_equal(video_driver, "d3d9_cg")) return true; break; case GFX_VIDEO_DRIVER_DIRECT3D10: diff --git a/gfx/gfx_display.h b/gfx/gfx_display.h index c30558a61f..337b2ffd17 100644 --- a/gfx/gfx_display.h +++ b/gfx/gfx_display.h @@ -96,7 +96,8 @@ enum gfx_display_driver_type GFX_VIDEO_DRIVER_VULKAN, GFX_VIDEO_DRIVER_METAL, GFX_VIDEO_DRIVER_DIRECT3D8, - GFX_VIDEO_DRIVER_DIRECT3D9, + GFX_VIDEO_DRIVER_DIRECT3D9_CG, + GFX_VIDEO_DRIVER_DIRECT3D9_HLSL, GFX_VIDEO_DRIVER_DIRECT3D10, GFX_VIDEO_DRIVER_DIRECT3D11, GFX_VIDEO_DRIVER_DIRECT3D12, @@ -352,7 +353,8 @@ extern gfx_display_ctx_driver_t gfx_display_ctx_gl1; extern gfx_display_ctx_driver_t gfx_display_ctx_vulkan; extern gfx_display_ctx_driver_t gfx_display_ctx_metal; extern gfx_display_ctx_driver_t gfx_display_ctx_d3d8; -extern gfx_display_ctx_driver_t gfx_display_ctx_d3d9; +extern gfx_display_ctx_driver_t gfx_display_ctx_d3d9_cg; +extern gfx_display_ctx_driver_t gfx_display_ctx_d3d9_hlsl; extern gfx_display_ctx_driver_t gfx_display_ctx_d3d10; extern gfx_display_ctx_driver_t gfx_display_ctx_d3d11; extern gfx_display_ctx_driver_t gfx_display_ctx_d3d12; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 8874829635..ff6db660d2 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -301,7 +301,12 @@ const video_driver_t *video_drivers[] = { &video_d3d10, #endif #if defined(HAVE_D3D9) - &video_d3d9, +#if defined(HAVE_HLSL) + &video_d3d9_hlsl, +#endif +#if defined(HAVE_CG) + &video_d3d9_cg, +#endif #endif #if defined(HAVE_D3D8) &video_d3d8, @@ -453,8 +458,10 @@ video_driver_t *hw_render_context_driver( #endif case RETRO_HW_CONTEXT_DIRECT3D: #if defined(HAVE_D3D9) +#if defined(HAVE_HLSL) if (major == 9) - return &video_d3d9; + return &video_d3d9_hlsl; +#endif #endif #if defined(HAVE_D3D11) if (major == 11) @@ -506,8 +513,10 @@ const char *hw_render_context_name( return "d3d11"; #endif #ifdef HAVE_D3D9 +#if defined(HAVE_HLSL) if (type == RETRO_HW_CONTEXT_DIRECT3D && major == 9) - return "d3d9"; + return "d3d9_hlsl"; +#endif #endif return "N/A"; } @@ -531,7 +540,7 @@ enum retro_hw_context_type hw_render_context_type(const char *s) return RETRO_HW_CONTEXT_DIRECT3D; #endif #ifdef HAVE_D3D11 - if (string_is_equal(s, "d3d9")) + if (string_is_equal(s, "d3d9_hlsl")) return RETRO_HW_CONTEXT_DIRECT3D; #endif return RETRO_HW_CONTEXT_NONE; @@ -3134,7 +3143,7 @@ enum gfx_ctx_api video_context_driver_get_api(void) : NULL; if (string_starts_with_size(video_ident, "d3d", STRLEN_CONST("d3d"))) { - if (string_is_equal(video_ident, "d3d9")) + if (string_is_equal(video_ident, "d3d9_hlsl")) return GFX_CTX_DIRECT3D9_API; else if (string_is_equal(video_ident, "d3d10")) return GFX_CTX_DIRECT3D10_API; diff --git a/gfx/video_driver.h b/gfx/video_driver.h index b3dd7d977a..18ca168362 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -1439,7 +1439,8 @@ extern video_driver_t video_ctr; extern video_driver_t video_gcm; extern video_driver_t video_switch; extern video_driver_t video_d3d8; -extern video_driver_t video_d3d9; +extern video_driver_t video_d3d9_cg; +extern video_driver_t video_d3d9_hlsl; extern video_driver_t video_d3d10; extern video_driver_t video_d3d11; extern video_driver_t video_d3d12; diff --git a/griffin/griffin.c b/griffin/griffin.c index 65739fd383..f964fcebce 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -419,15 +419,17 @@ VIDEO DRIVER #endif #if defined(HAVE_D3D9) -#include "../gfx/drivers/d3d9.c" #include "../gfx/common/d3d9_common.c" -#include "../gfx/drivers_display/gfx_display_d3d9.c" #ifdef HAVE_HLSL +#include "../gfx/drivers/d3d9hlsl.c" +#include "../gfx/drivers_display/gfx_display_d3d9hlsl.c" #include "../gfx/drivers_renderchain/d3d9_hlsl_renderchain.c" #endif #ifdef HAVE_CG +#include "../gfx/drivers/d3d9cg.c" +#include "../gfx/drivers_display/gfx_display_d3d9cg.c" #include "../gfx/drivers_renderchain/d3d9_cg_renderchain.c" #endif