diff --git a/gfx/d3d9/d3d.cpp b/gfx/d3d9/d3d.cpp index fb7b8da4be..5106ae4968 100644 --- a/gfx/d3d9/d3d.cpp +++ b/gfx/d3d9/d3d.cpp @@ -514,112 +514,7 @@ bool d3d_restore(void *data) } #ifdef HAVE_OVERLAY -static void d3d_overlay_render(void *data, overlay_t *overlay) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - - if (!overlay || !overlay->tex) - return; - - struct overlay_vertex - { - float x, y, z; - float u, v; - float r, g, b, a; - } vert[4]; - - if (!overlay->vert_buf) - { - D3DDevice_CreateVertexBuffers(d3d->dev, sizeof(vert), - d3d->dev->GetSoftwareVertexProcessing() ? D3DUSAGE_SOFTWAREPROCESSING : 0, 0, D3DPOOL_MANAGED, &overlay->vert_buf, NULL); - } - - for (unsigned i = 0; i < 4; i++) - { - vert[i].z = 0.5f; - vert[i].r = vert[i].g = vert[i].b = 1.0f; - vert[i].a = overlay->alpha_mod; - } - - float overlay_width = d3d->final_viewport.Width; - float overlay_height = d3d->final_viewport.Height; - - vert[0].x = overlay->vert_coords.x * overlay_width; - vert[1].x = (overlay->vert_coords.x + overlay->vert_coords.w) * overlay_width; - vert[2].x = overlay->vert_coords.x * overlay_width; - vert[3].x = (overlay->vert_coords.x + overlay->vert_coords.w) * overlay_width; - vert[0].y = overlay->vert_coords.y * overlay_height; - vert[1].y = overlay->vert_coords.y * overlay_height; - vert[2].y = (overlay->vert_coords.y + overlay->vert_coords.h) * overlay_height; - vert[3].y = (overlay->vert_coords.y + overlay->vert_coords.h) * overlay_height; - - vert[0].u = overlay->tex_coords.x; - vert[1].u = overlay->tex_coords.x + overlay->tex_coords.w; - vert[2].u = overlay->tex_coords.x; - vert[3].u = overlay->tex_coords.x + overlay->tex_coords.w; - vert[0].v = overlay->tex_coords.y; - vert[1].v = overlay->tex_coords.y; - vert[2].v = overlay->tex_coords.y + overlay->tex_coords.h; - vert[3].v = overlay->tex_coords.y + overlay->tex_coords.h; - - // Align texels and vertices. - for (unsigned i = 0; i < 4; i++) - { - vert[i].x -= 0.5f; - vert[i].y += 0.5f; - } - - void *verts; - overlay->vert_buf->Lock(0, sizeof(vert), &verts, 0); - memcpy(verts, vert, sizeof(vert)); - overlay->vert_buf->Unlock(); - - // enable alpha - d3d->dev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - d3d->dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - d3d->dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - -#ifndef _XBOX1 - // set vertex decl for overlay - D3DVERTEXELEMENT vElems[4] = { - {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, - {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, - {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, - D3DDECL_END() - }; - LPDIRECT3DVERTEXDECLARATION vertex_decl; - d3d->dev->CreateVertexDeclaration(vElems, &vertex_decl); - d3d->dev->SetVertexDeclaration(vertex_decl); - vertex_decl->Release(); -#endif - - D3DDevice_SetStreamSources(d3d->dev, 0, overlay->vert_buf, 0, sizeof(overlay_vertex)); - - if (overlay->fullscreen) - { - // set viewport to full window - D3DVIEWPORT vp_full; - vp_full.X = 0; - vp_full.Y = 0; - vp_full.Width = d3d->screen_width; - vp_full.Height = d3d->screen_height; - vp_full.MinZ = 0.0f; - vp_full.MaxZ = 1.0f; - d3d->dev->SetViewport(&vp_full); - } - - // render overlay - d3d->dev->SetTexture(0, overlay->tex); - D3DDevice_SetSamplerState_AddressU(d3d->dev, 0, D3DTADDRESS_BORDER); - D3DDevice_SetSamplerState_AddressV(d3d->dev, 0, D3DTADDRESS_BORDER); - D3DDevice_SetSamplerState_MinFilter(d3d->dev, 0, D3DTEXF_LINEAR); - D3DDevice_SetSamplerState_MagFilter(d3d->dev, 0, D3DTEXF_LINEAR); - D3DDevice_DrawPrimitive(d3d->dev, D3DPT_TRIANGLESTRIP, 0, 2); - - // restore previous state - d3d->dev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - d3d->dev->SetViewport(&d3d->final_viewport); -} +#include "d3d_overlays.cpp" #endif static void d3d_set_viewport(void *data, int x, int y, unsigned width, unsigned height) @@ -833,25 +728,6 @@ static void d3d_set_rotation(void *data, unsigned rot) d3d->dev_rotation = rot; } -#ifdef HAVE_OVERLAY -void d3d_free_overlay(void *data, overlay_t *overlay) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - if (overlay->tex) - overlay->tex->Release(); - if (overlay->vert_buf) - overlay->vert_buf->Release(); -} - -void d3d_free_overlays(void *data) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - for (unsigned i = 0; i < d3d->overlays.size(); i++) - d3d_free_overlay(d3d, &d3d->overlays[i]); - d3d->overlays.clear(); -} -#endif - static void d3d_free(void *data) { d3d_video_t *d3d = (d3d_video_t*)data; @@ -989,117 +865,6 @@ static bool d3d_set_shader(void *data, enum rarch_shader_type type, const char * static void d3d_get_poke_interface(void *data, const video_poke_interface_t **iface); #endif -#ifdef HAVE_OVERLAY -static void d3d_overlay_tex_geom(void *data, - unsigned index, - float x, float y, - float w, float h) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - - d3d->overlays[index].tex_coords.x = x; - d3d->overlays[index].tex_coords.y = y; - d3d->overlays[index].tex_coords.w = w; - d3d->overlays[index].tex_coords.h = h; -} - -static void d3d_overlay_vertex_geom(void *data, - unsigned index, - float x, float y, - float w, float h) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - - y = 1.0f - y; - h = -h; - d3d->overlays[index].vert_coords.x = x; - d3d->overlays[index].vert_coords.y = y; - d3d->overlays[index].vert_coords.w = w; - d3d->overlays[index].vert_coords.h = h; -} - -static bool d3d_overlay_load(void *data, const texture_image *images, unsigned num_images) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - d3d_free_overlays(data); - d3d->overlays.resize(num_images); - - for (unsigned i = 0; i < num_images; i++) - { - unsigned width = images[i].width; - unsigned height = images[i].height; - overlay_t &overlay = d3d->overlays[i]; - if (FAILED(d3d->dev->CreateTexture(width, height, 1, - 0, - D3DFMT_A8R8G8B8, - D3DPOOL_MANAGED, - &overlay.tex, NULL))) - { - RARCH_ERR("[D3D]: Failed to create overlay texture\n"); - return false; - } - - D3DLOCKED_RECT d3dlr; - if (SUCCEEDED(overlay.tex->LockRect(0, &d3dlr, NULL, D3DLOCK_NOSYSLOCK))) - { - uint32_t *dst = static_cast(d3dlr.pBits); - const uint32_t *src = images[i].pixels; - unsigned pitch = d3dlr.Pitch >> 2; - for (unsigned y = 0; y < height; y++, dst += pitch, src += width) - memcpy(dst, src, width << 2); - overlay.tex->UnlockRect(0); - } - - overlay.tex_w = width; - overlay.tex_h = height; - d3d_overlay_tex_geom(d3d, i, 0, 0, 1, 1); // Default. Stretch to whole screen. - d3d_overlay_vertex_geom(d3d, i, 0, 0, 1, 1); - } - - return true; -} - -static void d3d_overlay_enable(void *data, bool state) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - - for (unsigned i = 0; i < d3d->overlays.size(); i++) - d3d->overlays_enabled = state; - - if (d3d && d3d->ctx_driver && d3d->ctx_driver->show_mouse) - d3d->ctx_driver->show_mouse(d3d, state); -} - -static void d3d_overlay_full_screen(void *data, bool enable) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - - for (unsigned i = 0; i < d3d->overlays.size(); i++) - d3d->overlays[i].fullscreen = enable; -} - -static void d3d_overlay_set_alpha(void *data, unsigned index, float mod) -{ - d3d_video_t *d3d = (d3d_video_t*)data; - d3d->overlays[index].alpha_mod = mod; -} - -static const video_overlay_interface_t d3d_overlay_interface = { - d3d_overlay_enable, - d3d_overlay_load, - d3d_overlay_tex_geom, - d3d_overlay_vertex_geom, - d3d_overlay_full_screen, - d3d_overlay_set_alpha, -}; - -static void d3d_get_overlay_interface(void *data, const video_overlay_interface_t **iface) -{ - (void)data; - *iface = &d3d_overlay_interface; -} -#endif - static void d3d_set_aspect_ratio(void *data, unsigned aspect_ratio_idx) { d3d_video_t *d3d = (d3d_video_t*)data; diff --git a/gfx/d3d9/d3d_overlays.cpp b/gfx/d3d9/d3d_overlays.cpp new file mode 100644 index 0000000000..0e3109aad4 --- /dev/null +++ b/gfx/d3d9/d3d_overlays.cpp @@ -0,0 +1,232 @@ +static void d3d_overlay_render(void *data, overlay_t *overlay) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + + if (!overlay || !overlay->tex) + return; + + struct overlay_vertex + { + float x, y, z; + float u, v; + float r, g, b, a; + } vert[4]; + + if (!overlay->vert_buf) + { + D3DDevice_CreateVertexBuffers(d3d->dev, sizeof(vert), + d3d->dev->GetSoftwareVertexProcessing() ? D3DUSAGE_SOFTWAREPROCESSING : 0, 0, D3DPOOL_MANAGED, &overlay->vert_buf, NULL); + } + + for (unsigned i = 0; i < 4; i++) + { + vert[i].z = 0.5f; + vert[i].r = vert[i].g = vert[i].b = 1.0f; + vert[i].a = overlay->alpha_mod; + } + + float overlay_width = d3d->final_viewport.Width; + float overlay_height = d3d->final_viewport.Height; + + vert[0].x = overlay->vert_coords.x * overlay_width; + vert[1].x = (overlay->vert_coords.x + overlay->vert_coords.w) * overlay_width; + vert[2].x = overlay->vert_coords.x * overlay_width; + vert[3].x = (overlay->vert_coords.x + overlay->vert_coords.w) * overlay_width; + vert[0].y = overlay->vert_coords.y * overlay_height; + vert[1].y = overlay->vert_coords.y * overlay_height; + vert[2].y = (overlay->vert_coords.y + overlay->vert_coords.h) * overlay_height; + vert[3].y = (overlay->vert_coords.y + overlay->vert_coords.h) * overlay_height; + + vert[0].u = overlay->tex_coords.x; + vert[1].u = overlay->tex_coords.x + overlay->tex_coords.w; + vert[2].u = overlay->tex_coords.x; + vert[3].u = overlay->tex_coords.x + overlay->tex_coords.w; + vert[0].v = overlay->tex_coords.y; + vert[1].v = overlay->tex_coords.y; + vert[2].v = overlay->tex_coords.y + overlay->tex_coords.h; + vert[3].v = overlay->tex_coords.y + overlay->tex_coords.h; + + // Align texels and vertices. + for (unsigned i = 0; i < 4; i++) + { + vert[i].x -= 0.5f; + vert[i].y += 0.5f; + } + + void *verts; + overlay->vert_buf->Lock(0, sizeof(vert), &verts, 0); + memcpy(verts, vert, sizeof(vert)); + overlay->vert_buf->Unlock(); + + // enable alpha + d3d->dev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + d3d->dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + d3d->dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + +#ifndef _XBOX1 + // set vertex decl for overlay + D3DVERTEXELEMENT vElems[4] = { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + LPDIRECT3DVERTEXDECLARATION vertex_decl; + d3d->dev->CreateVertexDeclaration(vElems, &vertex_decl); + d3d->dev->SetVertexDeclaration(vertex_decl); + vertex_decl->Release(); +#endif + + D3DDevice_SetStreamSources(d3d->dev, 0, overlay->vert_buf, 0, sizeof(overlay_vertex)); + + if (overlay->fullscreen) + { + // set viewport to full window + D3DVIEWPORT vp_full; + vp_full.X = 0; + vp_full.Y = 0; + vp_full.Width = d3d->screen_width; + vp_full.Height = d3d->screen_height; + vp_full.MinZ = 0.0f; + vp_full.MaxZ = 1.0f; + d3d->dev->SetViewport(&vp_full); + } + + // render overlay + d3d->dev->SetTexture(0, overlay->tex); + D3DDevice_SetSamplerState_AddressU(d3d->dev, 0, D3DTADDRESS_BORDER); + D3DDevice_SetSamplerState_AddressV(d3d->dev, 0, D3DTADDRESS_BORDER); + D3DDevice_SetSamplerState_MinFilter(d3d->dev, 0, D3DTEXF_LINEAR); + D3DDevice_SetSamplerState_MagFilter(d3d->dev, 0, D3DTEXF_LINEAR); + D3DDevice_DrawPrimitive(d3d->dev, D3DPT_TRIANGLESTRIP, 0, 2); + + // restore previous state + d3d->dev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + d3d->dev->SetViewport(&d3d->final_viewport); +} + +void d3d_free_overlay(void *data, overlay_t *overlay) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + if (overlay->tex) + overlay->tex->Release(); + if (overlay->vert_buf) + overlay->vert_buf->Release(); +} + +void d3d_free_overlays(void *data) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + for (unsigned i = 0; i < d3d->overlays.size(); i++) + d3d_free_overlay(d3d, &d3d->overlays[i]); + d3d->overlays.clear(); +} + +static void d3d_overlay_tex_geom(void *data, + unsigned index, + float x, float y, + float w, float h) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + + d3d->overlays[index].tex_coords.x = x; + d3d->overlays[index].tex_coords.y = y; + d3d->overlays[index].tex_coords.w = w; + d3d->overlays[index].tex_coords.h = h; +} + +static void d3d_overlay_vertex_geom(void *data, + unsigned index, + float x, float y, + float w, float h) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + + y = 1.0f - y; + h = -h; + d3d->overlays[index].vert_coords.x = x; + d3d->overlays[index].vert_coords.y = y; + d3d->overlays[index].vert_coords.w = w; + d3d->overlays[index].vert_coords.h = h; +} + +static bool d3d_overlay_load(void *data, const texture_image *images, unsigned num_images) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + d3d_free_overlays(data); + d3d->overlays.resize(num_images); + + for (unsigned i = 0; i < num_images; i++) + { + unsigned width = images[i].width; + unsigned height = images[i].height; + overlay_t &overlay = d3d->overlays[i]; + if (FAILED(d3d->dev->CreateTexture(width, height, 1, + 0, + D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, + &overlay.tex, NULL))) + { + RARCH_ERR("[D3D]: Failed to create overlay texture\n"); + return false; + } + + D3DLOCKED_RECT d3dlr; + if (SUCCEEDED(overlay.tex->LockRect(0, &d3dlr, NULL, D3DLOCK_NOSYSLOCK))) + { + uint32_t *dst = static_cast(d3dlr.pBits); + const uint32_t *src = images[i].pixels; + unsigned pitch = d3dlr.Pitch >> 2; + for (unsigned y = 0; y < height; y++, dst += pitch, src += width) + memcpy(dst, src, width << 2); + overlay.tex->UnlockRect(0); + } + + overlay.tex_w = width; + overlay.tex_h = height; + d3d_overlay_tex_geom(d3d, i, 0, 0, 1, 1); // Default. Stretch to whole screen. + d3d_overlay_vertex_geom(d3d, i, 0, 0, 1, 1); + } + + return true; +} + +static void d3d_overlay_enable(void *data, bool state) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + + for (unsigned i = 0; i < d3d->overlays.size(); i++) + d3d->overlays_enabled = state; + + if (d3d && d3d->ctx_driver && d3d->ctx_driver->show_mouse) + d3d->ctx_driver->show_mouse(d3d, state); +} + +static void d3d_overlay_full_screen(void *data, bool enable) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + + for (unsigned i = 0; i < d3d->overlays.size(); i++) + d3d->overlays[i].fullscreen = enable; +} + +static void d3d_overlay_set_alpha(void *data, unsigned index, float mod) +{ + d3d_video_t *d3d = (d3d_video_t*)data; + d3d->overlays[index].alpha_mod = mod; +} + +static const video_overlay_interface_t d3d_overlay_interface = { + d3d_overlay_enable, + d3d_overlay_load, + d3d_overlay_tex_geom, + d3d_overlay_vertex_geom, + d3d_overlay_full_screen, + d3d_overlay_set_alpha, +}; + +static void d3d_get_overlay_interface(void *data, const video_overlay_interface_t **iface) +{ + (void)data; + *iface = &d3d_overlay_interface; +}