RetroArch/gfx/drivers_display/gfx_display_d3d11.c

326 lines
12 KiB
C
Raw Normal View History

2018-01-25 00:20:06 +01:00
/* 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 <http://www.gnu.org/licenses/>.
*/
2018-02-04 20:03:27 +01:00
#define CINTERFACE
2018-01-25 00:20:06 +01:00
#include <retro_miscellaneous.h>
#ifdef HAVE_CONFIG_H
2021-08-18 14:19:48 -04:00
#include "../../config.h"
2018-01-25 00:20:06 +01:00
#endif
2020-02-16 15:10:07 +01:00
#include "../gfx_display.h"
2018-01-25 00:20:06 +01:00
#include "../../retroarch.h"
#include "../common/d3d11_common.h"
2018-01-25 00:20:06 +01:00
static void gfx_display_d3d11_blend_begin(void *data)
2018-01-25 15:48:53 +01:00
{
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
d3d11->context->lpVtbl->OMSetBlendState(d3d11->context, d3d11->blend_enable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
2018-01-25 15:48:53 +01:00
}
2018-01-25 00:20:06 +01:00
static void gfx_display_d3d11_blend_end(void *data)
2018-01-25 15:48:53 +01:00
{
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
d3d11->context->lpVtbl->OMSetBlendState(d3d11->context, d3d11->blend_disable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
2018-01-25 15:48:53 +01:00
}
2018-01-25 00:20:06 +01:00
2020-02-16 15:10:07 +01:00
static void gfx_display_d3d11_draw(gfx_display_ctx_draw_t *draw,
void *data, unsigned video_width, unsigned video_height)
2018-01-25 00:20:06 +01:00
{
int vertex_count = 1;
d3d11_video_t *d3d11 = (d3d11_video_t*)data;
2018-01-25 00:20:06 +01:00
if (!d3d11 || !draw || !draw->texture)
return;
2020-08-14 15:58:43 +02:00
switch (draw->pipeline_id)
{
2018-01-25 15:48:53 +01:00
case VIDEO_SHADER_MENU:
case VIDEO_SHADER_MENU_2:
case VIDEO_SHADER_MENU_3:
case VIDEO_SHADER_MENU_4:
case VIDEO_SHADER_MENU_5:
case VIDEO_SHADER_MENU_6:
2022-04-22 22:58:35 +02:00
{
d3d11_shader_t *shader = &d3d11->shaders[draw->pipeline_id];
d3d11->context->lpVtbl->IASetInputLayout(d3d11->context, shader->layout);
d3d11->context->lpVtbl->VSSetShader(d3d11->context, shader->vs, NULL, 0);
d3d11->context->lpVtbl->PSSetShader(d3d11->context, shader->ps, NULL, 0);
d3d11->context->lpVtbl->GSSetShader(d3d11->context, shader->gs, NULL, 0);
}
2022-04-24 13:40:38 +02:00
d3d11->context->lpVtbl->Draw(d3d11->context, draw->coords->vertices, 0);
d3d11->context->lpVtbl->OMSetBlendState(d3d11->context, d3d11->blend_enable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
2022-04-22 22:58:35 +02:00
{
d3d11_shader_t *shader = &d3d11->sprites.shader;
d3d11->context->lpVtbl->IASetInputLayout(d3d11->context, shader->layout);
d3d11->context->lpVtbl->VSSetShader(d3d11->context, shader->vs, NULL, 0);
d3d11->context->lpVtbl->PSSetShader(d3d11->context, shader->ps, NULL, 0);
d3d11->context->lpVtbl->GSSetShader(d3d11->context, shader->gs, NULL, 0);
}
{
UINT stride = sizeof(d3d11_sprite_t);
UINT offset = 0;
2022-04-23 09:06:40 +02:00
d3d11->context->lpVtbl->IASetVertexBuffers(
d3d11->context, 0, 1,
&d3d11->sprites.vbo, &stride, &offset);
}
d3d11->context->lpVtbl->IASetPrimitiveTopology(d3d11->context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
2018-01-25 15:48:53 +01:00
return;
}
2018-01-25 00:20:06 +01:00
2018-02-08 17:11:24 +01:00
if (draw->coords->vertex && draw->coords->tex_coord && draw->coords->color)
vertex_count = draw->coords->vertices;
2022-11-02 08:31:40 +01:00
if ( (!(d3d11->flags & D3D11_ST_FLAG_SPRITES_ENABLE))
|| (vertex_count > d3d11->sprites.capacity))
2018-01-25 00:20:06 +01:00
return;
2018-02-08 17:11:24 +01:00
if (d3d11->sprites.offset + vertex_count > d3d11->sprites.capacity)
d3d11->sprites.offset = 0;
2018-01-25 15:48:53 +01:00
{
D3D11_MAPPED_SUBRESOURCE mapped_vbo;
2018-02-08 17:11:24 +01:00
d3d11_sprite_t* sprite = NULL;
2018-02-03 15:16:04 +01:00
d3d11->context->lpVtbl->Map(
d3d11->context, (D3D11Resource)d3d11->sprites.vbo, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_vbo);
2018-02-03 15:16:04 +01:00
2018-02-08 17:11:24 +01:00
sprite = (d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset;
if (vertex_count == 1)
{
sprite->pos.x = draw->x / (float)d3d11->viewport.Width;
sprite->pos.y =
2018-02-08 17:11:24 +01:00
(d3d11->viewport.Height - draw->y - draw->height) / (float)d3d11->viewport.Height;
sprite->pos.w = draw->width / (float)d3d11->viewport.Width;
sprite->pos.h = draw->height / (float)d3d11->viewport.Height;
2018-02-08 17:11:24 +01:00
sprite->coords.u = 0.0f;
sprite->coords.v = 0.0f;
sprite->coords.w = 1.0f;
sprite->coords.h = 1.0f;
if (draw->scale_factor)
sprite->params.scaling = draw->scale_factor;
else
sprite->params.scaling = 1.0f;
sprite->params.rotation = draw->rotation;
2018-02-08 17:11:24 +01:00
sprite->colors[3] = DXGI_COLOR_RGBA(
2018-02-08 17:11:24 +01:00
0xFF * draw->coords->color[0], 0xFF * draw->coords->color[1],
0xFF * draw->coords->color[2], 0xFF * draw->coords->color[3]);
sprite->colors[2] = DXGI_COLOR_RGBA(
2018-02-08 17:11:24 +01:00
0xFF * draw->coords->color[4], 0xFF * draw->coords->color[5],
0xFF * draw->coords->color[6], 0xFF * draw->coords->color[7]);
sprite->colors[1] = DXGI_COLOR_RGBA(
2018-02-08 17:11:24 +01:00
0xFF * draw->coords->color[8], 0xFF * draw->coords->color[9],
0xFF * draw->coords->color[10], 0xFF * draw->coords->color[11]);
sprite->colors[0] = DXGI_COLOR_RGBA(
2018-02-08 17:11:24 +01:00
0xFF * draw->coords->color[12], 0xFF * draw->coords->color[13],
0xFF * draw->coords->color[14], 0xFF * draw->coords->color[15]);
}
2018-01-25 15:48:53 +01:00
else
2018-02-08 17:11:24 +01:00
{
2022-11-02 08:31:40 +01:00
int i;
2018-02-08 17:11:24 +01:00
const float* vertex = draw->coords->vertex;
const float* tex_coord = draw->coords->tex_coord;
const float* color = draw->coords->color;
for (i = 0; i < vertex_count; i++)
{
d3d11_vertex_t* v = (d3d11_vertex_t*)sprite;
v->position[0] = *vertex++;
v->position[1] = *vertex++;
v->texcoord[0] = *tex_coord++;
v->texcoord[1] = *tex_coord++;
v->color[0] = *color++;
v->color[1] = *color++;
v->color[2] = *color++;
v->color[3] = *color++;
sprite++;
}
2022-04-22 22:58:35 +02:00
{
d3d11_shader_t *shader = &d3d11->shaders[VIDEO_SHADER_STOCK_BLEND];
d3d11->context->lpVtbl->IASetInputLayout(d3d11->context, shader->layout);
d3d11->context->lpVtbl->VSSetShader(d3d11->context, shader->vs, NULL, 0);
d3d11->context->lpVtbl->PSSetShader(d3d11->context, shader->ps, NULL, 0);
d3d11->context->lpVtbl->GSSetShader(d3d11->context, shader->gs, NULL, 0);
}
d3d11->context->lpVtbl->IASetPrimitiveTopology(d3d11->context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
2018-02-08 17:11:24 +01:00
}
2018-01-25 15:48:53 +01:00
d3d11->context->lpVtbl->Unmap(d3d11->context, (D3D11Resource)d3d11->sprites.vbo, 0);
2018-01-25 15:48:53 +01:00
}
2018-01-25 00:20:06 +01:00
{
d3d11_texture_t *texture = (d3d11_texture_t*)draw->texture;
d3d11->context->lpVtbl->PSSetShaderResources(
d3d11->context, 0, 1, &texture->view);
2022-04-23 09:06:40 +02:00
d3d11->context->lpVtbl->PSSetSamplers(
d3d11->context, 0, 1, (D3D11SamplerState*)&texture->sampler);
}
2022-04-24 13:40:38 +02:00
d3d11->context->lpVtbl->Draw(d3d11->context, vertex_count,
d3d11->sprites.offset);
2018-02-08 17:11:24 +01:00
d3d11->sprites.offset += vertex_count;
if (vertex_count > 1)
{
2022-04-22 22:58:35 +02:00
d3d11_shader_t *shader = &d3d11->sprites.shader;
d3d11->context->lpVtbl->IASetInputLayout(d3d11->context, shader->layout);
d3d11->context->lpVtbl->VSSetShader(d3d11->context, shader->vs, NULL, 0);
d3d11->context->lpVtbl->PSSetShader(d3d11->context, shader->ps, NULL, 0);
d3d11->context->lpVtbl->GSSetShader(d3d11->context, shader->gs, NULL, 0);
d3d11->context->lpVtbl->IASetPrimitiveTopology(d3d11->context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
2018-02-08 17:11:24 +01:00
}
2018-01-25 00:20:06 +01:00
}
2020-02-16 15:10:07 +01:00
static void gfx_display_d3d11_draw_pipeline(gfx_display_ctx_draw_t *draw,
2021-04-08 00:38:24 +02:00
gfx_display_t *p_disp,
void *data, unsigned video_width, unsigned video_height)
{
d3d11_video_t *d3d11 = (d3d11_video_t*)data;
if (!d3d11 || !draw)
return;
2020-08-14 15:58:43 +02:00
switch (draw->pipeline_id)
{
case VIDEO_SHADER_MENU:
2018-01-25 15:48:53 +01:00
case VIDEO_SHADER_MENU_2:
{
2020-09-25 10:31:07 +02:00
video_coord_array_t* ca = &p_disp->dispca;
if (!d3d11->menu_pipeline_vbo)
{
D3D11_BUFFER_DESC desc;
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.ByteWidth = ca->coords.vertices * 2 * sizeof(float);
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
{
D3D11_SUBRESOURCE_DATA vertex_data;
vertex_data.pSysMem = ca->coords.vertex;
vertex_data.SysMemPitch = 0;
vertex_data.SysMemSlicePitch = 0;
d3d11->device->lpVtbl->CreateBuffer(d3d11->device, &desc, &vertex_data,
&d3d11->menu_pipeline_vbo);
}
}
{
UINT stride = 2 * sizeof(float);
UINT offset = 0;
2022-04-23 09:06:40 +02:00
d3d11->context->lpVtbl->IASetVertexBuffers(
d3d11->context, 0, 1,
&d3d11->menu_pipeline_vbo, &stride, &offset);
}
draw->coords->vertices = ca->coords.vertices;
d3d11->context->lpVtbl->OMSetBlendState(d3d11->context, d3d11->blend_pipeline, NULL, D3D11_DEFAULT_SAMPLE_MASK);
2018-01-25 15:48:53 +01:00
break;
}
case VIDEO_SHADER_MENU_3:
case VIDEO_SHADER_MENU_4:
case VIDEO_SHADER_MENU_5:
case VIDEO_SHADER_MENU_6:
{
UINT stride = sizeof(d3d11_vertex_t);
UINT offset = 0;
2022-04-23 09:06:40 +02:00
d3d11->context->lpVtbl->IASetVertexBuffers(
d3d11->context, 0, 1,
&d3d11->frame.vbo, &stride, &offset);
}
2018-01-25 15:48:53 +01:00
draw->coords->vertices = 4;
break;
default:
return;
}
d3d11->context->lpVtbl->IASetPrimitiveTopology(d3d11->context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
d3d11->ubo_values.time += 0.01f;
2018-02-03 15:16:04 +01:00
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
d3d11->context->lpVtbl->Map(
d3d11->context, (D3D11Resource)d3d11->ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
*(d3d11_uniform_t*)mapped_ubo.pData = d3d11->ubo_values;
d3d11->context->lpVtbl->Unmap(d3d11->context, (D3D11Resource)d3d11->ubo, 0);
}
}
2018-01-25 00:20:06 +01:00
void gfx_display_d3d11_scissor_begin(void *data,
unsigned video_width,
unsigned video_height,
int x, int y, unsigned width, unsigned height)
{
2019-04-08 15:22:21 +02:00
D3D11_RECT rect;
d3d11_video_t *d3d11 = (d3d11_video_t*)data;
if (!d3d11 || !width || !height)
return;
2019-04-08 15:22:21 +02:00
rect.left = x;
rect.top = y;
2022-04-22 22:58:35 +02:00
rect.right = width + x;
2019-04-08 15:22:21 +02:00
rect.bottom = height + y;
d3d11->context->lpVtbl->RSSetScissorRects(d3d11->context, 1, &rect);
}
void gfx_display_d3d11_scissor_end(void *data,
unsigned video_width,
unsigned video_height)
{
2019-04-08 15:22:21 +02:00
D3D11_RECT rect;
d3d11_video_t *d3d11 = (d3d11_video_t*)data;
if (!d3d11)
return;
2019-04-10 00:22:36 -04:00
rect.left = 0;
rect.top = 0;
2020-03-08 01:28:15 +01:00
rect.right = video_width;
rect.bottom = video_height;
d3d11->context->lpVtbl->RSSetScissorRects(d3d11->context, 1, &rect);
}
2020-02-16 15:10:07 +01:00
gfx_display_ctx_driver_t gfx_display_ctx_d3d11 = {
gfx_display_d3d11_draw,
gfx_display_d3d11_draw_pipeline,
gfx_display_d3d11_blend_begin,
gfx_display_d3d11_blend_end,
2020-09-26 21:40:16 +02:00
NULL, /* get_default_mvp */
NULL, /* get_default_vertices */
NULL, /* get_default_tex_coords */
FONT_DRIVER_RENDER_D3D11_API,
2020-02-16 15:10:07 +01:00
GFX_VIDEO_DRIVER_DIRECT3D11,
"d3d11",
true,
2020-02-16 15:10:07 +01:00
gfx_display_d3d11_scissor_begin,
gfx_display_d3d11_scissor_end
2018-01-25 00:20:06 +01:00
};