From 9a354982a900950c062f388b7d2ce749f20703d3 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 19 Apr 2022 10:32:15 +0200 Subject: [PATCH] Move common D3D9 common out to file d3d9_common.c --- gfx/common/d3d9_common.c | 1104 ++++++++++++++++++++++++++++++++ gfx/common/d3d9_common.h | 86 +++ gfx/drivers/d3d9.c | 1304 +++----------------------------------- 3 files changed, 1280 insertions(+), 1214 deletions(-) diff --git a/gfx/common/d3d9_common.c b/gfx/common/d3d9_common.c index 0dfd47b66c..e1a0a6708d 100644 --- a/gfx/common/d3d9_common.c +++ b/gfx/common/d3d9_common.c @@ -29,6 +29,11 @@ #ifdef HAVE_DYNAMIC_D3D #include #endif +#include + +#ifdef HAVE_THREADS +#include "../video_thread_wrapper.h" +#endif #include "../../verbosity.h" @@ -43,6 +48,10 @@ #include #endif +#include "win32_common.h" + +#define FS_PRESENTINTERVAL(pp) ((pp)->PresentationInterval) + /* TODO/FIXME - static globals */ static UINT d3d9_SDKVersion = 0; #ifdef HAVE_DYNAMIC_D3D @@ -625,3 +634,1098 @@ const bool d3d9x_constant_table_set_float(void *p, #endif return false; } + +#ifdef _XBOX +static bool d3d9_is_windowed_enable(bool info_fullscreen) +{ + return false; +} + +static D3DFORMAT d3d9_get_color_format_backbuffer(bool rgb32, bool windowed) +{ + if (rgb32) + return D3DFMT_X8R8G8B8; + return d3d9_get_rgb565_format(); +} + +bool d3d9_has_windowed(void *data) { return false; } +#else +static bool d3d9_is_windowed_enable(bool info_fullscreen) +{ + settings_t *settings = config_get_ptr(); + if (!info_fullscreen) + return true; + if (settings) + return settings->bools.video_windowed_fullscreen; + return false; +} + +static D3DFORMAT d3d9_get_color_format_backbuffer(bool rgb32, bool windowed) +{ + if (windowed) + { + D3DDISPLAYMODE display_mode; + if (d3d9_get_adapter_display_mode(g_pD3D9, 0, &display_mode)) + return display_mode.Format; + } + return D3DFMT_X8R8G8B8; +} + +bool d3d9_has_windowed(void *data) { return true; } +#endif + +void d3d9_make_d3dpp(void *data, + const video_info_t *info, void *_d3dpp) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + D3DPRESENT_PARAMETERS *d3dpp = (D3DPRESENT_PARAMETERS*)_d3dpp; +#ifdef _XBOX + /* TODO/FIXME - get rid of global state dependencies. */ + global_t *global = global_get_ptr(); + int gamma_enable = global ? + global->console.screen.gamma_correction : 0; +#endif + bool windowed_enable = d3d9_is_windowed_enable(info->fullscreen); + + memset(d3dpp, 0, sizeof(*d3dpp)); + + d3dpp->Windowed = windowed_enable; + FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_IMMEDIATE; + + if (info->vsync) + { + settings_t *settings = config_get_ptr(); + unsigned video_swap_interval = settings->uints.video_swap_interval; + + switch (video_swap_interval) + { + default: + case 1: + FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_ONE; + break; + case 2: + FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_TWO; + break; + case 3: + FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_THREE; + break; + case 4: + FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_FOUR; + break; + } + } + + d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp->BackBufferCount = 2; + d3dpp->BackBufferFormat = d3d9_get_color_format_backbuffer( + info->rgb32, windowed_enable); + +#ifdef _XBOX + d3dpp->FrontBufferFormat = d3d9_get_color_format_front_buffer(); + + if (gamma_enable) + { + d3dpp->BackBufferFormat = (D3DFORMAT)MAKESRGBFMT( + d3dpp->BackBufferFormat); + d3dpp->FrontBufferFormat = (D3DFORMAT)MAKESRGBFMT( + d3dpp->FrontBufferFormat); + } +#else + d3dpp->hDeviceWindow = win32_get_window(); +#endif + + if (!windowed_enable) + { +#ifdef _XBOX + unsigned width = 0; + unsigned height = 0; + d3d9_get_video_size(d3d, &width, &height); + video_driver_set_size(width, height); +#endif + video_driver_get_size(&d3dpp->BackBufferWidth, + &d3dpp->BackBufferHeight); + } + +#ifdef _XBOX + d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE; + d3dpp->EnableAutoDepthStencil = FALSE; + if (!d3d->widescreen_mode) + d3dpp->Flags |= D3DPRESENTFLAG_NO_LETTERBOX; + d3dpp->MultiSampleQuality = 0; +#endif +} + +#ifdef _XBOX +static void d3d9_get_video_size(d3d9_video_t *d3d, + unsigned *width, unsigned *height) +{ + XVIDEO_MODE video_mode; + + XGetVideoMode(&video_mode); + + *width = video_mode.dwDisplayWidth; + *height = video_mode.dwDisplayHeight; + + d3d->resolution_hd_enable = false; + + if(video_mode.fIsHiDef) + { + *width = 1280; + *height = 720; + d3d->resolution_hd_enable = true; + } + else + { + *width = 640; + *height = 480; + } + + d3d->widescreen_mode = video_mode.fIsWideScreen; +} + +static D3DFORMAT d3d9_get_color_format_front_buffer(void) +{ + return D3DFMT_LE_X8R8G8B8; +} +#endif + +void d3d9_log_info(const struct LinkInfo *info) +{ + RARCH_LOG("[D3D9]: Render pass info:\n"); + RARCH_LOG("\tTexture width: %u\n", info->tex_w); + RARCH_LOG("\tTexture height: %u\n", info->tex_h); + + RARCH_LOG("\tScale type (X): "); + + switch (info->pass->fbo.type_x) + { + case RARCH_SCALE_INPUT: + RARCH_LOG("Relative @ %fx\n", info->pass->fbo.scale_x); + break; + + case RARCH_SCALE_VIEWPORT: + RARCH_LOG("Viewport @ %fx\n", info->pass->fbo.scale_x); + break; + + case RARCH_SCALE_ABSOLUTE: + RARCH_LOG("Absolute @ %u px\n", info->pass->fbo.abs_x); + break; + } + + RARCH_LOG("\tScale type (Y): "); + + switch (info->pass->fbo.type_y) + { + case RARCH_SCALE_INPUT: + RARCH_LOG("Relative @ %fx\n", info->pass->fbo.scale_y); + break; + + case RARCH_SCALE_VIEWPORT: + RARCH_LOG("Viewport @ %fx\n", info->pass->fbo.scale_y); + break; + + case RARCH_SCALE_ABSOLUTE: + RARCH_LOG("Absolute @ %u px\n", info->pass->fbo.abs_y); + break; + } + + RARCH_LOG("\tBilinear filter: %s\n", + info->pass->filter == RARCH_FILTER_LINEAR ? "true" : "false"); +} + +static bool d3d9_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 false; + + d3d->video_info.width = new_width; + d3d->video_info.height = new_height; + video_driver_set_size(new_width, new_height); + + return true; +} + +static bool d3d9_init_singlepass(d3d9_video_t *d3d) +{ + struct video_shader_pass *pass = NULL; + + if (!d3d) + return false; + + memset(&d3d->shader, 0, sizeof(d3d->shader)); + d3d->shader.passes = 1; + + pass = (struct video_shader_pass*) + &d3d->shader.pass[0]; + + pass->fbo.valid = true; + pass->fbo.scale_y = 1.0; + pass->fbo.type_y = RARCH_SCALE_VIEWPORT; + pass->fbo.scale_x = pass->fbo.scale_y; + pass->fbo.type_x = pass->fbo.type_y; + + if (!string_is_empty(d3d->shader_path)) + strlcpy(pass->source.path, d3d->shader_path, + sizeof(pass->source.path)); + + return true; +} + +static bool d3d9_init_multipass(d3d9_video_t *d3d, const char *shader_path) +{ + unsigned i; + bool use_extra_pass = false; + struct video_shader_pass *pass = NULL; + + memset(&d3d->shader, 0, sizeof(d3d->shader)); + + if (!video_shader_load_preset_into_shader(shader_path, &d3d->shader)) + return false; + + RARCH_LOG("[D3D9]: Found %u shaders.\n", d3d->shader.passes); + + for (i = 0; i < d3d->shader.passes; i++) + { + if (d3d->shader.pass[i].fbo.valid) + continue; + + d3d->shader.pass[i].fbo.scale_y = 1.0f; + d3d->shader.pass[i].fbo.scale_x = 1.0f; + d3d->shader.pass[i].fbo.type_x = RARCH_SCALE_INPUT; + d3d->shader.pass[i].fbo.type_y = RARCH_SCALE_INPUT; + } + + use_extra_pass = d3d->shader.passes < GFX_MAX_SHADERS && + d3d->shader.pass[d3d->shader.passes - 1].fbo.valid; + + if (use_extra_pass) + { + d3d->shader.passes++; + pass = (struct video_shader_pass*) + &d3d->shader.pass[d3d->shader.passes - 1]; + + pass->fbo.scale_x = 1.0f; + pass->fbo.scale_y = 1.0f; + pass->fbo.type_x = RARCH_SCALE_VIEWPORT; + pass->fbo.type_y = RARCH_SCALE_VIEWPORT; + pass->filter = RARCH_FILTER_UNSPEC; + } + else + { + pass = (struct video_shader_pass*) + &d3d->shader.pass[d3d->shader.passes - 1]; + + pass->fbo.scale_x = 1.0f; + pass->fbo.scale_y = 1.0f; + pass->fbo.type_x = RARCH_SCALE_VIEWPORT; + pass->fbo.type_y = RARCH_SCALE_VIEWPORT; + } + + return true; +} + +bool d3d9_process_shader(d3d9_video_t *d3d) +{ + const char *shader_path = d3d->shader_path; + if (d3d && !string_is_empty(shader_path)) + { + RARCH_ERR("[D3D9]: Failed to parse shader preset.\n"); + return d3d9_init_multipass(d3d, shader_path); + } + + return d3d9_init_singlepass(d3d); +} + +void d3d9_viewport_info(void *data, struct video_viewport *vp) +{ + unsigned width, height; + d3d9_video_t *d3d = (d3d9_video_t*)data; + + video_driver_get_size(&width, &height); + + vp->x = d3d->final_viewport.X; + vp->y = d3d->final_viewport.Y; + vp->width = d3d->final_viewport.Width; + vp->height = d3d->final_viewport.Height; + + vp->full_width = width; + vp->full_height = height; +} + +#if defined(HAVE_MENU) || defined(HAVE_OVERLAY) +void d3d9_overlay_render(d3d9_video_t *d3d, + unsigned width, + unsigned height, + overlay_t *overlay, bool force_linear) +{ + D3DTEXTUREFILTERTYPE filter_type; + LPDIRECT3DVERTEXDECLARATION9 vertex_decl; + LPDIRECT3DDEVICE9 dev; + struct video_viewport vp; + void *verts; + unsigned i; + Vertex vert[4]; + D3DVERTEXELEMENT9 vElems[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 (!d3d || !overlay || !overlay->tex) + return; + + dev = d3d->dev; + + if (!overlay->vert_buf) + { + overlay->vert_buf = d3d9_vertex_buffer_new( + dev, sizeof(vert), D3DUSAGE_WRITEONLY, +#ifdef _XBOX + 0, +#else + D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, +#endif + D3DPOOL_MANAGED, NULL); + + if (!overlay->vert_buf) + return; + } + + for (i = 0; i < 4; i++) + { + vert[i].z = 0.5f; + vert[i].color = (((uint32_t)(overlay->alpha_mod * 0xFF)) << 24) | 0xFFFFFF; + } + + d3d9_viewport_info(d3d, &vp); + + vert[0].x = overlay->vert_coords[0]; + vert[1].x = overlay->vert_coords[0] + overlay->vert_coords[2]; + vert[2].x = overlay->vert_coords[0]; + vert[3].x = overlay->vert_coords[0] + overlay->vert_coords[2]; + vert[0].y = overlay->vert_coords[1]; + vert[1].y = overlay->vert_coords[1]; + vert[2].y = overlay->vert_coords[1] + overlay->vert_coords[3]; + vert[3].y = overlay->vert_coords[1] + overlay->vert_coords[3]; + + vert[0].u = overlay->tex_coords[0]; + vert[1].u = overlay->tex_coords[0] + overlay->tex_coords[2]; + vert[2].u = overlay->tex_coords[0]; + vert[3].u = overlay->tex_coords[0] + overlay->tex_coords[2]; + vert[0].v = overlay->tex_coords[1]; + vert[1].v = overlay->tex_coords[1]; + vert[2].v = overlay->tex_coords[1] + overlay->tex_coords[3]; + vert[3].v = overlay->tex_coords[1] + overlay->tex_coords[3]; + + verts = d3d9_vertex_buffer_lock((LPDIRECT3DVERTEXBUFFER9)overlay->vert_buf); + memcpy(verts, vert, sizeof(vert)); + d3d9_vertex_buffer_unlock((LPDIRECT3DVERTEXBUFFER9)overlay->vert_buf); + + d3d9_enable_blend_func(d3d->dev); + + /* set vertex declaration for overlay. */ + d3d9_vertex_declaration_new(dev, &vElems, (void**)&vertex_decl); + d3d9_set_vertex_declaration(dev, vertex_decl); + d3d9_vertex_declaration_free(vertex_decl); + + d3d9_set_stream_source(dev, 0, (LPDIRECT3DVERTEXBUFFER9)overlay->vert_buf, + 0, sizeof(*vert)); + + if (overlay->fullscreen) + { + D3DVIEWPORT9 vp_full; + + vp_full.X = 0; + vp_full.Y = 0; + vp_full.Width = width; + vp_full.Height = height; + vp_full.MinZ = 0.0f; + vp_full.MaxZ = 1.0f; + d3d9_set_viewports(dev, &vp_full); + } + + filter_type = D3DTEXF_LINEAR; + + if (!force_linear) + { + settings_t *settings = config_get_ptr(); + bool menu_linear_filter = settings->bools.menu_linear_filter; + if (!menu_linear_filter) + filter_type = D3DTEXF_POINT; + } + + /* Render overlay. */ + d3d9_set_texture(dev, 0, (LPDIRECT3DTEXTURE9)overlay->tex); + d3d9_set_sampler_address_u(dev, 0, D3DTADDRESS_BORDER); + d3d9_set_sampler_address_v(dev, 0, D3DTADDRESS_BORDER); + d3d9_set_sampler_minfilter(dev, 0, filter_type); + d3d9_set_sampler_magfilter(dev, 0, filter_type); + d3d9_draw_primitive(dev, D3DPT_TRIANGLESTRIP, 0, 2); + + /* Restore previous state. */ + d3d9_disable_blend_func(dev); + d3d9_set_viewports(dev, &d3d->final_viewport); +} + +void d3d9_free_overlay(d3d9_video_t *d3d, overlay_t *overlay) +{ + d3d9_texture_free((LPDIRECT3DTEXTURE9)overlay->tex); + d3d9_vertex_buffer_free(overlay->vert_buf, NULL); +} +#endif + +void d3d9_set_nonblock_state(void *data, bool state, + bool adaptive_vsync_enabled, + unsigned swap_interval) +{ +#ifdef _XBOX + int interval = 0; +#endif + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + +#ifdef _XBOX + if (!state) + interval = 1; +#endif + + d3d->video_info.vsync = !state; + +#ifdef _XBOX + d3d9_set_render_state(d3d->dev, + D3DRS_PRESENTINTERVAL, + interval ? + D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE + ); +#else + d3d->needs_restore = true; + d3d9_restore(d3d); +#endif +} + +bool d3d9_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_set_resize(d3d, temp_width, temp_height); + d3d9_restore(d3d); + } + + ret = !quit; + + if ( temp_width != 0 && + temp_height != 0) + video_driver_set_size(temp_width, temp_height); + + return ret; +} + +bool d3d9_suppress_screensaver(void *data, bool enable) +{ +#ifdef _XBOX + return true; +#else + return win32_suppress_screensaver(data, enable); +#endif +} + +void d3d9_set_aspect_ratio(void *data, unsigned aspect_ratio_idx) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + + d3d->keep_aspect = true; + d3d->should_resize = true; +} + +void d3d9_apply_state_changes(void *data) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + if (d3d) + d3d->should_resize = true; +} + +void d3d9_set_osd_msg(void *data, + const char *msg, + const void *params, void *font) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + LPDIRECT3DDEVICE9 dev = d3d->dev; + const struct font_params *d3d_font_params = (const + struct font_params*)params; + + d3d9_set_font_rect(d3d, d3d_font_params); + d3d9_begin_scene(dev); + font_driver_render_msg(d3d, + msg, d3d_font_params, font); + d3d9_end_scene(dev); +} + +void d3d9_set_menu_texture_frame(void *data, + const void *frame, bool rgb32, unsigned width, unsigned height, + float alpha) +{ + D3DLOCKED_RECT d3dlr; + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d || !d3d->menu) + return; + + if ( !d3d->menu->tex || + d3d->menu->tex_w != width || + d3d->menu->tex_h != height) + { + d3d9_texture_free((LPDIRECT3DTEXTURE9)d3d->menu->tex); + + d3d->menu->tex = d3d9_texture_new(d3d->dev, NULL, + width, height, 1, + 0, d3d9_get_argb8888_format(), + D3DPOOL_MANAGED, 0, 0, 0, NULL, NULL, false); + + if (!d3d->menu->tex) + { + RARCH_ERR("[D3D9]: Failed to create menu texture.\n"); + return; + } + + d3d->menu->tex_w = width; + d3d->menu->tex_h = height; + } + + d3d->menu->alpha_mod = alpha; + + if (d3d9_lock_rectangle((LPDIRECT3DTEXTURE9)d3d->menu->tex, 0, &d3dlr, + NULL, 0, D3DLOCK_NOSYSLOCK)) + { + unsigned h, w; + if (rgb32) + { + uint8_t *dst = (uint8_t*)d3dlr.pBits; + const uint32_t *src = (const uint32_t*)frame; + + for (h = 0; h < height; h++, dst += d3dlr.Pitch, src += width) + { + memcpy(dst, src, width * sizeof(uint32_t)); + memset(dst + width * sizeof(uint32_t), 0, + d3dlr.Pitch - width * sizeof(uint32_t)); + } + } + else + { + uint32_t *dst = (uint32_t*)d3dlr.pBits; + const uint16_t *src = (const uint16_t*)frame; + + for (h = 0; h < height; h++, dst += d3dlr.Pitch >> 2, src += width) + { + for (w = 0; w < width; w++) + { + uint16_t c = src[w]; + uint32_t r = (c >> 12) & 0xf; + uint32_t g = (c >> 8) & 0xf; + uint32_t b = (c >> 4) & 0xf; + uint32_t a = (c >> 0) & 0xf; + r = ((r << 4) | r) << 16; + g = ((g << 4) | g) << 8; + b = ((b << 4) | b) << 0; + a = ((a << 4) | a) << 24; + dst[w] = r | g | b | a; + } + } + } + + if (d3d->menu) + d3d9_unlock_rectangle((LPDIRECT3DTEXTURE9)d3d->menu->tex); + } +} + +void d3d9_set_menu_texture_enable(void *data, + bool state, bool full_screen) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d || !d3d->menu) + return; + + d3d->menu->enabled = state; + d3d->menu->fullscreen = full_screen; +} + +struct d3d9_texture_info +{ + void *userdata; + void *data; + enum texture_filter_type type; +}; + +static void d3d9_video_texture_load_d3d( + struct d3d9_texture_info *info, + uintptr_t *id) +{ + D3DLOCKED_RECT d3dlr; + LPDIRECT3DTEXTURE9 tex = NULL; + unsigned usage = 0; + bool want_mipmap = false; + d3d9_video_t *d3d = (d3d9_video_t*)info->userdata; + struct texture_image *ti = (struct texture_image*)info->data; + + if (!ti) + return; + + if((info->type == TEXTURE_FILTER_MIPMAP_LINEAR) || + (info->type == TEXTURE_FILTER_MIPMAP_NEAREST)) + want_mipmap = true; + + tex = (LPDIRECT3DTEXTURE9)d3d9_texture_new(d3d->dev, NULL, + ti->width, ti->height, 0, + usage, d3d9_get_argb8888_format(), + D3DPOOL_MANAGED, 0, 0, 0, + NULL, NULL, want_mipmap); + + if (!tex) + { + RARCH_ERR("[D3D9]: Failed to create texture\n"); + return; + } + + if (d3d9_lock_rectangle(tex, 0, &d3dlr, + NULL, 0, D3DLOCK_NOSYSLOCK)) + { + unsigned i; + uint32_t *dst = (uint32_t*)(d3dlr.pBits); + const uint32_t *src = ti->pixels; + unsigned pitch = d3dlr.Pitch >> 2; + + for (i = 0; i < ti->height; i++, dst += pitch, src += ti->width) + memcpy(dst, src, ti->width << 2); + d3d9_unlock_rectangle(tex); + } + + *id = (uintptr_t)tex; +} + +#ifdef HAVE_THREADS +static int d3d9_video_texture_load_wrap_d3d(void *data) +{ + uintptr_t id = 0; + struct d3d9_texture_info *info = (struct d3d9_texture_info*)data; + if (!info) + return 0; + d3d9_video_texture_load_d3d(info, &id); + return id; +} +#endif + +uintptr_t d3d9_load_texture(void *video_data, void *data, + bool threaded, enum texture_filter_type filter_type) +{ + uintptr_t id = 0; + struct d3d9_texture_info info; + + info.userdata = video_data; + info.data = data; + info.type = filter_type; + +#ifdef HAVE_THREADS + if (threaded) + return video_thread_texture_load(&info, + d3d9_video_texture_load_wrap_d3d); +#endif + + d3d9_video_texture_load_d3d(&info, &id); + return id; +} + +void d3d9_unload_texture(void *data, + bool threaded, uintptr_t id) +{ + LPDIRECT3DTEXTURE9 texid; + if (!id) + return; + + texid = (LPDIRECT3DTEXTURE9)id; + d3d9_texture_free(texid); +} + +void d3d9_set_video_mode(void *data, + unsigned width, unsigned height, + bool fullscreen) +{ +#ifndef _XBOX + win32_show_cursor(data, !fullscreen); +#endif +} + +bool d3d9_read_viewport(void *data, uint8_t *buffer, bool is_idle) +{ + unsigned width, height; + D3DLOCKED_RECT rect; + LPDIRECT3DSURFACE9 target = NULL; + LPDIRECT3DSURFACE9 dest = NULL; + bool ret = true; + d3d9_video_t *d3d = (d3d9_video_t*)data; + LPDIRECT3DDEVICE9 d3dr = d3d->dev; + + video_driver_get_size(&width, &height); + + if ( + !d3d9_device_get_render_target(d3dr, 0, (void**)&target) || + !d3d9_device_create_offscreen_plain_surface(d3dr, width, height, + d3d9_get_xrgb8888_format(), + D3DPOOL_SYSTEMMEM, (void**)&dest, NULL) || + !d3d9_device_get_render_target_data(d3dr, target, dest) + ) + { + ret = false; + goto end; + } + + if (d3d9_surface_lock_rect(dest, &rect)) + { + unsigned x, y; + unsigned pitchpix = rect.Pitch / 4; + const uint32_t *pixels = (const uint32_t*)rect.pBits; + + pixels += d3d->final_viewport.X; + pixels += (d3d->final_viewport.Height - 1) * pitchpix; + pixels -= d3d->final_viewport.Y * pitchpix; + + for (y = 0; y < d3d->final_viewport.Height; y++, pixels -= pitchpix) + { + for (x = 0; x < d3d->final_viewport.Width; x++) + { + *buffer++ = (pixels[x] >> 0) & 0xff; + *buffer++ = (pixels[x] >> 8) & 0xff; + *buffer++ = (pixels[x] >> 16) & 0xff; + } + } + + d3d9_surface_unlock_rect(dest); + } + else + ret = false; + +end: + if (target) + d3d9_surface_free(target); + if (dest) + d3d9_surface_free(dest); + return ret; +} + +void d3d9_calculate_rect(void *data, + unsigned *width, unsigned *height, + int *x, int *y, + bool force_full, + bool allow_rotate) +{ + float device_aspect = (float)*width / *height; + d3d9_video_t *d3d = (d3d9_video_t*)data; + settings_t *settings = config_get_ptr(); + bool scale_integer = settings->bools.video_scale_integer; + + video_driver_get_size(width, height); + + *x = 0; + *y = 0; + + if (scale_integer && !force_full) + { + struct video_viewport vp; + + vp.x = 0; + vp.y = 0; + vp.width = 0; + vp.height = 0; + vp.full_width = 0; + vp.full_height = 0; + + video_viewport_get_scaled_integer(&vp, + *width, + *height, + video_driver_get_aspect_ratio(), + d3d->keep_aspect); + + *x = vp.x; + *y = vp.y; + *width = vp.width; + *height = vp.height; + } + else if (d3d->keep_aspect && !force_full) + { + float desired_aspect = video_driver_get_aspect_ratio(); + +#if defined(HAVE_MENU) + if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM) + { + video_viewport_t *custom = video_viewport_get_custom(); + + *x = custom->x; + *y = custom->y; + *width = custom->width; + *height = custom->height; + } + else +#endif + { + float delta; + + if (fabsf(device_aspect - desired_aspect) < 0.0001f) + { + /* If the aspect ratios of screen and desired aspect + * ratio are sufficiently equal (floating point stuff), + * assume they are actually equal. + */ + } + else if (device_aspect > desired_aspect) + { + delta = (desired_aspect / device_aspect - 1.0f) / 2.0f + 0.5f; + *x = (int)(roundf(*width * (0.5f - delta))); + *width = (unsigned)(roundf(2.0f * (*width) * delta)); + } + else + { + delta = (device_aspect / desired_aspect - 1.0f) / 2.0f + 0.5f; + *y = (int)(roundf(*height * (0.5f - delta))); + *height = (unsigned)(roundf(2.0f * (*height) * delta)); + } + } + } +} + +void d3d9_set_font_rect( + d3d9_video_t *d3d, + const struct font_params *params) +{ + settings_t *settings = config_get_ptr(); + float pos_x = settings->floats.video_msg_pos_x; + float pos_y = settings->floats.video_msg_pos_y; + float font_size = settings->floats.video_font_size; + + if (params) + { + pos_x = params->x; + pos_y = params->y; + font_size *= params->scale; + } + + if (!d3d) + return; + + d3d->font_rect.left = d3d->video_info.width * pos_x; + d3d->font_rect.right = d3d->video_info.width; + d3d->font_rect.top = (1.0f - pos_y) * d3d->video_info.height - font_size; + d3d->font_rect.bottom = d3d->video_info.height; + + d3d->font_rect_shifted = d3d->font_rect; + d3d->font_rect_shifted.left -= 2; + d3d->font_rect_shifted.right -= 2; + d3d->font_rect_shifted.top += 2; + d3d->font_rect_shifted.bottom += 2; +} + +void d3d9_set_rotation(void *data, unsigned rot) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + struct video_ortho ortho = {0, 1, 0, 1, -1, 1}; + + if (!d3d) + return; + + d3d->dev_rotation = rot; +} + +#ifdef HAVE_OVERLAY +void d3d9_free_overlays(d3d9_video_t *d3d) +{ + unsigned i; + + for (i = 0; i < d3d->overlays_size; i++) + d3d9_free_overlay(d3d, &d3d->overlays[i]); + free(d3d->overlays); + d3d->overlays = NULL; + d3d->overlays_size = 0; +} + +static void d3d9_overlay_tex_geom( + void *data, + unsigned index, + float x, float y, + float w, float h) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + + d3d->overlays[index].tex_coords[0] = x; + d3d->overlays[index].tex_coords[1] = y; + d3d->overlays[index].tex_coords[2] = w; + d3d->overlays[index].tex_coords[3] = h; +} + +static void d3d9_overlay_vertex_geom( + void *data, + unsigned index, + float x, float y, + float w, float h) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + + y = 1.0f - y; + h = -h; + d3d->overlays[index].vert_coords[0] = x; + d3d->overlays[index].vert_coords[1] = y; + d3d->overlays[index].vert_coords[2] = w; + d3d->overlays[index].vert_coords[3] = h; +} + +static bool d3d9_overlay_load(void *data, + const void *image_data, unsigned num_images) +{ + unsigned i, y; + overlay_t *new_overlays = NULL; + d3d9_video_t *d3d = (d3d9_video_t*)data; + const struct texture_image *images = (const struct texture_image*) + image_data; + + if (!d3d) + return false; + + d3d9_free_overlays(d3d); + d3d->overlays = (overlay_t*)calloc(num_images, sizeof(*d3d->overlays)); + d3d->overlays_size = num_images; + + for (i = 0; i < num_images; i++) + { + D3DLOCKED_RECT d3dlr; + unsigned width = images[i].width; + unsigned height = images[i].height; + overlay_t *overlay = (overlay_t*)&d3d->overlays[i]; + + overlay->tex = d3d9_texture_new(d3d->dev, NULL, + width, height, 1, + 0, + d3d9_get_argb8888_format(), + D3DPOOL_MANAGED, 0, 0, 0, + NULL, NULL, false); + + if (!overlay->tex) + { + RARCH_ERR("[D3D9]: Failed to create overlay texture\n"); + return false; + } + + if (d3d9_lock_rectangle((LPDIRECT3DTEXTURE9)overlay->tex, 0, &d3dlr, + NULL, 0, D3DLOCK_NOSYSLOCK)) + { + uint32_t *dst = (uint32_t*)(d3dlr.pBits); + const uint32_t *src = images[i].pixels; + unsigned pitch = d3dlr.Pitch >> 2; + + for (y = 0; y < height; y++, dst += pitch, src += width) + memcpy(dst, src, width << 2); + d3d9_unlock_rectangle((LPDIRECT3DTEXTURE9)overlay->tex); + } + + overlay->tex_w = width; + overlay->tex_h = height; + + /* Default. Stretch to whole screen. */ + d3d9_overlay_tex_geom(d3d, i, 0, 0, 1, 1); + d3d9_overlay_vertex_geom(d3d, i, 0, 0, 1, 1); + } + + return true; +} + +static void d3d9_overlay_enable(void *data, bool state) +{ + unsigned i; + d3d9_video_t *d3d = (d3d9_video_t*)data; + + if (!d3d) + return; + + for (i = 0; i < d3d->overlays_size; i++) + d3d->overlays_enabled = state; + +#ifndef XBOX + win32_show_cursor(d3d, state); +#endif +} + +static void d3d9_overlay_full_screen(void *data, bool enable) +{ + unsigned i; + d3d9_video_t *d3d = (d3d9_video_t*)data; + + for (i = 0; i < d3d->overlays_size; i++) + d3d->overlays[i].fullscreen = enable; +} + +static void d3d9_overlay_set_alpha(void *data, unsigned index, float mod) +{ + d3d9_video_t *d3d = (d3d9_video_t*)data; + if (d3d) + d3d->overlays[index].alpha_mod = mod; +} + +static const video_overlay_interface_t d3d9_overlay_interface = { + d3d9_overlay_enable, + d3d9_overlay_load, + d3d9_overlay_tex_geom, + d3d9_overlay_vertex_geom, + d3d9_overlay_full_screen, + d3d9_overlay_set_alpha, +}; + +void d3d9_get_overlay_interface(void *data, + const video_overlay_interface_t **iface) +{ + (void)data; + *iface = &d3d9_overlay_interface; +} +#endif + +void d3d9_get_poke_interface(void *data, + const video_poke_interface_t **iface) +{ + *iface = &d3d9_poke_interface; +} + +#ifdef HAVE_GFX_WIDGETS +bool d3d9_gfx_widgets_enabled(void *data) +{ + return false; /* currently disabled due to memory issues */ +} +#endif diff --git a/gfx/common/d3d9_common.h b/gfx/common/d3d9_common.h index f2473b253e..5622e6bc6d 100644 --- a/gfx/common/d3d9_common.h +++ b/gfx/common/d3d9_common.h @@ -811,6 +811,92 @@ static INLINE void d3d9_convert_geometry( } } +void d3d9_make_d3dpp(void *data, + const video_info_t *info, void *_d3dpp); + +void d3d9_calculate_rect(void *data, + unsigned *width, unsigned *height, + int *x, int *y, + bool force_full, + bool allow_rotate); + +void d3d9_set_font_rect( + d3d9_video_t *d3d, + const struct font_params *params); + +void d3d9_log_info(const struct LinkInfo *info); + +#ifdef HAVE_OVERLAY +void d3d9_free_overlays(d3d9_video_t *d3d); +#endif + +#if defined(HAVE_MENU) || defined(HAVE_OVERLAY) +void d3d9_free_overlay(d3d9_video_t *d3d, overlay_t *overlay); + +void d3d9_overlay_render(d3d9_video_t *d3d, + unsigned width, + unsigned height, + overlay_t *overlay, bool force_linear); +#endif + +#if defined(HAVE_OVERLAY) +void d3d9_get_overlay_interface(void *data, + const video_overlay_interface_t **iface); +#endif + +void d3d9_get_poke_interface(void *data, + const video_poke_interface_t **iface); + +void d3d9_set_nonblock_state(void *data, bool state, + bool adaptive_vsync_enabled, + unsigned swap_interval); + +bool d3d9_alive(void *data); + +void d3d9_set_rotation(void *data, unsigned rot); + +void d3d9_viewport_info(void *data, struct video_viewport *vp); + +bool d3d9_read_viewport(void *data, uint8_t *buffer, bool is_idle); + +bool d3d9_has_windowed(void *data); + +bool d3d9_suppress_screensaver(void *data, bool enable); + +bool d3d9_process_shader(d3d9_video_t *d3d); + +bool d3d9_gfx_widgets_enabled(void *data); + +uintptr_t d3d9_load_texture(void *video_data, void *data, + bool threaded, enum texture_filter_type filter_type); + +void d3d9_set_osd_msg(void *data, + const char *msg, + const void *params, void *font); + +void d3d9_unload_texture(void *data, + bool threaded, uintptr_t id); + +void d3d9_set_video_mode(void *data, + unsigned width, unsigned height, + bool fullscreen); + +void d3d9_set_aspect_ratio(void *data, unsigned aspect_ratio_idx); + +void d3d9_apply_state_changes(void *data); + +void d3d9_set_menu_texture_frame(void *data, + const void *frame, bool rgb32, unsigned width, unsigned height, + float alpha); + +void d3d9_set_menu_texture_enable(void *data, + bool state, bool full_screen); + +bool d3d9_restore(d3d9_video_t *d3d); + +extern LPDIRECT3D9 g_pD3D9; +extern const video_poke_interface_t d3d9_poke_interface; + RETRO_END_DECLS #endif diff --git a/gfx/drivers/d3d9.c b/gfx/drivers/d3d9.c index a61d1106b9..0ae0f74cb7 100644 --- a/gfx/drivers/d3d9.c +++ b/gfx/drivers/d3d9.c @@ -57,12 +57,6 @@ #include "../common/win32_common.h" -#ifdef _XBOX -#define D3D9_PRESENTATIONINTERVAL D3DRS_PRESENTINTERVAL -#endif - -#define FS_PRESENTINTERVAL(pp) ((pp)->PresentationInterval) - #ifdef HAVE_MENU #include "../../menu/menu_driver.h" #endif @@ -82,34 +76,88 @@ /* Temporary workaround for d3d9 not being able to poll flags during init */ static gfx_ctx_driver_t d3d9_fake_context; -static uint32_t d3d9_get_flags(void *data); -static bool d3d9_set_shader(void *data, - enum rarch_shader_type type, const char *path); -static LPDIRECT3D9 g_pD3D9; +LPDIRECT3D9 g_pD3D9; static enum rarch_shader_type supported_shader_type = RARCH_SHADER_NONE; -void *dinput; - -static bool d3d9_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 false; - - RARCH_LOG("[D3D9]: Resize %ux%u.\n", new_width, new_height); - d3d->video_info.width = new_width; - d3d->video_info.height = new_height; - video_driver_set_size(new_width, new_height); - - return true; -} - extern d3d9_renderchain_driver_t cg_d3d9_renderchain; extern d3d9_renderchain_driver_t hlsl_d3d9_renderchain; +static uint32_t d3d9_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); + + return flags; +} + +static bool d3d9_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) + 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 (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); + + 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_restore(d3d)) + { + RARCH_ERR("[D3D9]: Failed to set shader.\n"); + return false; + } + + return true; +#else + return false; +#endif +} + + +static void d3d9_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 bool renderchain_d3d_init_first( enum gfx_ctx_api api, const d3d9_renderchain_driver_t **renderchain_driver, @@ -158,49 +206,6 @@ static bool renderchain_d3d_init_first( return false; } -static void d3d9_log_info(const struct LinkInfo *info) -{ - RARCH_LOG("[D3D9]: Render pass info:\n"); - RARCH_LOG("\tTexture width: %u\n", info->tex_w); - RARCH_LOG("\tTexture height: %u\n", info->tex_h); - - RARCH_LOG("\tScale type (X): "); - - switch (info->pass->fbo.type_x) - { - case RARCH_SCALE_INPUT: - RARCH_LOG("Relative @ %fx\n", info->pass->fbo.scale_x); - break; - - case RARCH_SCALE_VIEWPORT: - RARCH_LOG("Viewport @ %fx\n", info->pass->fbo.scale_x); - break; - - case RARCH_SCALE_ABSOLUTE: - RARCH_LOG("Absolute @ %u px\n", info->pass->fbo.abs_x); - break; - } - - RARCH_LOG("\tScale type (Y): "); - - switch (info->pass->fbo.type_y) - { - case RARCH_SCALE_INPUT: - RARCH_LOG("Relative @ %fx\n", info->pass->fbo.scale_y); - break; - - case RARCH_SCALE_VIEWPORT: - RARCH_LOG("Viewport @ %fx\n", info->pass->fbo.scale_y); - break; - - case RARCH_SCALE_ABSOLUTE: - RARCH_LOG("Absolute @ %u px\n", info->pass->fbo.abs_y); - break; - } - - RARCH_LOG("\tBilinear filter: %s\n", - info->pass->filter == RARCH_FILTER_LINEAR ? "true" : "false"); -} static bool d3d9_init_chain(d3d9_video_t *d3d, unsigned input_scale, @@ -300,257 +305,6 @@ static bool d3d9_init_chain(d3d9_video_t *d3d, return true; } -static bool d3d9_init_singlepass(d3d9_video_t *d3d) -{ - struct video_shader_pass *pass = NULL; - - if (!d3d) - return false; - - memset(&d3d->shader, 0, sizeof(d3d->shader)); - d3d->shader.passes = 1; - - pass = (struct video_shader_pass*) - &d3d->shader.pass[0]; - - pass->fbo.valid = true; - pass->fbo.scale_y = 1.0; - pass->fbo.type_y = RARCH_SCALE_VIEWPORT; - pass->fbo.scale_x = pass->fbo.scale_y; - pass->fbo.type_x = pass->fbo.type_y; - - if (!string_is_empty(d3d->shader_path)) - strlcpy(pass->source.path, d3d->shader_path, - sizeof(pass->source.path)); - - return true; -} - -static bool d3d9_init_multipass(d3d9_video_t *d3d, const char *shader_path) -{ - unsigned i; - bool use_extra_pass = false; - struct video_shader_pass *pass = NULL; - - memset(&d3d->shader, 0, sizeof(d3d->shader)); - - if (!video_shader_load_preset_into_shader(shader_path, &d3d->shader)) - { - RARCH_ERR("[D3D9]: Failed to parse shader preset.\n"); - return false; - } - - RARCH_LOG("[D3D9]: Found %u shaders.\n", d3d->shader.passes); - - for (i = 0; i < d3d->shader.passes; i++) - { - if (d3d->shader.pass[i].fbo.valid) - continue; - - d3d->shader.pass[i].fbo.scale_y = 1.0f; - d3d->shader.pass[i].fbo.scale_x = 1.0f; - d3d->shader.pass[i].fbo.type_x = RARCH_SCALE_INPUT; - d3d->shader.pass[i].fbo.type_y = RARCH_SCALE_INPUT; - } - - use_extra_pass = d3d->shader.passes < GFX_MAX_SHADERS && - d3d->shader.pass[d3d->shader.passes - 1].fbo.valid; - - if (use_extra_pass) - { - d3d->shader.passes++; - pass = (struct video_shader_pass*) - &d3d->shader.pass[d3d->shader.passes - 1]; - - pass->fbo.scale_x = 1.0f; - pass->fbo.scale_y = 1.0f; - pass->fbo.type_x = RARCH_SCALE_VIEWPORT; - pass->fbo.type_y = RARCH_SCALE_VIEWPORT; - pass->filter = RARCH_FILTER_UNSPEC; - } - else - { - pass = (struct video_shader_pass*) - &d3d->shader.pass[d3d->shader.passes - 1]; - - pass->fbo.scale_x = 1.0f; - pass->fbo.scale_y = 1.0f; - pass->fbo.type_x = RARCH_SCALE_VIEWPORT; - pass->fbo.type_y = RARCH_SCALE_VIEWPORT; - } - - return true; -} - -static bool d3d9_process_shader(d3d9_video_t *d3d) -{ - const char *shader_path = d3d->shader_path; - if (d3d && !string_is_empty(shader_path)) - return d3d9_init_multipass(d3d, shader_path); - - return d3d9_init_singlepass(d3d); -} - -static void d3d9_viewport_info(void *data, struct video_viewport *vp) -{ - unsigned width, height; - d3d9_video_t *d3d = (d3d9_video_t*)data; - - if (!vp) - return; - - video_driver_get_size(&width, &height); - - vp->x = d3d->final_viewport.X; - vp->y = d3d->final_viewport.Y; - vp->width = d3d->final_viewport.Width; - vp->height = d3d->final_viewport.Height; - - vp->full_width = width; - vp->full_height = height; -} - -#if defined(HAVE_MENU) || defined(HAVE_OVERLAY) -static void d3d9_overlay_render(d3d9_video_t *d3d, - unsigned width, - unsigned height, - overlay_t *overlay, bool force_linear) -{ - D3DTEXTUREFILTERTYPE filter_type; - LPDIRECT3DVERTEXDECLARATION9 vertex_decl; - LPDIRECT3DDEVICE9 dev; - struct video_viewport vp; - void *verts; - unsigned i; - Vertex vert[4]; - D3DVERTEXELEMENT9 vElems[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 (!d3d || !overlay || !overlay->tex) - return; - - dev = d3d->dev; - - if (!overlay->vert_buf) - { - overlay->vert_buf = d3d9_vertex_buffer_new( - dev, sizeof(vert), D3DUSAGE_WRITEONLY, -#ifdef _XBOX - 0, -#else - D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, -#endif - D3DPOOL_MANAGED, NULL); - - if (!overlay->vert_buf) - return; - } - - for (i = 0; i < 4; i++) - { - vert[i].z = 0.5f; - vert[i].color = (((uint32_t)(overlay->alpha_mod * 0xFF)) << 24) | 0xFFFFFF; - } - - d3d9_viewport_info(d3d, &vp); - - vert[0].x = overlay->vert_coords[0]; - vert[1].x = overlay->vert_coords[0] + overlay->vert_coords[2]; - vert[2].x = overlay->vert_coords[0]; - vert[3].x = overlay->vert_coords[0] + overlay->vert_coords[2]; - vert[0].y = overlay->vert_coords[1]; - vert[1].y = overlay->vert_coords[1]; - vert[2].y = overlay->vert_coords[1] + overlay->vert_coords[3]; - vert[3].y = overlay->vert_coords[1] + overlay->vert_coords[3]; - - vert[0].u = overlay->tex_coords[0]; - vert[1].u = overlay->tex_coords[0] + overlay->tex_coords[2]; - vert[2].u = overlay->tex_coords[0]; - vert[3].u = overlay->tex_coords[0] + overlay->tex_coords[2]; - vert[0].v = overlay->tex_coords[1]; - vert[1].v = overlay->tex_coords[1]; - vert[2].v = overlay->tex_coords[1] + overlay->tex_coords[3]; - vert[3].v = overlay->tex_coords[1] + overlay->tex_coords[3]; - - verts = d3d9_vertex_buffer_lock((LPDIRECT3DVERTEXBUFFER9)overlay->vert_buf); - memcpy(verts, vert, sizeof(vert)); - d3d9_vertex_buffer_unlock((LPDIRECT3DVERTEXBUFFER9)overlay->vert_buf); - - d3d9_enable_blend_func(d3d->dev); - - /* set vertex declaration for overlay. */ - d3d9_vertex_declaration_new(dev, &vElems, (void**)&vertex_decl); - d3d9_set_vertex_declaration(dev, vertex_decl); - d3d9_vertex_declaration_free(vertex_decl); - - d3d9_set_stream_source(dev, 0, (LPDIRECT3DVERTEXBUFFER9)overlay->vert_buf, - 0, sizeof(*vert)); - - if (overlay->fullscreen) - { - D3DVIEWPORT9 vp_full; - - vp_full.X = 0; - vp_full.Y = 0; - vp_full.Width = width; - vp_full.Height = height; - vp_full.MinZ = 0.0f; - vp_full.MaxZ = 1.0f; - d3d9_set_viewports(dev, &vp_full); - } - - filter_type = D3DTEXF_LINEAR; - - if (!force_linear) - { - settings_t *settings = config_get_ptr(); - bool menu_linear_filter = settings->bools.menu_linear_filter; - if (!menu_linear_filter) - filter_type = D3DTEXF_POINT; - } - - /* Render overlay. */ - d3d9_set_texture(dev, 0, (LPDIRECT3DTEXTURE9)overlay->tex); - d3d9_set_sampler_address_u(dev, 0, D3DTADDRESS_BORDER); - d3d9_set_sampler_address_v(dev, 0, D3DTADDRESS_BORDER); - d3d9_set_sampler_minfilter(dev, 0, filter_type); - d3d9_set_sampler_magfilter(dev, 0, filter_type); - d3d9_draw_primitive(dev, D3DPT_TRIANGLESTRIP, 0, 2); - - /* Restore previous state. */ - d3d9_disable_blend_func(dev); - d3d9_set_viewports(dev, &d3d->final_viewport); -} -#endif - -static void d3d9_free_overlay(d3d9_video_t *d3d, overlay_t *overlay) -{ - if (!d3d) - return; - - d3d9_texture_free((LPDIRECT3DTEXTURE9)overlay->tex); - d3d9_vertex_buffer_free(overlay->vert_buf, NULL); -} - -static void d3d9_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_deinitialize(d3d9_video_t *d3d) { if (!d3d) @@ -559,166 +313,19 @@ static void d3d9_deinitialize(d3d9_video_t *d3d) font_driver_free_osd(); d3d9_deinit_chain(d3d); - d3d9_vertex_buffer_free(d3d->menu_display.buffer, d3d->menu_display.decl); + d3d9_vertex_buffer_free(d3d->menu_display.buffer, + d3d->menu_display.decl); d3d->menu_display.buffer = NULL; - d3d->menu_display.decl = NULL; -} - -static D3DFORMAT d3d9_get_color_format_backbuffer(bool rgb32, bool windowed) -{ - D3DFORMAT fmt = D3DFMT_X8R8G8B8; -#ifdef _XBOX - if (!rgb32) - fmt = d3d9_get_rgb565_format(); -#else - if (windowed) - { - D3DDISPLAYMODE display_mode; - if (d3d9_get_adapter_display_mode(g_pD3D9, 0, &display_mode)) - fmt = display_mode.Format; - } -#endif - return fmt; -} - -#ifdef _XBOX -static D3DFORMAT d3d9_get_color_format_front_buffer(void) -{ - return D3DFMT_LE_X8R8G8B8; -} -#endif - -static bool d3d9_is_windowed_enable(bool info_fullscreen) -{ -#ifndef _XBOX - settings_t *settings = config_get_ptr(); - if (!info_fullscreen) - return true; - if (settings) - return settings->bools.video_windowed_fullscreen; -#endif - return false; -} - -#ifdef _XBOX -static void d3d9_get_video_size(d3d9_video_t *d3d, - unsigned *width, unsigned *height) -{ - XVIDEO_MODE video_mode; - - XGetVideoMode(&video_mode); - - *width = video_mode.dwDisplayWidth; - *height = video_mode.dwDisplayHeight; - - d3d->resolution_hd_enable = false; - - if(video_mode.fIsHiDef) - { - *width = 1280; - *height = 720; - d3d->resolution_hd_enable = true; - } - else - { - *width = 640; - *height = 480; - } - - d3d->widescreen_mode = video_mode.fIsWideScreen; -} -#endif - -void d3d9_make_d3dpp(void *data, - const video_info_t *info, void *_d3dpp) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - D3DPRESENT_PARAMETERS *d3dpp = (D3DPRESENT_PARAMETERS*)_d3dpp; -#ifdef _XBOX - /* TODO/FIXME - get rid of global state dependencies. */ - global_t *global = global_get_ptr(); - int gamma_enable = global ? - global->console.screen.gamma_correction : 0; -#endif - bool windowed_enable = d3d9_is_windowed_enable(info->fullscreen); - - memset(d3dpp, 0, sizeof(*d3dpp)); - - d3dpp->Windowed = windowed_enable; - FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_IMMEDIATE; - - if (info->vsync) - { - settings_t *settings = config_get_ptr(); - unsigned video_swap_interval = settings->uints.video_swap_interval; - - switch (video_swap_interval) - { - default: - case 1: - FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_ONE; - break; - case 2: - FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_TWO; - break; - case 3: - FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_THREE; - break; - case 4: - FS_PRESENTINTERVAL(d3dpp) = D3DPRESENT_INTERVAL_FOUR; - break; - } - } - - d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp->BackBufferCount = 2; - d3dpp->BackBufferFormat = d3d9_get_color_format_backbuffer( - info->rgb32, windowed_enable); - -#ifdef _XBOX - d3dpp->FrontBufferFormat = d3d9_get_color_format_front_buffer(); - - if (gamma_enable) - { - d3dpp->BackBufferFormat = (D3DFORMAT)MAKESRGBFMT( - d3dpp->BackBufferFormat); - d3dpp->FrontBufferFormat = (D3DFORMAT)MAKESRGBFMT( - d3dpp->FrontBufferFormat); - } -#else - d3dpp->hDeviceWindow = win32_get_window(); -#endif - - if (!windowed_enable) - { -#ifdef _XBOX - unsigned width = 0; - unsigned height = 0; - d3d9_get_video_size(d3d, &width, &height); - video_driver_set_size(width, height); -#endif - video_driver_get_size(&d3dpp->BackBufferWidth, - &d3dpp->BackBufferHeight); - } - -#ifdef _XBOX - d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE; - d3dpp->EnableAutoDepthStencil = FALSE; - if (!d3d->widescreen_mode) - d3dpp->Flags |= D3DPRESENTFLAG_NO_LETTERBOX; - d3dpp->MultiSampleQuality = 0; -#endif + d3d->menu_display.decl = NULL; } static bool d3d9_init_base(void *data, const video_info_t *info) { D3DPRESENT_PARAMETERS d3dpp; - HWND focus_window = NULL; d3d9_video_t *d3d = (d3d9_video_t*)data; - #ifndef _XBOX - focus_window = win32_get_window(); + HWND focus_window = win32_get_window(); #endif memset(&d3dpp, 0, sizeof(d3dpp)); @@ -747,117 +354,6 @@ static bool d3d9_init_base(void *data, const video_info_t *info) return true; } -static void d3d9_calculate_rect(void *data, - unsigned *width, unsigned *height, - int *x, int *y, - bool force_full, - bool allow_rotate) -{ - float device_aspect = (float)*width / *height; - d3d9_video_t *d3d = (d3d9_video_t*)data; - settings_t *settings = config_get_ptr(); - bool scale_integer = settings->bools.video_scale_integer; - - video_driver_get_size(width, height); - - *x = 0; - *y = 0; - - if (scale_integer && !force_full) - { - struct video_viewport vp; - - vp.x = 0; - vp.y = 0; - vp.width = 0; - vp.height = 0; - vp.full_width = 0; - vp.full_height = 0; - - video_viewport_get_scaled_integer(&vp, - *width, - *height, - video_driver_get_aspect_ratio(), - d3d->keep_aspect); - - *x = vp.x; - *y = vp.y; - *width = vp.width; - *height = vp.height; - } - else if (d3d->keep_aspect && !force_full) - { - float desired_aspect = video_driver_get_aspect_ratio(); - -#if defined(HAVE_MENU) - if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM) - { - video_viewport_t *custom = video_viewport_get_custom(); - - *x = custom->x; - *y = custom->y; - *width = custom->width; - *height = custom->height; - } - else -#endif - { - float delta; - - if (fabsf(device_aspect - desired_aspect) < 0.0001f) - { - /* If the aspect ratios of screen and desired aspect - * ratio are sufficiently equal (floating point stuff), - * assume they are actually equal. - */ - } - else if (device_aspect > desired_aspect) - { - delta = (desired_aspect / device_aspect - 1.0f) / 2.0f + 0.5f; - *x = (int)(roundf(*width * (0.5f - delta))); - *width = (unsigned)(roundf(2.0f * (*width) * delta)); - } - else - { - delta = (device_aspect / desired_aspect - 1.0f) / 2.0f + 0.5f; - *y = (int)(roundf(*height * (0.5f - delta))); - *height = (unsigned)(roundf(2.0f * (*height) * delta)); - } - } - } -} - -static void d3d9_set_font_rect( - d3d9_video_t *d3d, - const struct font_params *params) -{ - settings_t *settings = config_get_ptr(); - float pos_x = settings->floats.video_msg_pos_x; - float pos_y = settings->floats.video_msg_pos_y; - float font_size = settings->floats.video_font_size; - - if (params) - { - pos_x = params->x; - pos_y = params->y; - font_size *= params->scale; - } - - if (!d3d) - return; - - d3d->font_rect.left = d3d->video_info.width * pos_x; - d3d->font_rect.right = d3d->video_info.width; - d3d->font_rect.top = (1.0f - pos_y) * d3d->video_info.height - font_size; - d3d->font_rect.bottom = d3d->video_info.height; - - d3d->font_rect_shifted = d3d->font_rect; - d3d->font_rect_shifted.left -= 2; - d3d->font_rect_shifted.right -= 2; - d3d->font_rect_shifted.top += 2; - d3d->font_rect_shifted.bottom += 2; -} - static void d3d9_set_viewport(void *data, unsigned width, unsigned height, bool force_full, @@ -886,6 +382,8 @@ static void d3d9_set_viewport(void *data, d3d9_set_font_rect(d3d, NULL); } + + static bool d3d9_initialize(d3d9_video_t *d3d, const video_info_t *info) { unsigned width, height; @@ -985,133 +483,6 @@ static bool d3d9_initialize(d3d9_video_t *d3d, const video_info_t *info) return true; } -static bool d3d9_restore(void *data) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - - if (!d3d) - return false; - - d3d9_deinitialize(d3d); - - if (!d3d9_initialize(d3d, &d3d->video_info)) - { - RARCH_ERR("[D3D9]: Restore error.\n"); - return false; - } - - d3d->needs_restore = false; - - return true; -} - -static void d3d9_set_nonblock_state(void *data, bool state, - bool adaptive_vsync_enabled, - unsigned swap_interval) -{ -#ifdef _XBOX - int interval = 0; -#endif - d3d9_video_t *d3d = (d3d9_video_t*)data; - - if (!d3d) - return; - -#ifdef _XBOX - if (!state) - interval = 1; -#endif - - d3d->video_info.vsync = !state; - -#ifdef _XBOX - d3d9_set_render_state(d3d->dev, - D3D9_PRESENTATIONINTERVAL, - interval ? - D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE - ); -#else - d3d->needs_restore = true; - d3d9_restore(d3d); -#endif -} - -static bool d3d9_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_set_resize(d3d, temp_width, temp_height); - d3d9_restore(d3d); - } - - ret = !quit; - - if ( temp_width != 0 && - temp_height != 0) - video_driver_set_size(temp_width, temp_height); - - return ret; -} - -static bool d3d9_suppress_screensaver(void *data, bool enable) -{ -#ifdef _XBOX - return true; -#else - return win32_suppress_screensaver(data, enable); -#endif -} - -static void d3d9_set_aspect_ratio(void *data, unsigned aspect_ratio_idx) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - - if (!d3d) - return; - - d3d->keep_aspect = true; - d3d->should_resize = true; -} - -static void d3d9_apply_state_changes(void *data) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - if (d3d) - d3d->should_resize = true; -} - -static void d3d9_set_osd_msg(void *data, - const char *msg, - const void *params, void *font) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - LPDIRECT3DDEVICE9 dev = d3d->dev; - const struct font_params *d3d_font_params = (const - struct font_params*)params; - - d3d9_set_font_rect(d3d, d3d_font_params); - d3d9_begin_scene(dev); - font_driver_render_msg(d3d, - msg, d3d_font_params, font); - d3d9_end_scene(dev); -} - static bool d3d9_init_internal(d3d9_video_t *d3d, const video_info_t *info, input_driver_t **input, void **input_data) @@ -1245,17 +616,6 @@ static bool d3d9_init_internal(d3d9_video_t *d3d, return true; } -static void d3d9_set_rotation(void *data, unsigned rot) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - struct video_ortho ortho = {0, 1, 0, 1, -1, 1}; - - if (!d3d) - return; - - d3d->dev_rotation = rot; -} - static void *d3d9_init(const video_info_t *info, input_driver_t **input, void **input_data) { @@ -1297,22 +657,6 @@ static void *d3d9_init(const video_info_t *info, return d3d; } -#ifdef HAVE_OVERLAY -static void d3d9_free_overlays(d3d9_video_t *d3d) -{ - unsigned i; - - if (!d3d) - return; - - for (i = 0; i < d3d->overlays_size; i++) - d3d9_free_overlay(d3d, &d3d->overlays[i]); - free(d3d->overlays); - d3d->overlays = NULL; - d3d->overlays_size = 0; -} -#endif - static void d3d9_free(void *data) { d3d9_video_t *d3d = (d3d9_video_t*)data; @@ -1352,150 +696,21 @@ static void d3d9_free(void *data) free(d3d); } -#ifdef HAVE_OVERLAY -static void d3d9_overlay_tex_geom( - void *data, - unsigned index, - float x, float y, - float w, float h) +bool d3d9_restore(d3d9_video_t *d3d) { - d3d9_video_t *d3d = (d3d9_video_t*)data; + d3d9_deinitialize(d3d); - if (!d3d) - return; - - d3d->overlays[index].tex_coords[0] = x; - d3d->overlays[index].tex_coords[1] = y; - d3d->overlays[index].tex_coords[2] = w; - d3d->overlays[index].tex_coords[3] = h; -} - -static void d3d9_overlay_vertex_geom( - void *data, - unsigned index, - float x, float y, - float w, float h) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - - if (!d3d) - return; - - y = 1.0f - y; - h = -h; - d3d->overlays[index].vert_coords[0] = x; - d3d->overlays[index].vert_coords[1] = y; - d3d->overlays[index].vert_coords[2] = w; - d3d->overlays[index].vert_coords[3] = h; -} - -static bool d3d9_overlay_load(void *data, - const void *image_data, unsigned num_images) -{ - unsigned i, y; - overlay_t *new_overlays = NULL; - d3d9_video_t *d3d = (d3d9_video_t*)data; - const struct texture_image *images = (const struct texture_image*) - image_data; - - if (!d3d) - return false; - - d3d9_free_overlays(d3d); - d3d->overlays = (overlay_t*)calloc(num_images, sizeof(*d3d->overlays)); - d3d->overlays_size = num_images; - - for (i = 0; i < num_images; i++) + if (!d3d9_initialize(d3d, &d3d->video_info)) { - D3DLOCKED_RECT d3dlr; - unsigned width = images[i].width; - unsigned height = images[i].height; - overlay_t *overlay = (overlay_t*)&d3d->overlays[i]; - - overlay->tex = d3d9_texture_new(d3d->dev, NULL, - width, height, 1, - 0, - d3d9_get_argb8888_format(), - D3DPOOL_MANAGED, 0, 0, 0, - NULL, NULL, false); - - if (!overlay->tex) - { - RARCH_ERR("[D3D9]: Failed to create overlay texture\n"); - return false; - } - - if (d3d9_lock_rectangle((LPDIRECT3DTEXTURE9)overlay->tex, 0, &d3dlr, - NULL, 0, D3DLOCK_NOSYSLOCK)) - { - uint32_t *dst = (uint32_t*)(d3dlr.pBits); - const uint32_t *src = images[i].pixels; - unsigned pitch = d3dlr.Pitch >> 2; - - for (y = 0; y < height; y++, dst += pitch, src += width) - memcpy(dst, src, width << 2); - d3d9_unlock_rectangle((LPDIRECT3DTEXTURE9)overlay->tex); - } - - overlay->tex_w = width; - overlay->tex_h = height; - - /* Default. Stretch to whole screen. */ - d3d9_overlay_tex_geom(d3d, i, 0, 0, 1, 1); - d3d9_overlay_vertex_geom(d3d, i, 0, 0, 1, 1); + RARCH_ERR("[D3D9]: Restore error.\n"); + return false; } + d3d->needs_restore = false; + return true; } -static void d3d9_overlay_enable(void *data, bool state) -{ - unsigned i; - d3d9_video_t *d3d = (d3d9_video_t*)data; - - if (!d3d) - return; - - for (i = 0; i < d3d->overlays_size; i++) - d3d->overlays_enabled = state; - -#ifndef XBOX - win32_show_cursor(d3d, state); -#endif -} - -static void d3d9_overlay_full_screen(void *data, bool enable) -{ - unsigned i; - d3d9_video_t *d3d = (d3d9_video_t*)data; - - for (i = 0; i < d3d->overlays_size; i++) - d3d->overlays[i].fullscreen = enable; -} - -static void d3d9_overlay_set_alpha(void *data, unsigned index, float mod) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - if (d3d) - d3d->overlays[index].alpha_mod = mod; -} - -static const video_overlay_interface_t d3d9_overlay_interface = { - d3d9_overlay_enable, - d3d9_overlay_load, - d3d9_overlay_tex_geom, - d3d9_overlay_vertex_geom, - d3d9_overlay_full_screen, - d3d9_overlay_set_alpha, -}; - -static void d3d9_get_overlay_interface(void *data, - const video_overlay_interface_t **iface) -{ - (void)data; - *iface = &d3d9_overlay_interface; -} -#endif static bool d3d9_frame(void *data, const void *frame, unsigned frame_width, unsigned frame_height, @@ -1643,327 +858,7 @@ static bool d3d9_frame(void *data, const void *frame, return true; } -static bool d3d9_read_viewport(void *data, uint8_t *buffer, bool is_idle) -{ - unsigned width, height; - D3DLOCKED_RECT rect; - LPDIRECT3DSURFACE9 target = NULL; - LPDIRECT3DSURFACE9 dest = NULL; - bool ret = true; - d3d9_video_t *d3d = (d3d9_video_t*)data; - LPDIRECT3DDEVICE9 d3dr = d3d->dev; - - video_driver_get_size(&width, &height); - - if ( - !d3d9_device_get_render_target(d3dr, 0, (void**)&target) || - !d3d9_device_create_offscreen_plain_surface(d3dr, width, height, - d3d9_get_xrgb8888_format(), - D3DPOOL_SYSTEMMEM, (void**)&dest, NULL) || - !d3d9_device_get_render_target_data(d3dr, target, dest) - ) - { - ret = false; - goto end; - } - - if (d3d9_surface_lock_rect(dest, &rect)) - { - unsigned x, y; - unsigned pitchpix = rect.Pitch / 4; - const uint32_t *pixels = (const uint32_t*)rect.pBits; - - pixels += d3d->final_viewport.X; - pixels += (d3d->final_viewport.Height - 1) * pitchpix; - pixels -= d3d->final_viewport.Y * pitchpix; - - for (y = 0; y < d3d->final_viewport.Height; y++, pixels -= pitchpix) - { - for (x = 0; x < d3d->final_viewport.Width; x++) - { - *buffer++ = (pixels[x] >> 0) & 0xff; - *buffer++ = (pixels[x] >> 8) & 0xff; - *buffer++ = (pixels[x] >> 16) & 0xff; - } - } - - d3d9_surface_unlock_rect(dest); - } - else - ret = false; - -end: - if (target) - d3d9_surface_free(target); - if (dest) - d3d9_surface_free(dest); - return ret; -} - -static bool d3d9_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) - 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 (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); - - 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_restore(d3d)) - { - RARCH_ERR("[D3D9]: Failed to set shader.\n"); - return false; - } - - return true; -#else - return false; -#endif -} - -static void d3d9_set_menu_texture_frame(void *data, - const void *frame, bool rgb32, unsigned width, unsigned height, - float alpha) -{ - D3DLOCKED_RECT d3dlr; - d3d9_video_t *d3d = (d3d9_video_t*)data; - - (void)d3dlr; - (void)frame; - (void)rgb32; - (void)width; - (void)height; - (void)alpha; - - if (!d3d || !d3d->menu) - return; - - if ( !d3d->menu->tex || - d3d->menu->tex_w != width || - d3d->menu->tex_h != height) - { - d3d9_texture_free((LPDIRECT3DTEXTURE9)d3d->menu->tex); - - d3d->menu->tex = d3d9_texture_new(d3d->dev, NULL, - width, height, 1, - 0, d3d9_get_argb8888_format(), - D3DPOOL_MANAGED, 0, 0, 0, NULL, NULL, false); - - if (!d3d->menu->tex) - { - RARCH_ERR("[D3D9]: Failed to create menu texture.\n"); - return; - } - - d3d->menu->tex_w = width; - d3d->menu->tex_h = height; - } - - d3d->menu->alpha_mod = alpha; - - if (d3d9_lock_rectangle((LPDIRECT3DTEXTURE9)d3d->menu->tex, 0, &d3dlr, - NULL, 0, D3DLOCK_NOSYSLOCK)) - { - unsigned h, w; - if (rgb32) - { - uint8_t *dst = (uint8_t*)d3dlr.pBits; - const uint32_t *src = (const uint32_t*)frame; - - for (h = 0; h < height; h++, dst += d3dlr.Pitch, src += width) - { - memcpy(dst, src, width * sizeof(uint32_t)); - memset(dst + width * sizeof(uint32_t), 0, - d3dlr.Pitch - width * sizeof(uint32_t)); - } - } - else - { - uint32_t *dst = (uint32_t*)d3dlr.pBits; - const uint16_t *src = (const uint16_t*)frame; - - for (h = 0; h < height; h++, dst += d3dlr.Pitch >> 2, src += width) - { - for (w = 0; w < width; w++) - { - uint16_t c = src[w]; - uint32_t r = (c >> 12) & 0xf; - uint32_t g = (c >> 8) & 0xf; - uint32_t b = (c >> 4) & 0xf; - uint32_t a = (c >> 0) & 0xf; - r = ((r << 4) | r) << 16; - g = ((g << 4) | g) << 8; - b = ((b << 4) | b) << 0; - a = ((a << 4) | a) << 24; - dst[w] = r | g | b | a; - } - } - } - - if (d3d->menu) - d3d9_unlock_rectangle((LPDIRECT3DTEXTURE9)d3d->menu->tex); - } -} - -static void d3d9_set_menu_texture_enable(void *data, - bool state, bool full_screen) -{ - d3d9_video_t *d3d = (d3d9_video_t*)data; - - if (!d3d || !d3d->menu) - return; - - d3d->menu->enabled = state; - d3d->menu->fullscreen = full_screen; -} - -struct d3d9_texture_info -{ - void *userdata; - void *data; - enum texture_filter_type type; -}; - -static void d3d9_video_texture_load_d3d( - struct d3d9_texture_info *info, - uintptr_t *id) -{ - D3DLOCKED_RECT d3dlr; - LPDIRECT3DTEXTURE9 tex = NULL; - unsigned usage = 0; - bool want_mipmap = false; - d3d9_video_t *d3d = (d3d9_video_t*)info->userdata; - struct texture_image *ti = (struct texture_image*)info->data; - - if (!ti) - return; - - if((info->type == TEXTURE_FILTER_MIPMAP_LINEAR) || - (info->type == TEXTURE_FILTER_MIPMAP_NEAREST)) - want_mipmap = true; - - tex = (LPDIRECT3DTEXTURE9)d3d9_texture_new(d3d->dev, NULL, - ti->width, ti->height, 0, - usage, d3d9_get_argb8888_format(), - D3DPOOL_MANAGED, 0, 0, 0, - NULL, NULL, want_mipmap); - - if (!tex) - { - RARCH_ERR("[D3D9]: Failed to create texture\n"); - return; - } - - if (d3d9_lock_rectangle(tex, 0, &d3dlr, - NULL, 0, D3DLOCK_NOSYSLOCK)) - { - unsigned i; - uint32_t *dst = (uint32_t*)(d3dlr.pBits); - const uint32_t *src = ti->pixels; - unsigned pitch = d3dlr.Pitch >> 2; - - for (i = 0; i < ti->height; i++, dst += pitch, src += ti->width) - memcpy(dst, src, ti->width << 2); - d3d9_unlock_rectangle(tex); - } - - *id = (uintptr_t)tex; -} - -#ifdef HAVE_THREADS -static int d3d9_video_texture_load_wrap_d3d(void *data) -{ - uintptr_t id = 0; - struct d3d9_texture_info *info = (struct d3d9_texture_info*)data; - if (!info) - return 0; - d3d9_video_texture_load_d3d(info, &id); - return id; -} -#endif - -static uintptr_t d3d9_load_texture(void *video_data, void *data, - bool threaded, enum texture_filter_type filter_type) -{ - uintptr_t id = 0; - struct d3d9_texture_info info; - - info.userdata = video_data; - info.data = data; - info.type = filter_type; - -#ifdef HAVE_THREADS - if (threaded) - return video_thread_texture_load(&info, - d3d9_video_texture_load_wrap_d3d); -#endif - - d3d9_video_texture_load_d3d(&info, &id); - return id; -} - -static void d3d9_unload_texture(void *data, - bool threaded, uintptr_t id) -{ - LPDIRECT3DTEXTURE9 texid; - if (!id) - return; - - texid = (LPDIRECT3DTEXTURE9)id; - d3d9_texture_free(texid); -} - -static void d3d9_set_video_mode(void *data, - unsigned width, unsigned height, - bool fullscreen) -{ -#ifndef _XBOX - win32_show_cursor(data, !fullscreen); -#endif -} - -static uint32_t d3d9_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); - - return flags; -} - -static const video_poke_interface_t d3d9_poke_interface = { +const video_poke_interface_t d3d9_poke_interface = { d3d9_get_flags, d3d9_load_texture, d3d9_unload_texture, @@ -1997,25 +892,6 @@ static const video_poke_interface_t d3d9_poke_interface = { NULL /* set_hdr_expand_gamut */ }; -static void d3d9_get_poke_interface(void *data, - const video_poke_interface_t **iface) -{ - *iface = &d3d9_poke_interface; -} - -#ifdef _XBOX -static bool d3d9_has_windowed(void *data) { return false; } -#else -static bool d3d9_has_windowed(void *data) { return true; } -#endif - -#ifdef HAVE_GFX_WIDGETS -static bool d3d9_gfx_widgets_enabled(void *data) -{ - return false; /* currently disabled due to memory issues */ -} -#endif - video_driver_t video_d3d9 = { d3d9_init, d3d9_frame,