1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2014-2018 - Ali Bouhlel
3 *
4 * RetroArch is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with RetroArch.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #define CINTERFACE
17
18 #include <retro_miscellaneous.h>
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "../gfx_display.h"
25
26 #include "../../retroarch.h"
27 #include "../font_driver.h"
28 #include "../common/d3d11_common.h"
29
gfx_display_d3d11_blend_begin(void * data)30 static void gfx_display_d3d11_blend_begin(void *data)
31 {
32 d3d11_video_t* d3d11 = (d3d11_video_t*)data;
33 D3D11SetBlendState(d3d11->context,
34 d3d11->blend_enable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
35 }
36
gfx_display_d3d11_blend_end(void * data)37 static void gfx_display_d3d11_blend_end(void *data)
38 {
39 d3d11_video_t* d3d11 = (d3d11_video_t*)data;
40 D3D11SetBlendState(d3d11->context,
41 d3d11->blend_disable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
42 }
43
gfx_display_d3d11_draw(gfx_display_ctx_draw_t * draw,void * data,unsigned video_width,unsigned video_height)44 static void gfx_display_d3d11_draw(gfx_display_ctx_draw_t *draw,
45 void *data, unsigned video_width, unsigned video_height)
46 {
47 int vertex_count = 1;
48 d3d11_video_t *d3d11 = (d3d11_video_t*)data;
49
50 if (!d3d11 || !draw || !draw->texture)
51 return;
52
53 switch (draw->pipeline_id)
54 {
55 case VIDEO_SHADER_MENU:
56 case VIDEO_SHADER_MENU_2:
57 case VIDEO_SHADER_MENU_3:
58 case VIDEO_SHADER_MENU_4:
59 case VIDEO_SHADER_MENU_5:
60 case VIDEO_SHADER_MENU_6:
61 d3d11_set_shader(d3d11->context, &d3d11->shaders[draw->pipeline_id]);
62 D3D11Draw(d3d11->context, draw->coords->vertices, 0);
63
64 D3D11SetBlendState(d3d11->context, d3d11->blend_enable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
65 d3d11_set_shader(d3d11->context, &d3d11->sprites.shader);
66 D3D11SetVertexBuffer(d3d11->context, 0, d3d11->sprites.vbo, sizeof(d3d11_sprite_t), 0);
67 D3D11SetPrimitiveTopology(d3d11->context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
68 return;
69 }
70
71 if (draw->coords->vertex && draw->coords->tex_coord && draw->coords->color)
72 vertex_count = draw->coords->vertices;
73
74 if (!d3d11->sprites.enabled || vertex_count > d3d11->sprites.capacity)
75 return;
76
77 if (d3d11->sprites.offset + vertex_count > d3d11->sprites.capacity)
78 d3d11->sprites.offset = 0;
79
80 {
81 D3D11_MAPPED_SUBRESOURCE mapped_vbo;
82 d3d11_sprite_t* sprite = NULL;
83
84 D3D11MapBuffer(
85 d3d11->context, d3d11->sprites.vbo, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_vbo);
86
87 sprite = (d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset;
88
89 if (vertex_count == 1)
90 {
91 sprite->pos.x = draw->x / (float)d3d11->viewport.Width;
92 sprite->pos.y =
93 (d3d11->viewport.Height - draw->y - draw->height) / (float)d3d11->viewport.Height;
94 sprite->pos.w = draw->width / (float)d3d11->viewport.Width;
95 sprite->pos.h = draw->height / (float)d3d11->viewport.Height;
96
97 sprite->coords.u = 0.0f;
98 sprite->coords.v = 0.0f;
99 sprite->coords.w = 1.0f;
100 sprite->coords.h = 1.0f;
101
102 if (draw->scale_factor)
103 sprite->params.scaling = draw->scale_factor;
104 else
105 sprite->params.scaling = 1.0f;
106
107 sprite->params.rotation = draw->rotation;
108
109 sprite->colors[3] = DXGI_COLOR_RGBA(
110 0xFF * draw->coords->color[0], 0xFF * draw->coords->color[1],
111 0xFF * draw->coords->color[2], 0xFF * draw->coords->color[3]);
112 sprite->colors[2] = DXGI_COLOR_RGBA(
113 0xFF * draw->coords->color[4], 0xFF * draw->coords->color[5],
114 0xFF * draw->coords->color[6], 0xFF * draw->coords->color[7]);
115 sprite->colors[1] = DXGI_COLOR_RGBA(
116 0xFF * draw->coords->color[8], 0xFF * draw->coords->color[9],
117 0xFF * draw->coords->color[10], 0xFF * draw->coords->color[11]);
118 sprite->colors[0] = DXGI_COLOR_RGBA(
119 0xFF * draw->coords->color[12], 0xFF * draw->coords->color[13],
120 0xFF * draw->coords->color[14], 0xFF * draw->coords->color[15]);
121 }
122 else
123 {
124 int i;
125 const float* vertex = draw->coords->vertex;
126 const float* tex_coord = draw->coords->tex_coord;
127 const float* color = draw->coords->color;
128
129 for (i = 0; i < vertex_count; i++)
130 {
131 d3d11_vertex_t* v = (d3d11_vertex_t*)sprite;
132 v->position[0] = *vertex++;
133 v->position[1] = *vertex++;
134 v->texcoord[0] = *tex_coord++;
135 v->texcoord[1] = *tex_coord++;
136 v->color[0] = *color++;
137 v->color[1] = *color++;
138 v->color[2] = *color++;
139 v->color[3] = *color++;
140
141 sprite++;
142 }
143
144 d3d11_set_shader(d3d11->context, &d3d11->shaders[VIDEO_SHADER_STOCK_BLEND]);
145 D3D11SetPrimitiveTopology(d3d11->context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
146 }
147
148 D3D11UnmapBuffer(d3d11->context, d3d11->sprites.vbo, 0);
149 }
150
151 d3d11_set_texture_and_sampler(d3d11->context, 0, (d3d11_texture_t*)draw->texture);
152 D3D11Draw(d3d11->context, vertex_count, d3d11->sprites.offset);
153 d3d11->sprites.offset += vertex_count;
154
155 if (vertex_count > 1)
156 {
157 d3d11_set_shader(d3d11->context, &d3d11->sprites.shader);
158 D3D11SetPrimitiveTopology(d3d11->context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
159 }
160
161 return;
162 }
163
gfx_display_d3d11_draw_pipeline(gfx_display_ctx_draw_t * draw,gfx_display_t * p_disp,void * data,unsigned video_width,unsigned video_height)164 static void gfx_display_d3d11_draw_pipeline(gfx_display_ctx_draw_t *draw,
165 gfx_display_t *p_disp,
166 void *data, unsigned video_width, unsigned video_height)
167 {
168 d3d11_video_t *d3d11 = (d3d11_video_t*)data;
169
170 if (!d3d11 || !draw)
171 return;
172
173 switch (draw->pipeline_id)
174 {
175 case VIDEO_SHADER_MENU:
176 case VIDEO_SHADER_MENU_2:
177 {
178 video_coord_array_t* ca = &p_disp->dispca;
179
180 if (!d3d11->menu_pipeline_vbo)
181 {
182 D3D11_BUFFER_DESC desc = { 0 };
183 desc.Usage = D3D11_USAGE_IMMUTABLE;
184 desc.ByteWidth = ca->coords.vertices * 2 * sizeof(float);
185 desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
186
187 {
188 D3D11_SUBRESOURCE_DATA vertexData = { ca->coords.vertex };
189 D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->menu_pipeline_vbo);
190 }
191 }
192 D3D11SetVertexBuffer(d3d11->context, 0, d3d11->menu_pipeline_vbo, 2 * sizeof(float), 0);
193 draw->coords->vertices = ca->coords.vertices;
194 D3D11SetBlendState(d3d11->context, d3d11->blend_pipeline, NULL, D3D11_DEFAULT_SAMPLE_MASK);
195 break;
196 }
197
198 case VIDEO_SHADER_MENU_3:
199 case VIDEO_SHADER_MENU_4:
200 case VIDEO_SHADER_MENU_5:
201 case VIDEO_SHADER_MENU_6:
202 D3D11SetVertexBuffer(d3d11->context, 0, d3d11->frame.vbo, sizeof(d3d11_vertex_t), 0);
203 draw->coords->vertices = 4;
204 break;
205 default:
206 return;
207 }
208
209 D3D11SetPrimitiveTopology(d3d11->context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
210
211 d3d11->ubo_values.time += 0.01f;
212
213 {
214 D3D11_MAPPED_SUBRESOURCE mapped_ubo;
215 D3D11MapBuffer(d3d11->context, d3d11->ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
216 *(d3d11_uniform_t*)mapped_ubo.pData = d3d11->ubo_values;
217 D3D11UnmapBuffer(d3d11->context, d3d11->ubo, 0);
218 }
219 }
220
gfx_display_d3d11_font_init_first(void ** font_handle,void * video_data,const char * font_path,float menu_font_size,bool is_threaded)221 static bool gfx_display_d3d11_font_init_first(
222 void** font_handle,
223 void* video_data,
224 const char* font_path,
225 float menu_font_size,
226 bool is_threaded)
227 {
228 font_data_t** handle = (font_data_t**)font_handle;
229 font_data_t* new_handle = font_driver_init_first(
230 video_data, font_path, menu_font_size, true,
231 is_threaded, FONT_DRIVER_RENDER_D3D11_API);
232 if (!new_handle)
233 return false;
234 *handle = new_handle;
235 return true;
236 }
237
gfx_display_d3d11_scissor_begin(void * data,unsigned video_width,unsigned video_height,int x,int y,unsigned width,unsigned height)238 void gfx_display_d3d11_scissor_begin(void *data,
239 unsigned video_width,
240 unsigned video_height,
241 int x, int y, unsigned width, unsigned height)
242 {
243 D3D11_RECT rect;
244 d3d11_video_t *d3d11 = (d3d11_video_t*)data;
245
246 if (!d3d11 || !width || !height)
247 return;
248
249 rect.left = x;
250 rect.top = y;
251 rect.right = width + x;
252 rect.bottom = height + y;
253
254 D3D11SetScissorRects(d3d11->context, 1, &rect);
255 }
256
gfx_display_d3d11_scissor_end(void * data,unsigned video_width,unsigned video_height)257 void gfx_display_d3d11_scissor_end(void *data,
258 unsigned video_width,
259 unsigned video_height)
260 {
261 D3D11_RECT rect;
262 d3d11_video_t *d3d11 = (d3d11_video_t*)data;
263
264 if (!d3d11)
265 return;
266
267 rect.left = 0;
268 rect.top = 0;
269 rect.right = video_width;
270 rect.bottom = video_height;
271
272 D3D11SetScissorRects(d3d11->context, 1, &rect);
273 }
274
275 gfx_display_ctx_driver_t gfx_display_ctx_d3d11 = {
276 gfx_display_d3d11_draw,
277 gfx_display_d3d11_draw_pipeline,
278 gfx_display_d3d11_blend_begin,
279 gfx_display_d3d11_blend_end,
280 NULL, /* get_default_mvp */
281 NULL, /* get_default_vertices */
282 NULL, /* get_default_tex_coords */
283 gfx_display_d3d11_font_init_first,
284 GFX_VIDEO_DRIVER_DIRECT3D11,
285 "d3d11",
286 true,
287 gfx_display_d3d11_scissor_begin,
288 gfx_display_d3d11_scissor_end
289 };
290