mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-24 08:30:16 +00:00
324 lines
10 KiB
C
324 lines
10 KiB
C
/* RetroArch - A frontend for libretro.
|
|
* Copyright (C) 2011-2018 - Daniel De Matteis
|
|
* 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/>.
|
|
*/
|
|
|
|
#define CINTERFACE
|
|
|
|
#include <retro_miscellaneous.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "../gfx_display.h"
|
|
|
|
#include "../../retroarch.h"
|
|
#include "../font_driver.h"
|
|
#include "../common/d3d10_common.h"
|
|
|
|
static const float* gfx_display_d3d10_get_default_vertices(void)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static const float* gfx_display_d3d10_get_default_tex_coords(void)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static void* gfx_display_d3d10_get_default_mvp(void *data)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static void gfx_display_d3d10_blend_begin(void *data)
|
|
{
|
|
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
|
D3D10SetBlendState(d3d10->device,
|
|
d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK);
|
|
}
|
|
|
|
static void gfx_display_d3d10_blend_end(void *data)
|
|
{
|
|
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
|
D3D10SetBlendState(d3d10->device,
|
|
d3d10->blend_disable, NULL, D3D10_DEFAULT_SAMPLE_MASK);
|
|
}
|
|
|
|
static void gfx_display_d3d10_viewport(gfx_display_ctx_draw_t *draw, void *data) { }
|
|
|
|
static void gfx_display_d3d10_draw(gfx_display_ctx_draw_t *draw,
|
|
void *data, unsigned video_width, unsigned video_height)
|
|
{
|
|
int vertex_count;
|
|
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
|
|
|
if (!d3d10 || !draw || !draw->texture)
|
|
return;
|
|
|
|
switch (draw->pipeline.id)
|
|
{
|
|
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:
|
|
d3d10_set_shader(d3d10->device, &d3d10->shaders[draw->pipeline.id]);
|
|
D3D10Draw(d3d10->device, draw->coords->vertices, 0);
|
|
|
|
D3D10SetBlendState(d3d10->device, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK);
|
|
d3d10_set_shader(d3d10->device, &d3d10->sprites.shader);
|
|
D3D10SetVertexBuffer(d3d10->device, 0, d3d10->sprites.vbo, sizeof(d3d10_sprite_t), 0);
|
|
D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_POINTLIST);
|
|
return;
|
|
}
|
|
|
|
if (draw->coords->vertex && draw->coords->tex_coord && draw->coords->color)
|
|
vertex_count = draw->coords->vertices;
|
|
else
|
|
vertex_count = 1;
|
|
|
|
if (!d3d10->sprites.enabled || vertex_count > d3d10->sprites.capacity)
|
|
return;
|
|
|
|
if (d3d10->sprites.offset + vertex_count > d3d10->sprites.capacity)
|
|
d3d10->sprites.offset = 0;
|
|
|
|
{
|
|
void* mapped_vbo;
|
|
d3d10_sprite_t* sprite = NULL;
|
|
|
|
D3D10MapBuffer(d3d10->sprites.vbo, D3D10_MAP_WRITE_NO_OVERWRITE, 0, &mapped_vbo);
|
|
|
|
sprite = (d3d10_sprite_t*)mapped_vbo + d3d10->sprites.offset;
|
|
|
|
if (vertex_count == 1)
|
|
{
|
|
sprite->pos.x = draw->x / (float)d3d10->viewport.Width;
|
|
sprite->pos.y =
|
|
(d3d10->viewport.Height - draw->y - draw->height)
|
|
/ (float)d3d10->viewport.Height;
|
|
sprite->pos.w = draw->width / (float)d3d10->viewport.Width;
|
|
sprite->pos.h = draw->height / (float)d3d10->viewport.Height;
|
|
|
|
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;
|
|
|
|
sprite->colors[3] = DXGI_COLOR_RGBA(
|
|
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(
|
|
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(
|
|
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(
|
|
0xFF * draw->coords->color[12], 0xFF * draw->coords->color[13],
|
|
0xFF * draw->coords->color[14], 0xFF * draw->coords->color[15]);
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
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++)
|
|
{
|
|
d3d10_vertex_t* v = (d3d10_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++;
|
|
}
|
|
|
|
d3d10_set_shader(d3d10->device, &d3d10->shaders[VIDEO_SHADER_STOCK_BLEND]);
|
|
D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
}
|
|
|
|
D3D10UnmapBuffer(d3d10->sprites.vbo);
|
|
}
|
|
|
|
d3d10_set_texture_and_sampler(d3d10->device, 0, (d3d10_texture_t*)draw->texture);
|
|
D3D10Draw(d3d10->device, vertex_count, d3d10->sprites.offset);
|
|
d3d10->sprites.offset += vertex_count;
|
|
|
|
if (vertex_count > 1)
|
|
{
|
|
d3d10_set_shader(d3d10->device, &d3d10->sprites.shader);
|
|
D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_POINTLIST);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void gfx_display_d3d10_draw_pipeline(gfx_display_ctx_draw_t* draw,
|
|
void *data, unsigned video_width, unsigned video_height)
|
|
{
|
|
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
|
|
|
if (!d3d10 || !draw)
|
|
return;
|
|
|
|
switch (draw->pipeline.id)
|
|
{
|
|
case VIDEO_SHADER_MENU:
|
|
case VIDEO_SHADER_MENU_2:
|
|
{
|
|
video_coord_array_t* ca = gfx_display_get_coords_array();
|
|
|
|
if (!d3d10->menu_pipeline_vbo)
|
|
{
|
|
D3D10_BUFFER_DESC desc = { 0 };
|
|
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
|
desc.ByteWidth = ca->coords.vertices * 2 * sizeof(float);
|
|
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
|
|
|
{
|
|
D3D10_SUBRESOURCE_DATA vertexData = { ca->coords.vertex };
|
|
D3D10CreateBuffer(d3d10->device, &desc, &vertexData, &d3d10->menu_pipeline_vbo);
|
|
}
|
|
}
|
|
D3D10SetVertexBuffer(d3d10->device, 0, d3d10->menu_pipeline_vbo, 2 * sizeof(float), 0);
|
|
draw->coords->vertices = ca->coords.vertices;
|
|
D3D10SetBlendState(d3d10->device, d3d10->blend_pipeline, NULL, D3D10_DEFAULT_SAMPLE_MASK);
|
|
break;
|
|
}
|
|
|
|
case VIDEO_SHADER_MENU_3:
|
|
case VIDEO_SHADER_MENU_4:
|
|
case VIDEO_SHADER_MENU_5:
|
|
case VIDEO_SHADER_MENU_6:
|
|
D3D10SetVertexBuffer(d3d10->device, 0, d3d10->frame.vbo, sizeof(d3d10_vertex_t), 0);
|
|
draw->coords->vertices = 4;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
|
|
d3d10->ubo_values.time += 0.01f;
|
|
|
|
{
|
|
void* mapped_ubo;
|
|
D3D10MapBuffer(d3d10->ubo, D3D10_MAP_WRITE_DISCARD, 0, (void**)&mapped_ubo);
|
|
*(d3d10_uniform_t*)mapped_ubo = d3d10->ubo_values;
|
|
D3D10UnmapBuffer(d3d10->ubo);
|
|
}
|
|
}
|
|
|
|
static void gfx_display_d3d10_restore_clear_color(void) {}
|
|
|
|
static void gfx_display_d3d10_clear_color(
|
|
gfx_display_ctx_clearcolor_t* clearcolor, void *data)
|
|
{
|
|
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
|
|
|
if (!d3d10 || !clearcolor)
|
|
return;
|
|
|
|
D3D10ClearRenderTargetView(d3d10->device,
|
|
d3d10->renderTargetView, (float*)clearcolor);
|
|
}
|
|
|
|
static bool gfx_display_d3d10_font_init_first(
|
|
void** font_handle,
|
|
void* video_data,
|
|
const char* font_path,
|
|
float menu_font_size,
|
|
bool is_threaded)
|
|
{
|
|
font_data_t** handle = (font_data_t**)font_handle;
|
|
font_data_t* new_handle = font_driver_init_first(
|
|
video_data, font_path, menu_font_size, true,
|
|
is_threaded, FONT_DRIVER_RENDER_D3D10_API);
|
|
if (!new_handle)
|
|
return false;
|
|
*handle = new_handle;
|
|
return true;
|
|
}
|
|
|
|
void gfx_display_d3d10_scissor_begin(void *data,
|
|
unsigned video_width, unsigned video_height,
|
|
int x, int y, unsigned width, unsigned height)
|
|
{
|
|
D3D10_RECT rect;
|
|
d3d10_video_t *d3d10 = (d3d10_video_t*)data;
|
|
|
|
if (!d3d10 || !width || !height)
|
|
return;
|
|
|
|
rect.left = x;
|
|
rect.top = y;
|
|
rect.right = width + x;
|
|
rect.bottom = height + y;
|
|
|
|
D3D10SetScissorRects(d3d10->device, 1, &rect);
|
|
}
|
|
|
|
void gfx_display_d3d10_scissor_end(void *data,
|
|
unsigned video_width, unsigned video_height)
|
|
{
|
|
D3D10_RECT rect;
|
|
d3d10_video_t *d3d10 = (d3d10_video_t*)data;
|
|
|
|
if (!d3d10)
|
|
return;
|
|
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = video_width;
|
|
rect.bottom = video_height;
|
|
|
|
D3D10SetScissorRects(d3d10->device, 1, &rect);
|
|
}
|
|
|
|
gfx_display_ctx_driver_t gfx_display_ctx_d3d10 = {
|
|
gfx_display_d3d10_draw,
|
|
gfx_display_d3d10_draw_pipeline,
|
|
gfx_display_d3d10_viewport,
|
|
gfx_display_d3d10_blend_begin,
|
|
gfx_display_d3d10_blend_end,
|
|
gfx_display_d3d10_restore_clear_color,
|
|
gfx_display_d3d10_clear_color,
|
|
gfx_display_d3d10_get_default_mvp,
|
|
gfx_display_d3d10_get_default_vertices,
|
|
gfx_display_d3d10_get_default_tex_coords,
|
|
gfx_display_d3d10_font_init_first,
|
|
GFX_VIDEO_DRIVER_DIRECT3D10,
|
|
"d3d10",
|
|
true,
|
|
gfx_display_d3d10_scissor_begin,
|
|
gfx_display_d3d10_scissor_end
|
|
};
|