diff --git a/Makefile.common b/Makefile.common index 92d363a2ab..49dd6d3292 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1303,7 +1303,7 @@ endif ifeq ($(HAVE_D3D11), 1) OBJ += gfx/drivers/d3d11.o gfx/common/d3d11_common.o \ - gfx/drivers_font/d3d11_font.o + gfx/drivers_font/d3d11_font.o menu/drivers_display/menu_display_d3d11.o DEFINES += -DHAVE_D3D11 endif diff --git a/gfx/common/d3d11_common.c b/gfx/common/d3d11_common.c index b3cd629ec1..bb913b8934 100644 --- a/gfx/common/d3d11_common.c +++ b/gfx/common/d3d11_common.c @@ -67,8 +67,9 @@ void d3d11_init_texture(D3D11Device device, d3d11_texture_t* texture) texture->desc.SampleDesc.Count = 1; texture->desc.SampleDesc.Quality = 0; texture->desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texture->desc.CPUAccessFlags = 0; - texture->desc.MiscFlags = 0; + texture->desc.CPUAccessFlags = + texture->desc.Usage == D3D11_USAGE_DYNAMIC ? D3D11_CPU_ACCESS_WRITE : 0; + texture->desc.MiscFlags = 0; D3D11CreateTexture2D(device, &texture->desc, NULL, &texture->handle); { diff --git a/gfx/common/d3d11_common.h b/gfx/common/d3d11_common.h index b8666daeec..12184ca7f1 100644 --- a/gfx/common/d3d11_common.h +++ b/gfx/common/d3d11_common.h @@ -2538,7 +2538,7 @@ typedef struct D3D11Buffer vbo; D3D11InputLayout layout; int offset; - int size; + int capacity; bool enabled; } sprites; } d3d11_video_t; diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index d2b3e4f6ef..1ac809e2f1 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -28,6 +28,7 @@ #include "../common/dxgi_common.h" #include "../common/d3dcompiler_common.h" #include "../../performance_counters.h" +#include "../../menu/menu_driver.h" static void d3d11_set_filtering(void* data, unsigned index, bool smooth) { @@ -92,6 +93,7 @@ static void d3d11_gfx_free(void* data) Release(d3d11->sprites.vs); Release(d3d11->sprites.ps); + Release(d3d11->sprites.ps_8bit); Release(d3d11->sprites.gs); Release(d3d11->sprites.vbo); Release(d3d11->sprites.layout); @@ -107,6 +109,9 @@ static void d3d11_gfx_free(void* data) Release(d3d11->state); Release(d3d11->renderTargetView); Release(d3d11->swapChain); + + font_driver_free_osd(); + Release(d3d11->ctx); Release(d3d11->device); @@ -119,6 +124,8 @@ static void* d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data) { WNDCLASSEX wndclass = { 0 }; + MONITORINFOEX current_mon; + HMONITOR hm_to_use; settings_t* settings = config_get_ptr(); gfx_ctx_input_t inp = { input, input_data }; d3d11_video_t* d3d11 = (d3d11_video_t*)calloc(1, sizeof(*d3d11)); @@ -131,7 +138,17 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i wndclass.lpfnWndProc = WndProcD3D; win32_window_init(&wndclass, true, NULL); - if (!win32_set_video_mode(d3d11, video->width, video->height, video->fullscreen)) + win32_monitor_info(¤t_mon, &hm_to_use, &d3d11->cur_mon_id); + + d3d11->vp.full_width = video->width; + d3d11->vp.full_height = video->height; + + if (!d3d11->vp.full_width) + d3d11->vp.full_width = current_mon.rcMonitor.right - current_mon.rcMonitor.left; + if (!d3d11->vp.full_height) + d3d11->vp.full_height = current_mon.rcMonitor.bottom - current_mon.rcMonitor.top; + + if (!win32_set_video_mode(d3d11, d3d11->vp.full_width, d3d11->vp.full_height, video->fullscreen)) { RARCH_ERR("[D3D11]: win32_set_video_mode failed.\n"); goto error; @@ -144,8 +161,8 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i D3D_FEATURE_LEVEL requested_feature_level = D3D_FEATURE_LEVEL_11_0; DXGI_SWAP_CHAIN_DESC desc = { .BufferCount = 1, - .BufferDesc.Width = video->width, - .BufferDesc.Height = video->height, + .BufferDesc.Width = d3d11->vp.full_width, + .BufferDesc.Height = d3d11->vp.full_height, .BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM, .BufferDesc.RefreshRate.Numerator = 60, .BufferDesc.RefreshRate.Denominator = 1, @@ -182,10 +199,9 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i D3D11SetRenderTargets(d3d11->ctx, 1, &d3d11->renderTargetView, NULL); - d3d11->vp.full_width = video->width; - d3d11->vp.full_height = video->height; - d3d11->viewport.Width = video->width; - d3d11->viewport.Height = video->height; + video_driver_set_size(&d3d11->vp.full_width, &d3d11->vp.full_height); + d3d11->viewport.Width = d3d11->vp.full_width; + d3d11->viewport.Height = d3d11->vp.full_height; d3d11->resize_viewport = true; d3d11->vsync = video->vsync; d3d11->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; @@ -251,8 +267,8 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->menu.vbo); - d3d11->sprites.size = sizeof(d3d11_sprite_t) * 1024; - desc.ByteWidth = d3d11->sprites.size; + d3d11->sprites.capacity = 4096; + desc.ByteWidth = sizeof(d3d11_sprite_t) * d3d11->sprites.capacity; D3D11CreateBuffer(d3d11->device, &desc, NULL, &d3d11->sprites.vbo); } } @@ -425,6 +441,7 @@ static bool d3d11_gfx_frame( d3d11->resize_chain = false; d3d11->resize_viewport = true; + video_driver_set_size(&video_info->width, &video_info->height); } PERF_START(); @@ -508,6 +525,9 @@ static bool d3d11_gfx_frame( d3d11->sprites.offset = 0; d3d11->sprites.enabled = true; + if (d3d11->menu.enabled) + menu_driver_frame(video_info); + if (msg && *msg) { font_driver_render_msg(video_info, NULL, msg, NULL); @@ -646,11 +666,51 @@ static void d3d11_gfx_set_osd_msg( printf("OSD msg: %s\n", msg); } } +static uintptr_t d3d11_gfx_load_texture( + void* video_data, void* data, bool threaded, enum texture_filter_type filter_type) +{ + d3d11_video_t* d3d11 = (d3d11_video_t*)video_data; + struct texture_image* image = (struct texture_image*)data; + D3D11_BOX frame_box = { 0, 0, 0, image->width, image->height, 1 }; + + if (!d3d11) + return 0; + + d3d11_texture_t* texture = calloc(1, sizeof(*texture)); + + texture->desc.Width = image->width; + texture->desc.Height = image->height; + texture->desc.Format = + d3d11_get_closest_match_texture2D(d3d11->device, DXGI_FORMAT_B8G8R8A8_UNORM); + + d3d11_init_texture(d3d11->device, texture); + + d3d11_update_texture( + d3d11->ctx, image->width, image->height, 0, DXGI_FORMAT_B8G8R8A8_UNORM, image->pixels, + texture); + D3D11CopyTexture2DSubresourceRegion( + d3d11->ctx, texture->handle, 0, 0, 0, 0, texture->staging, 0, &frame_box); + + return (uintptr_t)texture; +} +static void d3d11_gfx_unload_texture(void* data, uintptr_t handle) +{ + d3d11_texture_t* texture = (d3d11_texture_t*)handle; + + if (!texture) + return; + + Release(texture->view); + Release(texture->staging); + Release(texture->handle); + free(texture); +} + static const video_poke_interface_t d3d11_poke_interface = { NULL, /* set_coords */ NULL, /* set_mvp */ - NULL, /* load_texture */ - NULL, /* unload_texture */ + d3d11_gfx_load_texture, + d3d11_gfx_unload_texture, NULL, /* set_video_mode */ d3d11_set_filtering, NULL, /* get_video_output_size */ diff --git a/gfx/drivers/d3d_shaders/sprite_sm4.hlsl.h b/gfx/drivers/d3d_shaders/sprite_sm4.hlsl.h index 2e1c081eb1..8448599210 100644 --- a/gfx/drivers/d3d_shaders/sprite_sm4.hlsl.h +++ b/gfx/drivers/d3d_shaders/sprite_sm4.hlsl.h @@ -74,13 +74,10 @@ SRC( float4 PSMain(PSInput input) : SV_TARGET { return input.color * t0.Sample(s0, input.texcoord); - // return input.color; }; float4 PSMainA8(PSInput input) : SV_TARGET { - // return t0.Sample(s0, input.texcoord).a; return input.color * t0.Sample(s0, input.texcoord).a; - // return input.color; }; ) diff --git a/gfx/drivers_font/d3d11_font.c b/gfx/drivers_font/d3d11_font.c index 4f91e77e2a..8cce456f5d 100644 --- a/gfx/drivers_font/d3d11_font.c +++ b/gfx/drivers_font/d3d11_font.c @@ -56,13 +56,12 @@ d3d11_font_init_font(void* data, const char* font_path, float font_size, bool is font->texture.desc.Height = font->atlas->height; font->texture.desc.Format = d3d11_get_closest_match_texture2D(d3d11->device, DXGI_FORMAT_A8_UNORM); - DEBUG_INT(font->texture.desc.Format); d3d11_init_texture(d3d11->device, &font->texture); d3d11_update_texture( - d3d11->ctx, font->atlas->width, font->atlas->height, font->atlas->width, DXGI_FORMAT_A8_UNORM, - font->atlas->buffer, &font->texture); + d3d11->ctx, font->atlas->width, font->atlas->height, font->atlas->width, + DXGI_FORMAT_A8_UNORM, font->atlas->buffer, &font->texture); font->texture.dirty = true; - font->atlas->dirty = false; + font->atlas->dirty = false; return font; } @@ -127,14 +126,16 @@ static void d3d11_font_render_line( float pos_y, unsigned text_align) { - unsigned i; - d3d11_video_t* d3d11 = (d3d11_video_t*)video_driver_get_ptr(false); - unsigned width = video_info->width; - unsigned height = video_info->height; - int x = roundf(pos_x * width); - int y = roundf((1.0 - pos_y) * height); + unsigned i, count; + D3D11_MAPPED_SUBRESOURCE mapped_vbo; + d3d11_sprite_t* v; + d3d11_video_t* d3d11 = (d3d11_video_t*)video_driver_get_ptr(false); + unsigned width = video_info->width; + unsigned height = video_info->height; + int x = roundf(pos_x * width); + int y = roundf((1.0 - pos_y) * height); - if (!d3d11->sprites.enabled || d3d11->sprites.offset + msg_len > d3d11->sprites.size) + if (!d3d11->sprites.enabled || d3d11->sprites.offset + msg_len > d3d11->sprites.capacity) return; switch (text_align) @@ -148,12 +149,12 @@ static void d3d11_font_render_line( break; } - D3D11_MAPPED_SUBRESOURCE mapped_vbo; D3D11MapBuffer(d3d11->ctx, d3d11->sprites.vbo, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_vbo); - d3d11_sprite_t* v = (d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset; + v = (d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset; for (i = 0; i < msg_len; i++) { + const struct font_glyph* glyph; const char* msg_tmp = &msg[i]; unsigned code = utf8_walk(&msg_tmp); unsigned skip = msg_tmp - &msg[i]; @@ -161,7 +162,7 @@ static void d3d11_font_render_line( if (skip > 1) i += skip - 1; - const struct font_glyph* glyph = font->font_driver->get_glyph(font->font_data, code); + glyph = font->font_driver->get_glyph(font->font_data, code); if (!glyph) /* Do something smarter here ... */ glyph = font->font_driver->get_glyph(font->font_data, '?'); @@ -177,7 +178,7 @@ static void d3d11_font_render_line( v->coords.u = glyph->atlas_offset_x / (float)font->texture.desc.Width; v->coords.v = glyph->atlas_offset_y / (float)font->texture.desc.Height; v->coords.w = glyph->width / (float)font->texture.desc.Width; - v->coords.h = glyph->height / (float)font->texture.desc.Height; + v->coords.h = glyph->height / (float)font->texture.desc.Height; v->colors[0] = color; v->colors[1] = color; @@ -190,9 +191,7 @@ static void d3d11_font_render_line( y += glyph->advance_y * scale; } - v++; - - int count = v - ((d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset); + count = v - ((d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset); D3D11UnmapBuffer(d3d11->ctx, d3d11->sprites.vbo, 0); if (!count) @@ -200,20 +199,18 @@ static void d3d11_font_render_line( if (font->atlas->dirty) { - d3d11_update_texture( - d3d11->ctx, font->atlas->width, font->atlas->height, font->atlas->width, DXGI_FORMAT_A8_UNORM, - font->atlas->buffer, &font->texture); - font->atlas->dirty = false; + d3d11->ctx, font->atlas->width, font->atlas->height, font->atlas->width, + DXGI_FORMAT_A8_UNORM, font->atlas->buffer, &font->texture); + font->atlas->dirty = false; font->texture.dirty = true; } - if(font->texture.dirty) + if (font->texture.dirty) { D3D11_BOX frame_box = { 0, 0, 0, font->atlas->width, font->atlas->height, 1 }; D3D11CopyTexture2DSubresourceRegion( - d3d11->ctx, font->texture.handle, 0, 0, 0, 0, font->texture.staging, 0, - &frame_box); + d3d11->ctx, font->texture.handle, 0, 0, 0, 0, font->texture.staging, 0, &frame_box); font->texture.dirty = false; } diff --git a/griffin/griffin.c b/griffin/griffin.c index 26a7fdbc3d..8a5f02c6c9 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -1162,6 +1162,10 @@ MENU #include "../menu/drivers_display/menu_display_d3d.c" #endif +#if defined(HAVE_D3D11) +#include "../menu/drivers_display/menu_display_d3d11.c" +#endif + #ifdef HAVE_OPENGL #include "../menu/drivers_display/menu_display_gl.c" #endif diff --git a/menu/drivers_display/menu_display_d3d11.c b/menu/drivers_display/menu_display_d3d11.c new file mode 100644 index 0000000000..f7b5faab41 --- /dev/null +++ b/menu/drivers_display/menu_display_d3d11.c @@ -0,0 +1,139 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2014-2018 - Ali Bouhlel + * + * 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 . + */ + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "menu/menu_driver.h" + +#include "retroarch.h" +#include "gfx/font_driver.h" +#include "gfx/video_driver.h" +#include "gfx/common/d3d11_common.h" + +static const float* menu_display_d3d11_get_default_vertices(void) { return NULL; } + +static const float* menu_display_d3d11_get_default_tex_coords(void) { return NULL; } + +static void* menu_display_d3d11_get_default_mvp(void) { return NULL; } + +static void menu_display_d3d11_blend_begin(void) {} + +static void menu_display_d3d11_blend_end(void) {} + +static void menu_display_d3d11_viewport(void* data) {} + +static void menu_display_d3d11_draw(void* data) +{ + d3d11_video_t* d3d11 = (d3d11_video_t*)video_driver_get_ptr(false); + menu_display_ctx_draw_t* draw = (menu_display_ctx_draw_t*)data; + + if (!d3d11 || !draw || !draw->texture) + return; + + if (draw->pipeline.id) + return; + + if (!d3d11->sprites.enabled) + return; + + if(d3d11->sprites.offset + 1 > d3d11->sprites.capacity) + return; + + D3D11_MAPPED_SUBRESOURCE mapped_vbo; + D3D11MapBuffer(d3d11->ctx, d3d11->sprites.vbo, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_vbo); + d3d11_sprite_t* v = (d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset; + + v->pos.x = draw->x / (float)d3d11->viewport.Width; + v->pos.y = (d3d11->viewport.Height - draw->y - draw->height) / (float)d3d11->viewport.Height; + v->pos.w = draw->width / (float)d3d11->viewport.Width; + v->pos.h = draw->height / (float)d3d11->viewport.Height; + + v->coords.u = 0.0f; + v->coords.v = 0.0f; + v->coords.w = 1.0f; + v->coords.h = 1.0f; + + v->colors[0] = DXGI_COLOR_RGBA( + 0xFF * draw->coords->color[0], 0xFF * draw->coords->color[1], + 0xFF * draw->coords->color[2], 0xFF * draw->coords->color[3]); + v->colors[1] = DXGI_COLOR_RGBA( + 0xFF * draw->coords->color[4], 0xFF * draw->coords->color[5], + 0xFF * draw->coords->color[6], 0xFF * draw->coords->color[7]); + v->colors[2] = DXGI_COLOR_RGBA( + 0xFF * draw->coords->color[8], 0xFF * draw->coords->color[9], + 0xFF * draw->coords->color[10], 0xFF * draw->coords->color[11]); + v->colors[3] = DXGI_COLOR_RGBA( + 0xFF * draw->coords->color[12], 0xFF * draw->coords->color[13], + 0xFF * draw->coords->color[14], 0xFF * draw->coords->color[15]); + + D3D11UnmapBuffer(d3d11->ctx, d3d11->sprites.vbo, 0); +#if 0 + D3D11SetPShader(d3d11->ctx, d3d11->sprites.ps, NULL, 0); +#endif + D3D11SetPShaderResources(d3d11->ctx, 0, 1, &((d3d11_texture_t*)draw->texture)->view); + + + D3D11Draw(d3d11->ctx, 1, d3d11->sprites.offset); + d3d11->sprites.offset++; + return; +} + +static void menu_display_d3d11_draw_pipeline(void* data) {} + +static void menu_display_d3d11_restore_clear_color(void) {} + +static void menu_display_d3d11_clear_color(menu_display_ctx_clearcolor_t* clearcolor) +{ + DWORD clear_color = 0; + d3d11_video_t* d3d11 = (d3d11_video_t*)video_driver_get_ptr(false); + + if (!d3d11 || !clearcolor) + return; + + D3D11ClearRenderTargetView(d3d11->ctx, d3d11->renderTargetView, (float*)clearcolor); +} + +static bool menu_display_d3d11_font_init_first( + void** font_handle, + void* video_data, + const char* font_path, + float font_size, + bool is_threaded) +{ + font_data_t** handle = (font_data_t**)font_handle; + *handle = font_driver_init_first( + video_data, font_path, font_size, true, is_threaded, FONT_DRIVER_RENDER_D3D11_API); + return *handle; +} + +menu_display_ctx_driver_t menu_display_ctx_d3d11 = { + menu_display_d3d11_draw, + menu_display_d3d11_draw_pipeline, + menu_display_d3d11_viewport, + menu_display_d3d11_blend_begin, + menu_display_d3d11_blend_end, + menu_display_d3d11_restore_clear_color, + menu_display_d3d11_clear_color, + menu_display_d3d11_get_default_mvp, + menu_display_d3d11_get_default_vertices, + menu_display_d3d11_get_default_tex_coords, + menu_display_d3d11_font_init_first, + MENU_VIDEO_DRIVER_DIRECT3D11, + "menu_display_d3d11", +}; diff --git a/menu/menu_driver.c b/menu/menu_driver.c index acd2f4456b..bebf064d09 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -90,6 +90,9 @@ static menu_display_ctx_driver_t *menu_display_ctx_drivers[] = { #ifdef HAVE_D3D &menu_display_ctx_d3d, #endif +#ifdef HAVE_D3D11 + &menu_display_ctx_d3d11, +#endif #ifdef HAVE_OPENGL &menu_display_ctx_gl, #endif @@ -222,6 +225,10 @@ static bool menu_display_check_compatibility( ) return true; break; + case MENU_VIDEO_DRIVER_DIRECT3D11: + if (string_is_equal(video_driver, "d3d11")) + return true; + break; case MENU_VIDEO_DRIVER_VITA2D: if (string_is_equal(video_driver, "vita2d")) return true; diff --git a/menu/menu_driver.h b/menu/menu_driver.h index 030fba6aff..fdedb7765d 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -279,6 +279,7 @@ enum menu_display_driver_type MENU_VIDEO_DRIVER_OPENGL, MENU_VIDEO_DRIVER_VULKAN, MENU_VIDEO_DRIVER_DIRECT3D, + MENU_VIDEO_DRIVER_DIRECT3D11, MENU_VIDEO_DRIVER_VITA2D, MENU_VIDEO_DRIVER_CTR, MENU_VIDEO_DRIVER_WIIU, @@ -732,6 +733,7 @@ extern uintptr_t menu_display_white_texture; extern menu_display_ctx_driver_t menu_display_ctx_gl; extern menu_display_ctx_driver_t menu_display_ctx_vulkan; extern menu_display_ctx_driver_t menu_display_ctx_d3d; +extern menu_display_ctx_driver_t menu_display_ctx_d3d11; extern menu_display_ctx_driver_t menu_display_ctx_vita2d; extern menu_display_ctx_driver_t menu_display_ctx_ctr; extern menu_display_ctx_driver_t menu_display_ctx_wiiu;