1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2014-2017 - Ali Bouhlel
3 * Copyright (C) 2011-2017 - Daniel De Matteis
4 *
5 * RetroArch is free software: you can redistribute it and/or modify it under the terms
6 * of the GNU General Public License as published by the Free Software Found-
7 * ation, either version 3 of the License, or (at your option) any later version.
8 *
9 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with RetroArch.
14 * If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <string.h>
18 #include <wiiu/os.h>
19 #include <wiiu/gx2.h>
20 #include <formats/image.h>
21 #include <file/file_path.h>
22 #include <string/stdstring.h>
23
24 #include "../../driver.h"
25 #include "../../configuration.h"
26 #include "../../verbosity.h"
27 #include "../../retroarch.h"
28
29 #ifdef HAVE_REWIND
30 #include "../../state_manager.h"
31 #endif
32
33 #ifdef HAVE_CONFIG_H
34 #include "../../config.h"
35 #endif
36
37 #ifdef HAVE_MENU
38 #include "../../menu/menu_driver.h"
39 #endif
40 #ifdef HAVE_GFX_WIDGETS
41 #include "../gfx_widgets.h"
42 #endif
43
44 #include "gfx/common/gx2_common.h"
45 #include "gfx/video_shader_parse.h"
46 #include "gfx/drivers_shader/slang_process.h"
47 #include "system/memory.h"
48
49 #include "wiiu_dbg.h"
50
51 #include "../font_driver.h"
52
53 /* Temporary workaround for gx2 not being able to poll flags during init */
54 static gfx_ctx_driver_t wiiu_fake_context;
55
56 static const wiiu_render_mode_t wiiu_render_mode_map[] =
57 {
58 {0}, /* GX2_TV_SCAN_MODE_NONE */
59 {854, 480, GX2_TV_RENDER_MODE_WIDE_480P}, /* GX2_TV_SCAN_MODE_576I */
60 {854, 480, GX2_TV_RENDER_MODE_WIDE_480P}, /* GX2_TV_SCAN_MODE_480I */
61 {854, 480, GX2_TV_RENDER_MODE_WIDE_480P}, /* GX2_TV_SCAN_MODE_480P */
62 {1280, 720, GX2_TV_RENDER_MODE_WIDE_720P}, /* GX2_TV_SCAN_MODE_720P */
63 {0}, /* GX2_TV_SCAN_MODE_unk */
64 {1920, 1080, GX2_TV_RENDER_MODE_WIDE_1080P}, /* GX2_TV_SCAN_MODE_1080I */
65 {1920, 1080, GX2_TV_RENDER_MODE_WIDE_1080P} /* GX2_TV_SCAN_MODE_1080P */
66 };
67
68 static bool wiiu_gfx_set_shader(void *data,
69 enum rarch_shader_type type, const char *path);
70
wiiu_set_tex_coords(frame_vertex_t * v,GX2Texture * texture,float u0,float v0,float u1,float v1,unsigned rotation)71 static void wiiu_set_tex_coords(frame_vertex_t *v,
72 GX2Texture *texture, float u0, float v0,
73 float u1, float v1,
74 unsigned rotation)
75 {
76 v[0].coord.u = u0 / texture->surface.width;
77 v[0].coord.v = v0 / texture->surface.height;
78 v[1].coord.u = u1 / texture->surface.width;
79 v[1].coord.v = v0 / texture->surface.height;
80 v[2].coord.u = u1 / texture->surface.width;
81 v[2].coord.v = v1 / texture->surface.height;
82 v[3].coord.u = u0 / texture->surface.width;
83 v[3].coord.v = v1 / texture->surface.height;
84 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, v, 4 * sizeof(*v));
85 }
86
wiiu_set_projection(wiiu_video_t * wiiu)87 static void wiiu_set_projection(wiiu_video_t *wiiu)
88 {
89 math_matrix_4x4 proj, rot;
90 matrix_4x4_ortho(proj, 0, 1, 1, 0, -1, 1);
91 matrix_4x4_rotate_z(rot, wiiu->rotation * -M_PI_2);
92 matrix_4x4_multiply((*wiiu->ubo_mvp), rot, proj);
93 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->ubo_mvp, sizeof(*wiiu->ubo_mvp));
94 }
95
wiiu_gfx_update_viewport(wiiu_video_t * wiiu)96 static void wiiu_gfx_update_viewport(wiiu_video_t *wiiu)
97 {
98 int x = 0;
99 int y = 0;
100 unsigned viewport_width = wiiu->color_buffer.surface.width;
101 unsigned viewport_height = wiiu->color_buffer.surface.height;
102 float device_aspect = (float)viewport_width / viewport_height;
103 settings_t *settings = config_get_ptr();
104 bool video_scale_integer = settings->bools.video_scale_integer;
105 unsigned video_aspect_ratio_idx = settings->uints.video_aspect_ratio_idx;
106
107 if (video_scale_integer)
108 {
109 video_viewport_get_scaled_integer(&wiiu->vp,
110 viewport_width, viewport_height,
111 video_driver_get_aspect_ratio(), wiiu->keep_aspect);
112 viewport_width = wiiu->vp.width;
113 viewport_height = wiiu->vp.height;
114 }
115 else if (wiiu->keep_aspect)
116 {
117 float desired_aspect = video_driver_get_aspect_ratio();
118
119 #if defined(HAVE_MENU)
120 if (video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
121 {
122 const struct video_viewport *custom = video_viewport_get_custom();
123
124 /* Vulkan has top-left origin viewport. */
125 x = custom->x;
126 y = custom->y;
127 viewport_width = custom->width;
128 viewport_height = custom->height;
129 }
130 else
131 #endif
132 {
133 float delta;
134
135 if (fabsf(device_aspect - desired_aspect) < 0.0001f)
136 {
137 /* If the aspect ratios of screen and desired aspect
138 * ratio are sufficiently equal (floating point stuff),
139 * assume they are actually equal.
140 */
141 }
142 else if (device_aspect > desired_aspect)
143 {
144 delta = (desired_aspect / device_aspect - 1.0f)
145 / 2.0f + 0.5f;
146 x = (int)roundf(viewport_width * (0.5f - delta));
147 viewport_width = (unsigned)roundf(2.0f * viewport_width * delta);
148 }
149 else
150 {
151 delta = (device_aspect / desired_aspect - 1.0f)
152 / 2.0f + 0.5f;
153 y = (int)roundf(viewport_height * (0.5f - delta));
154 viewport_height = (unsigned)roundf(2.0f * viewport_height * delta);
155 }
156 }
157
158 wiiu->vp.x = x;
159 wiiu->vp.y = y;
160 wiiu->vp.width = viewport_width;
161 wiiu->vp.height = viewport_height;
162 }
163 else
164 {
165 wiiu->vp.x = 0;
166 wiiu->vp.y = 0;
167 wiiu->vp.width = viewport_width;
168 wiiu->vp.height = viewport_height;
169 }
170
171 wiiu_set_projection(wiiu);
172 }
173
wiiu_gfx_set_aspect_ratio(void * data,unsigned aspect_ratio_idx)174 static void wiiu_gfx_set_aspect_ratio(void *data, unsigned aspect_ratio_idx)
175 {
176 wiiu_video_t *wiiu = (wiiu_video_t *)data;
177
178 if (!wiiu)
179 return;
180
181 wiiu->keep_aspect = true;
182 wiiu->should_resize = true;
183 }
184
185 static uint32_t wiiu_gfx_get_flags(void *data);
186
wiiu_gfx_init(const video_info_t * video,input_driver_t ** input,void ** input_data)187 static void *wiiu_gfx_init(const video_info_t *video,
188 input_driver_t **input, void **input_data)
189 {
190 unsigned i;
191 float refresh_rate = 60.0f / 1.001f;
192 u32 size = 0;
193 u32 tmp = 0;
194 void *wiiuinput = NULL;
195 wiiu_video_t *wiiu = (wiiu_video_t*)calloc(1, sizeof(*wiiu));
196 settings_t *settings = config_get_ptr();
197 const char *input_joypad_driver = settings->arrays.input_joypad_driver;
198
199 if (!wiiu)
200 return NULL;
201
202 *input = NULL;
203 *input_data = NULL;
204
205 if (input && input_data)
206 {
207 wiiuinput = input_driver_init_wrap(&input_wiiu, input_joypad_driver);
208 *input = wiiuinput ? &input_wiiu : NULL;
209 *input_data = wiiuinput;
210 }
211
212 /* video initialize */
213 wiiu->cmd_buffer = MEM2_alloc(0x400000, 0x40);
214 u32 init_attributes[] =
215 {
216 GX2_INIT_CMD_BUF_BASE, (u32)wiiu->cmd_buffer,
217 GX2_INIT_CMD_BUF_POOL_SIZE, 0x400000,
218 GX2_INIT_ARGC, 0,
219 GX2_INIT_ARGV, 0,
220 GX2_INIT_END
221 };
222 GX2Init(init_attributes);
223
224 wiiu->rgb32 = video->rgb32;
225
226 /* setup scanbuffers */
227 #if 0
228 wiiu->render_mode = wiiu_render_mode_map[GX2_TV_SCAN_MODE_480P];
229 #else
230 wiiu->render_mode = wiiu_render_mode_map[GX2GetSystemTVScanMode()];
231 #endif
232 GX2CalcTVSize(wiiu->render_mode.mode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8,
233 GX2_BUFFERING_MODE_DOUBLE, &size, &tmp);
234
235 wiiu->tv_scan_buffer = MEMBucket_alloc(size, GX2_SCAN_BUFFER_ALIGNMENT);
236 GX2Invalidate(GX2_INVALIDATE_MODE_CPU, wiiu->tv_scan_buffer, size);
237 GX2SetTVBuffer(wiiu->tv_scan_buffer, size, wiiu->render_mode.mode,
238 GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8,
239 GX2_BUFFERING_MODE_DOUBLE);
240
241 GX2CalcDRCSize(GX2_DRC_RENDER_MODE_SINGLE, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8,
242 GX2_BUFFERING_MODE_DOUBLE, &size,
243 &tmp);
244
245 wiiu->drc_scan_buffer = MEMBucket_alloc(size, GX2_SCAN_BUFFER_ALIGNMENT);
246 GX2Invalidate(GX2_INVALIDATE_MODE_CPU, wiiu->drc_scan_buffer, size);
247 GX2SetDRCBuffer(wiiu->drc_scan_buffer, size, GX2_DRC_RENDER_MODE_SINGLE,
248 GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8,
249 GX2_BUFFERING_MODE_DOUBLE);
250
251 memset(&wiiu->color_buffer, 0, sizeof(GX2ColorBuffer));
252
253 wiiu->color_buffer.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
254 wiiu->color_buffer.surface.width = wiiu->render_mode.width;
255 wiiu->color_buffer.surface.height = wiiu->render_mode.height;
256 wiiu->color_buffer.surface.depth = 1;
257 wiiu->color_buffer.surface.mipLevels = 1;
258 wiiu->color_buffer.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
259 wiiu->color_buffer.surface.use = GX2_SURFACE_USE_TEXTURE_COLOR_BUFFER_TV;
260 wiiu->color_buffer.viewNumSlices = 1;
261
262 GX2CalcSurfaceSizeAndAlignment(&wiiu->color_buffer.surface);
263 GX2InitColorBufferRegs(&wiiu->color_buffer);
264
265 wiiu->color_buffer.surface.image = MEM1_alloc(wiiu->color_buffer.surface.imageSize,
266 wiiu->color_buffer.surface.alignment);
267 GX2Invalidate(GX2_INVALIDATE_MODE_CPU, wiiu->color_buffer.surface.image,
268 wiiu->color_buffer.surface.imageSize);
269
270 wiiu->ctx_state = (GX2ContextState *)MEM2_alloc(sizeof(GX2ContextState),
271 GX2_CONTEXT_STATE_ALIGNMENT);
272 GX2SetupContextStateEx(wiiu->ctx_state, GX2_TRUE);
273
274 GX2SetContextState(wiiu->ctx_state);
275 GX2SetColorBuffer(&wiiu->color_buffer, GX2_RENDER_TARGET_0);
276 GX2SetViewport(0.0f, 0.0f, wiiu->color_buffer.surface.width, wiiu->color_buffer.surface.height,
277 0.0f, 1.0f);
278 GX2SetScissor(0, 0, wiiu->color_buffer.surface.width, wiiu->color_buffer.surface.height);
279 GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_FUNC_ALWAYS);
280 GX2SetColorControl(GX2_LOGIC_OP_COPY, 1, GX2_DISABLE, GX2_ENABLE);
281 GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA,
282 GX2_BLEND_COMBINE_MODE_ADD,
283 GX2_ENABLE, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA,
284 GX2_BLEND_COMBINE_MODE_ADD);
285 GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_DISABLE, GX2_DISABLE);
286
287 GX2InitShader(&frame_shader);
288 GX2InitShader(&tex_shader);
289 GX2InitShader(&sprite_shader);
290 GX2InitShader(&ribbon_simple_shader);
291 GX2InitShader(&ribbon_shader);
292 GX2InitShader(&bokeh_shader);
293 GX2InitShader(&snow_shader);
294 GX2InitShader(&snow_simple_shader);
295 GX2InitShader(&snowflake_shader);
296
297 GX2SetShader(&frame_shader);
298
299 wiiu->ubo_vp = MEM1_alloc(sizeof(*wiiu->ubo_vp), GX2_UNIFORM_BLOCK_ALIGNMENT);
300 wiiu->ubo_vp->width = wiiu->color_buffer.surface.width;
301 wiiu->ubo_vp->height = wiiu->color_buffer.surface.height;
302 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->ubo_vp, sizeof(*wiiu->ubo_vp));
303
304 wiiu->ubo_tex = MEM1_alloc(sizeof(*wiiu->ubo_tex), GX2_UNIFORM_BLOCK_ALIGNMENT);
305 wiiu->ubo_tex->width = 1.0;
306 wiiu->ubo_tex->height = 1.0;
307 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->ubo_tex, sizeof(*wiiu->ubo_tex));
308
309 wiiu->ubo_mvp = MEM1_alloc(sizeof(*wiiu->ubo_mvp), GX2_UNIFORM_BLOCK_ALIGNMENT);
310 wiiu_set_projection(wiiu);
311
312 wiiu->input_ring_buffer_size = GX2CalcGeometryShaderInputRingBufferSize(
313 sprite_shader.vs.ringItemSize);
314 wiiu->output_ring_buffer_size = GX2CalcGeometryShaderOutputRingBufferSize(
315 sprite_shader.gs.ringItemSize);
316 wiiu->input_ring_buffer = MEM1_alloc(wiiu->input_ring_buffer_size, 0x1000);
317 wiiu->output_ring_buffer = MEM1_alloc(wiiu->output_ring_buffer_size, 0x1000);
318
319 /* init menu texture */
320 memset(&wiiu->menu.texture, 0, sizeof(GX2Texture));
321 wiiu->menu.texture.surface.width = 512;
322 wiiu->menu.texture.surface.height = 512;
323 wiiu->menu.texture.surface.depth = 1;
324 wiiu->menu.texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
325 wiiu->menu.texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R4_G4_B4_A4;
326 wiiu->menu.texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
327 wiiu->menu.texture.viewNumSlices = 1;
328 /* Presumably an endian thing. RGBA, but swap R and G, then B and A. */
329 wiiu->menu.texture.compMap = GX2_COMP_SEL(_G, _R, _A, _B);
330 GX2CalcSurfaceSizeAndAlignment(&wiiu->menu.texture.surface);
331 GX2InitTextureRegs(&wiiu->menu.texture);
332
333 wiiu->menu.texture.surface.image = MEM2_alloc(wiiu->menu.texture.surface.imageSize,
334 wiiu->menu.texture.surface.alignment);
335
336 memset(wiiu->menu.texture.surface.image, 0x0, wiiu->menu.texture.surface.imageSize);
337 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->menu.texture.surface.image,
338 wiiu->menu.texture.surface.imageSize);
339
340 wiiu->v = MEM2_alloc(4 * sizeof(*wiiu->v), GX2_VERTEX_BUFFER_ALIGNMENT);
341
342 wiiu->v[0].pos.x = 0.0f;
343 wiiu->v[0].pos.y = 0.0f;
344 wiiu->v[1].pos.x = 1.0f;
345 wiiu->v[1].pos.y = 0.0f;
346 wiiu->v[2].pos.x = 1.0f;
347 wiiu->v[2].pos.y = 1.0f;
348 wiiu->v[3].pos.x = 0.0f;
349 wiiu->v[3].pos.y = 1.0f;
350 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, wiiu->v, 4 * sizeof(*wiiu->v));
351
352 wiiu_set_tex_coords(wiiu->v, &wiiu->texture, 0, 0,
353 wiiu->texture.surface.width, wiiu->texture.surface.height, wiiu->rotation);
354
355 GX2SetAttribBuffer(0, 4 * sizeof(*wiiu->v), sizeof(*wiiu->v), wiiu->v);
356
357 wiiu->menu.v = MEM2_alloc(4 * sizeof(*wiiu->menu.v), GX2_VERTEX_BUFFER_ALIGNMENT);
358 wiiu->menu.v->pos.x = 0.0f;
359 wiiu->menu.v->pos.y = 0.0f;
360 wiiu->menu.v->pos.width = wiiu->color_buffer.surface.width;
361 wiiu->menu.v->pos.height = wiiu->color_buffer.surface.height;
362 wiiu->menu.v->coord.u = 0.0f;
363 wiiu->menu.v->coord.v = 0.0f;
364 wiiu->menu.v->coord.width = 1.0f;
365 wiiu->menu.v->coord.height = 1.0f;
366 wiiu->menu.v->color = 0xFFFFFFFF;
367 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, wiiu->menu.v, 4 * sizeof(*wiiu->menu.v));
368
369 wiiu->vertex_cache.size = 0x1000;
370 wiiu->vertex_cache.current = 0;
371 wiiu->vertex_cache.v = MEM2_alloc(wiiu->vertex_cache.size
372 * sizeof(*wiiu->vertex_cache.v), GX2_VERTEX_BUFFER_ALIGNMENT);
373
374 wiiu->vertex_cache_tex.size = 0x1000;
375 wiiu->vertex_cache_tex.current = 0;
376 wiiu->vertex_cache_tex.v = MEM2_alloc(wiiu->vertex_cache_tex.size
377 * sizeof(*wiiu->vertex_cache_tex.v), GX2_VERTEX_BUFFER_ALIGNMENT);
378
379 /* Initialize samplers */
380 for (i = 0; i < RARCH_WRAP_MAX; i++)
381 {
382 switch (i)
383 {
384 case RARCH_WRAP_BORDER:
385 GX2InitSampler(&wiiu->sampler_nearest[i],
386 GX2_TEX_CLAMP_MODE_CLAMP_BORDER,
387 GX2_TEX_XY_FILTER_MODE_POINT);
388 GX2InitSampler(&wiiu->sampler_linear[i],
389 GX2_TEX_CLAMP_MODE_CLAMP_BORDER,
390 GX2_TEX_XY_FILTER_MODE_LINEAR);
391 break;
392
393 case RARCH_WRAP_EDGE:
394 GX2InitSampler(&wiiu->sampler_nearest[i],
395 GX2_TEX_CLAMP_MODE_CLAMP,
396 GX2_TEX_XY_FILTER_MODE_POINT);
397 GX2InitSampler(&wiiu->sampler_linear[i],
398 GX2_TEX_CLAMP_MODE_CLAMP,
399 GX2_TEX_XY_FILTER_MODE_LINEAR);
400 break;
401
402 case RARCH_WRAP_REPEAT:
403 GX2InitSampler(&wiiu->sampler_nearest[i],
404 GX2_TEX_CLAMP_MODE_WRAP,
405 GX2_TEX_XY_FILTER_MODE_POINT);
406 GX2InitSampler(&wiiu->sampler_linear[i],
407 GX2_TEX_CLAMP_MODE_WRAP,
408 GX2_TEX_XY_FILTER_MODE_LINEAR);
409 break;
410
411 case RARCH_WRAP_MIRRORED_REPEAT:
412 GX2InitSampler(&wiiu->sampler_nearest[i],
413 GX2_TEX_CLAMP_MODE_MIRROR,
414 GX2_TEX_XY_FILTER_MODE_POINT);
415 GX2InitSampler(&wiiu->sampler_linear[i],
416 GX2_TEX_CLAMP_MODE_MIRROR,
417 GX2_TEX_XY_FILTER_MODE_LINEAR);
418 break;
419 }
420 }
421
422 /* set Texture and Sampler */
423 GX2SetPixelTexture(&wiiu->texture, frame_shader.ps.samplerVars[0].location);
424 GX2SetPixelSampler(&wiiu->sampler_linear[RARCH_WRAP_DEFAULT],
425 frame_shader.ps.samplerVars[0].location);
426
427 /* clear leftover image */
428 GX2ClearColor(&wiiu->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f);
429 GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC);
430 GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV);
431
432 GX2SwapScanBuffers();
433 GX2Flush();
434 GX2WaitForVsync();
435
436 GX2SetTVEnable(GX2_ENABLE);
437 GX2SetDRCEnable(GX2_ENABLE);
438
439 wiiu->keep_aspect = true;
440 wiiu->should_resize = true;
441 wiiu->smooth = video->smooth;
442 wiiu->vsync = video->vsync;
443 GX2SetSwapInterval(!!video->vsync);
444
445 wiiu->vp.x = 0;
446 wiiu->vp.y = 0;
447 wiiu->vp.width = wiiu->render_mode.width;
448 wiiu->vp.height = wiiu->render_mode.height;
449 wiiu->vp.full_width = wiiu->render_mode.width;
450 wiiu->vp.full_height = wiiu->render_mode.height;
451 video_driver_set_size(wiiu->vp.width, wiiu->vp.height);
452
453 driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &refresh_rate);
454
455 font_driver_init_osd(wiiu,
456 video,
457 false,
458 video->is_threaded,
459 FONT_DRIVER_RENDER_WIIU);
460
461 {
462 enum rarch_shader_type type;
463 const char *shader_preset = NULL;
464
465 wiiu_fake_context.get_flags = wiiu_gfx_get_flags;
466
467 video_context_driver_set(&wiiu_fake_context);
468
469 shader_preset = retroarch_get_shader_preset();
470 type = video_shader_parse_type(shader_preset);
471 wiiu_gfx_set_shader(wiiu, type, shader_preset);
472 }
473
474 return wiiu;
475 }
476
477 #ifdef HAVE_OVERLAY
gx2_overlay_tex_geom(void * data,unsigned image,float x,float y,float w,float h)478 static void gx2_overlay_tex_geom(void *data, unsigned image,
479 float x, float y, float w, float h)
480 {
481 wiiu_video_t *gx2 = (wiiu_video_t *)data;
482 struct gx2_overlay_data *o = NULL;
483
484 if (gx2)
485 o = (struct gx2_overlay_data *)&gx2->overlay[image];
486
487 if (!o)
488 return;
489
490 o->v.coord.u = x;
491 o->v.coord.v = y;
492 o->v.coord.width = w;
493 o->v.coord.height = h;
494 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, &o->v, sizeof(o->v));
495 }
496
gx2_overlay_vertex_geom(void * data,unsigned image,float x,float y,float w,float h)497 static void gx2_overlay_vertex_geom(void *data, unsigned image,
498 float x, float y, float w, float h)
499 {
500 wiiu_video_t *gx2 = (wiiu_video_t *)data;
501 struct gx2_overlay_data *o = NULL;
502
503 if (gx2)
504 o = (struct gx2_overlay_data *)&gx2->overlay[image];
505
506 if (!o)
507 return;
508
509 o->v.pos.x = x * gx2->color_buffer.surface.width;
510 o->v.pos.y = y * gx2->color_buffer.surface.height;
511 o->v.pos.width = w * gx2->color_buffer.surface.width;
512 o->v.pos.height = h * gx2->color_buffer.surface.height;
513
514 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, &o->v, sizeof(o->v));
515 }
516
gx2_free_overlay(wiiu_video_t * gx2)517 static void gx2_free_overlay(wiiu_video_t *gx2)
518 {
519 unsigned i;
520
521 for (i = 0; i < gx2->overlays; i++)
522 MEM2_free(gx2->overlay[i].tex.surface.image);
523
524 free(gx2->overlay);
525 gx2->overlay = NULL;
526 gx2->overlays = 0;
527
528 }
529
gx2_overlay_load(void * data,const void * image_data,unsigned num_images)530 static bool gx2_overlay_load(void *data,
531 const void *image_data, unsigned num_images)
532 {
533 unsigned i, j;
534 wiiu_video_t *gx2 = (wiiu_video_t *)data;
535 const struct texture_image *images = (const struct texture_image *)image_data;
536
537 gx2_free_overlay(gx2);
538 gx2->overlay = (struct gx2_overlay_data *)calloc(num_images, sizeof(*gx2->overlay));
539
540 if (!gx2->overlay)
541 return false;
542
543 gx2->overlays = num_images;
544
545 for (i = 0; i < num_images; i++)
546 {
547 struct gx2_overlay_data *o = (struct gx2_overlay_data *)&gx2->overlay[i];
548
549 memset(&o->tex, 0, sizeof(GX2Texture));
550 o->tex.surface.width = images[i].width;
551 o->tex.surface.height = images[i].height;
552 o->tex.surface.depth = 1;
553 o->tex.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
554 o->tex.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
555 o->tex.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
556 o->tex.viewNumSlices = 1;
557 o->tex.compMap = GX2_COMP_SEL(_G, _B, _A, _R);
558 GX2CalcSurfaceSizeAndAlignment(&o->tex.surface);
559 GX2InitTextureRegs(&o->tex);
560
561 o->tex.surface.image = MEM2_alloc(o->tex.surface.imageSize,
562 o->tex.surface.alignment);
563
564 for (j = 0; (j < images[i].height) && (j < o->tex.surface.height); j++)
565 memcpy((uint32_t *)o->tex.surface.image + (j * o->tex.surface.pitch),
566 images[i].pixels + (j * images[i].width), images[i].width * sizeof(images[i].pixels));
567
568 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, o->tex.surface.image, o->tex.surface.imageSize);
569
570 /* Default. Stretch to whole screen. */
571 gx2_overlay_tex_geom(gx2, i, 0, 0, 1, 1);
572 gx2_overlay_vertex_geom(gx2, i, 0, 0, 1, 1);
573 gx2->overlay[i].alpha_mod = 1.0f;
574 gx2->overlay[i].v.color = 0xFFFFFFFF;
575
576 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, &o->v, sizeof(o->v));
577
578 }
579
580 return true;
581 }
582
gx2_overlay_enable(void * data,bool state)583 static void gx2_overlay_enable(void *data, bool state)
584 {
585
586 wiiu_video_t *gx2 = (wiiu_video_t *)data;
587 gx2->overlay_enable = state;
588 }
589
gx2_overlay_full_screen(void * data,bool enable)590 static void gx2_overlay_full_screen(void *data, bool enable)
591 {
592 wiiu_video_t *gx2 = (wiiu_video_t *)data;
593 gx2->overlay_full_screen = enable;
594 }
595
gx2_overlay_set_alpha(void * data,unsigned image,float mod)596 static void gx2_overlay_set_alpha(void *data, unsigned image, float mod)
597 {
598 wiiu_video_t *gx2 = (wiiu_video_t *)data;
599
600 if (gx2)
601 {
602 gx2->overlay[image].alpha_mod = mod;
603 gx2->overlay[image].v.color = COLOR_RGBA(0xFF, 0xFF, 0xFF, 0xFF * gx2->overlay[image].alpha_mod);
604 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, &gx2->overlay[image].v,
605 sizeof(gx2->overlay[image].v));
606 }
607 }
608
gx2_render_overlay(void * data)609 static void gx2_render_overlay(void *data)
610 {
611 unsigned i;
612
613 wiiu_video_t *gx2 = (wiiu_video_t *)data;
614
615 for (i = 0; i < gx2->overlays; i++)
616 {
617
618 GX2SetAttribBuffer(0, sizeof(gx2->overlay[i].v), sizeof(gx2->overlay[i].v), &gx2->overlay[i].v);
619
620 GX2SetPixelTexture(&gx2->overlay[i].tex, sprite_shader.ps.samplerVars[0].location);
621 GX2SetPixelSampler(&gx2->sampler_linear[RARCH_WRAP_EDGE], sprite_shader.ps.samplerVars[0].location);
622
623 GX2DrawEx(GX2_PRIMITIVE_MODE_POINTS, 1, 0, 1);
624
625 }
626
627 }
628
629 static const video_overlay_interface_t gx2_overlay_interface =
630 {
631 gx2_overlay_enable,
632 gx2_overlay_load,
633 gx2_overlay_tex_geom,
634 gx2_overlay_vertex_geom,
635 gx2_overlay_full_screen,
636 gx2_overlay_set_alpha,
637 };
638
gx2_get_overlay_interface(void * data,const video_overlay_interface_t ** iface)639 static void gx2_get_overlay_interface(void *data,
640 const video_overlay_interface_t **iface)
641 {
642 (void)data;
643 *iface = &gx2_overlay_interface;
644 }
645 #endif
646
wiiu_free_shader_preset(wiiu_video_t * wiiu)647 static void wiiu_free_shader_preset(wiiu_video_t *wiiu)
648 {
649 unsigned i;
650 if (!wiiu->shader_preset)
651 return;
652
653 for (i = 0; i < wiiu->shader_preset->passes; i++)
654 {
655 gfd_free(wiiu->pass[i].gfd);
656 MEM2_free(wiiu->pass[i].vs_ubos[0]);
657 MEM2_free(wiiu->pass[i].vs_ubos[1]);
658 MEM2_free(wiiu->pass[i].ps_ubos[0]);
659 MEM2_free(wiiu->pass[i].ps_ubos[1]);
660 if(wiiu->pass[i].mem1)
661 MEM1_free(wiiu->pass[i].texture.surface.image);
662 else
663 MEM2_free(wiiu->pass[i].texture.surface.image);
664 }
665
666 memset(wiiu->pass, 0, sizeof(wiiu->pass));
667
668 for (i = 0; i < wiiu->shader_preset->luts; i++)
669 {
670 MEM2_free(wiiu->luts[i].surface.image);
671 wiiu->luts[i].surface.image = NULL;
672 }
673
674 free(wiiu->shader_preset);
675 wiiu->shader_preset = NULL;
676 }
677
wiiu_gfx_free(void * data)678 static void wiiu_gfx_free(void *data)
679 {
680 wiiu_video_t *wiiu = (wiiu_video_t *) data;
681
682 if (!wiiu)
683 return;
684
685 /* clear leftover image */
686 GX2ClearColor(&wiiu->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f);
687 GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC);
688 GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV);
689
690 GX2SwapScanBuffers();
691 GX2Flush();
692 GX2DrawDone();
693 GX2WaitForVsync();
694 GX2Shutdown();
695
696 GX2SetTVEnable(GX2_DISABLE);
697 GX2SetDRCEnable(GX2_DISABLE);
698
699 GX2DestroyShader(&frame_shader);
700 GX2DestroyShader(&tex_shader);
701 GX2DestroyShader(&sprite_shader);
702 GX2DestroyShader(&ribbon_simple_shader);
703 GX2DestroyShader(&ribbon_shader);
704 GX2DestroyShader(&bokeh_shader);
705 GX2DestroyShader(&snow_shader);
706 GX2DestroyShader(&snow_simple_shader);
707 GX2DestroyShader(&snowflake_shader);
708
709 wiiu_free_shader_preset(wiiu);
710
711 #ifdef HAVE_OVERLAY
712 gx2_free_overlay(wiiu);
713 #endif
714
715 MEM2_free(wiiu->ctx_state);
716 MEM2_free(wiiu->cmd_buffer);
717 MEM2_free(wiiu->texture.surface.image);
718 MEM2_free(wiiu->menu.texture.surface.image);
719 MEM2_free(wiiu->v);
720 MEM2_free(wiiu->menu.v);
721 MEM2_free(wiiu->vertex_cache.v);
722 MEM2_free(wiiu->vertex_cache_tex.v);
723 MEM2_free(wiiu->menu_shader_vbo);
724 MEM2_free(wiiu->menu_shader_ubo);
725
726 MEM1_free(wiiu->color_buffer.surface.image);
727 MEM1_free(wiiu->ubo_vp);
728 MEM1_free(wiiu->ubo_tex);
729 MEM1_free(wiiu->ubo_mvp);
730 MEM1_free(wiiu->input_ring_buffer);
731 MEM1_free(wiiu->output_ring_buffer);
732
733 MEMBucket_free(wiiu->tv_scan_buffer);
734 MEMBucket_free(wiiu->drc_scan_buffer);
735
736 free(wiiu);
737 }
738
wiiu_init_frame_textures(wiiu_video_t * wiiu,unsigned width,unsigned height)739 static bool wiiu_init_frame_textures(wiiu_video_t *wiiu, unsigned width, unsigned height)
740 {
741 unsigned i;
742
743 MEM2_free(wiiu->texture.surface.image);
744
745 if (wiiu->shader_preset)
746 {
747 for (i = 0; i < wiiu->shader_preset->passes; i++)
748 {
749 if(wiiu->pass[i].mem1)
750 MEM1_free(wiiu->pass[i].texture.surface.image);
751 else
752 MEM2_free(wiiu->pass[i].texture.surface.image);
753
754 wiiu->pass[i].texture.surface.image = NULL;
755 }
756 }
757
758 /* Initialize frame texture */
759 memset(&wiiu->texture, 0, sizeof(GX2Texture));
760 wiiu->texture.surface.width = width;
761 wiiu->texture.surface.height = height;
762 wiiu->texture.surface.depth = 1;
763 wiiu->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
764 wiiu->texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
765 wiiu->texture.viewNumSlices = 1;
766
767 if (wiiu->rgb32)
768 {
769 wiiu->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
770 wiiu->texture.compMap = GX2_COMP_SEL(_G, _B, _A, _1);
771 }
772 else
773 {
774 wiiu->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R5_G6_B5;
775 wiiu->texture.compMap = GX2_COMP_SEL(_B, _G, _R, _1);
776 }
777
778 GX2CalcSurfaceSizeAndAlignment(&wiiu->texture.surface);
779 GX2InitTextureRegs(&wiiu->texture);
780
781 wiiu->texture.surface.image = MEM2_alloc(wiiu->texture.surface.imageSize,
782 wiiu->texture.surface.alignment);
783 memset(wiiu->texture.surface.image, 0x0, wiiu->texture.surface.imageSize);
784 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->texture.surface.image,
785 wiiu->texture.surface.imageSize);
786
787 if (wiiu->shader_preset)
788 {
789 for (i = 0; i < wiiu->shader_preset->passes; i++)
790 {
791 struct video_shader_pass *pass = &wiiu->shader_preset->pass[i];
792
793 switch (pass->fbo.type_x)
794 {
795 case RARCH_SCALE_INPUT:
796 width *= pass->fbo.scale_x;
797 break;
798
799 case RARCH_SCALE_VIEWPORT:
800 width = wiiu->vp.width * pass->fbo.scale_x;
801 break;
802
803 case RARCH_SCALE_ABSOLUTE:
804 width = pass->fbo.abs_x;
805 break;
806
807 default:
808 break;
809 }
810
811 switch (pass->fbo.type_y)
812 {
813 case RARCH_SCALE_INPUT:
814 height *= pass->fbo.scale_y;
815 break;
816
817 case RARCH_SCALE_VIEWPORT:
818 height = wiiu->vp.height * pass->fbo.scale_y;
819 break;
820
821 case RARCH_SCALE_ABSOLUTE:
822 height = pass->fbo.abs_y;
823 break;
824
825 default:
826 break;
827 }
828
829 if (!width)
830 width = wiiu->color_buffer.surface.width;
831
832 if (!height)
833 height = wiiu->color_buffer.surface.height;
834
835 memset(&wiiu->pass[i].texture, 0, sizeof(wiiu->pass[i].texture));
836 wiiu->pass[i].texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
837 wiiu->pass[i].texture.surface.width = width;
838 wiiu->pass[i].texture.surface.height = height;
839 wiiu->pass[i].texture.surface.depth = 1;
840 #if 0
841 wiiu->pass[i].texture.surface.mipLevels = 1;
842 #endif
843 wiiu->pass[i].texture.surface.format = pass->fbo.fp_fbo ?
844 GX2_SURFACE_FORMAT_FLOAT_R32_G32_B32_A32 :
845 pass->fbo.srgb_fbo ? GX2_SURFACE_FORMAT_SRGB_R8_G8_B8_A8 :
846 GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
847 wiiu->pass[i].texture.surface.use = (GX2_SURFACE_USE_TEXTURE |
848 GX2_SURFACE_USE_COLOR_BUFFER);
849 wiiu->pass[i].texture.viewNumSlices = 1;
850 wiiu->pass[i].texture.compMap = GX2_COMP_SEL(_R, _G, _B, _A);
851
852 GX2CalcSurfaceSizeAndAlignment(&wiiu->pass[i].texture.surface);
853 GX2InitTextureRegs(&wiiu->pass[i].texture);
854
855 if ((i != (wiiu->shader_preset->passes - 1)) || (width != wiiu->vp.width)
856 || (height != wiiu->vp.height))
857 {
858 wiiu->pass[i].mem1 = true;
859 wiiu->pass[i].texture.surface.image = MEM1_alloc(wiiu->pass[i].texture.surface.imageSize,
860 wiiu->pass[i].texture.surface.alignment);
861
862 if (!wiiu->pass[i].texture.surface.image)
863 {
864 printf("failed to allocate Render target memory from MEM1. trying MEM2.\n");
865 wiiu->pass[i].mem1 = false;
866 wiiu->pass[i].texture.surface.image = MEM2_alloc(wiiu->pass[i].texture.surface.imageSize,
867 wiiu->pass[i].texture.surface.alignment);
868
869 if (!wiiu->pass[i].texture.surface.image)
870 {
871 printf("failed to allocate Render target memory from MEM2. falling back to stock.\n");
872
873 wiiu_free_shader_preset(wiiu);
874 return false;
875 }
876 }
877
878 memset(wiiu->pass[i].texture.surface.image, 0x00, wiiu->pass[i].texture.surface.imageSize);
879 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->pass[i].texture.surface.image,
880 wiiu->pass[i].texture.surface.imageSize);
881 }
882
883 memset(&wiiu->pass[i].color_buffer, 0, sizeof(wiiu->pass[i].color_buffer));
884 wiiu->pass[i].color_buffer.surface = wiiu->pass[i].texture.surface;
885 GX2InitColorBufferRegs(&wiiu->pass[i].color_buffer);
886 }
887 }
888
889 return true;
890 }
891
wiiu_gfx_update_uniform_block(wiiu_video_t * wiiu,int pass,float * ubo,int id,int size,int uniformVarCount,GX2UniformVar * uniformVars,uint64_t frame_count,int32_t frame_direction)892 static void wiiu_gfx_update_uniform_block(wiiu_video_t *wiiu,
893 int pass, float *ubo, int id,
894 int size, int uniformVarCount, GX2UniformVar *uniformVars,
895 uint64_t frame_count, int32_t frame_direction)
896 {
897 unsigned i;
898 for (i = 0; i < uniformVarCount; i++)
899 {
900 if (uniformVars[i].block != id)
901 continue;
902
903 const char *id = strrchr(uniformVars[i].name, '.');
904
905 if (!id)
906 continue;
907
908 id++;
909
910 float *dst = ubo + uniformVars[i].offset;
911
912 if (string_is_equal(id, "OutputSize"))
913 {
914 ((GX2_vec4 *)dst)->x = wiiu->pass[pass].color_buffer.surface.width;
915 ((GX2_vec4 *)dst)->y = wiiu->pass[pass].color_buffer.surface.height;
916 ((GX2_vec4 *)dst)->z = 1.0f / wiiu->pass[pass].color_buffer.surface.width;
917 ((GX2_vec4 *)dst)->w = 1.0f / wiiu->pass[pass].color_buffer.surface.height;
918 continue;
919 }
920
921 if (string_is_equal(id, "FinalViewportSize"))
922 {
923 ((GX2_vec4 *)dst)->x = wiiu->vp.width;
924 ((GX2_vec4 *)dst)->y = wiiu->vp.height;
925 ((GX2_vec4 *)dst)->z = 1.0f / wiiu->vp.width;
926 ((GX2_vec4 *)dst)->w = 1.0f / wiiu->vp.height;
927 continue;
928 }
929
930 if (string_is_equal(id, "FrameCount"))
931 {
932 *dst = wiiu->shader_preset->pass[pass].frame_count_mod ?
933 frame_count % wiiu->shader_preset->pass[pass].frame_count_mod :
934 frame_count;
935 *(u32 *)dst = __builtin_bswap32(*(u32 *)dst);
936 continue;
937 }
938
939 if (string_is_equal(id, "FrameDirection"))
940 {
941 *dst = frame_direction;
942 *(u32 *)dst = __builtin_bswap32(*(u32 *)dst);
943 continue;
944 }
945
946 if (string_is_equal(id, "OriginalSize"))
947 {
948 ((GX2_vec4 *)dst)->x = wiiu->texture.surface.width;
949 ((GX2_vec4 *)dst)->y = wiiu->texture.surface.height;
950 ((GX2_vec4 *)dst)->z = 1.0f / wiiu->texture.surface.width;
951 ((GX2_vec4 *)dst)->w = 1.0f / wiiu->texture.surface.height;
952 continue;
953 }
954
955 if (string_is_equal(id, "SourceSize"))
956 {
957 GX2Surface *source = (pass > 0) ? &wiiu->pass[pass - 1].texture.surface : &wiiu->texture.surface;
958 ((GX2_vec4 *)dst)->x = source->width;
959 ((GX2_vec4 *)dst)->y = source->height;
960 ((GX2_vec4 *)dst)->z = 1.0f / source->width;
961 ((GX2_vec4 *)dst)->w = 1.0f / source->height;
962 continue;
963 }
964
965 if (!strncmp(id, "OriginalHistorySize",
966 STRLEN_CONST("OriginalHistorySize")))
967 {
968 unsigned index = strtoul(id + STRLEN_CONST("OriginalHistorySize"),
969 NULL, 0);
970 if(index > pass)
971 index = 0;
972
973 if(index)
974 index = pass - index;
975
976 GX2Surface *source = (index > 0) ? &wiiu->pass[index - 1].texture.surface : &wiiu->texture.surface;
977 ((GX2_vec4 *)dst)->x = source->width;
978 ((GX2_vec4 *)dst)->y = source->height;
979 ((GX2_vec4 *)dst)->z = 1.0f / source->width;
980 ((GX2_vec4 *)dst)->w = 1.0f / source->height;
981 continue;
982 }
983
984 if ((pass > 0 ) && !strncmp(id, "PassOutputSize",
985 STRLEN_CONST("PassOutputSize")))
986 {
987 unsigned index = strtoul(id + STRLEN_CONST("PassOutputSize"), NULL, 0);
988 if(index > pass - 1)
989 index = pass - 1;
990 GX2Surface *output = &wiiu->pass[index].texture.surface;
991 ((GX2_vec4 *)dst)->x = output->width;
992 ((GX2_vec4 *)dst)->y = output->height;
993 ((GX2_vec4 *)dst)->z = 1.0f / output->width;
994 ((GX2_vec4 *)dst)->w = 1.0f / output->height;
995 continue;
996 }
997
998 /* feedback not supported yet */
999 if (!strncmp(id, "PassFeedbackSize", STRLEN_CONST("PassFeedbackSize")))
1000 {
1001 unsigned index = strtoul(id + STRLEN_CONST("PassFeedbackSize"), NULL, 0);
1002 if(index > wiiu->shader_preset->passes - 1)
1003 index = wiiu->shader_preset->passes - 1;
1004 GX2Surface *output = &wiiu->pass[index].texture.surface;
1005 ((GX2_vec4 *)dst)->x = output->width;
1006 ((GX2_vec4 *)dst)->y = output->height;
1007 ((GX2_vec4 *)dst)->z = 1.0f / output->width;
1008 ((GX2_vec4 *)dst)->w = 1.0f / output->height;
1009 continue;
1010 }
1011
1012 for (int k = 0; k < wiiu->shader_preset->luts; k++)
1013 {
1014 size_t lut_id_size = strlen(wiiu->shader_preset->lut[k].id);
1015 if (!strncmp(id, wiiu->shader_preset->lut[k].id, lut_id_size)
1016 && !!strcmp(id + lut_id_size, "Size"))
1017 {
1018 GX2Surface *surface = &wiiu->luts[k].surface;
1019 ((GX2_vec4 *)dst)->x = surface->width;
1020 ((GX2_vec4 *)dst)->y = surface->height;
1021 ((GX2_vec4 *)dst)->z = 1.0f / surface->width;
1022 ((GX2_vec4 *)dst)->w = 1.0f / surface->height;
1023 }
1024 }
1025
1026 if (string_is_equal(id, "MVP"))
1027 {
1028 memcpy(dst, wiiu->ubo_mvp, sizeof(*wiiu->ubo_mvp));
1029 continue;
1030 }
1031
1032 for (int k = 0; k < wiiu->shader_preset->num_parameters; k++)
1033 {
1034 if (string_is_equal(id, wiiu->shader_preset->parameters[k].id))
1035 {
1036 *dst = wiiu->shader_preset->parameters[k].current;
1037 *(u32 *)dst = __builtin_bswap32(*(u32 *)dst);
1038 break;
1039 }
1040 }
1041
1042 }
1043
1044 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, ubo, size);
1045 }
1046
wiiu_gfx_frame(void * data,const void * frame,unsigned width,unsigned height,uint64_t frame_count,unsigned pitch,const char * msg,video_frame_info_t * video_info)1047 static bool wiiu_gfx_frame(void *data, const void *frame,
1048 unsigned width, unsigned height, uint64_t frame_count,
1049 unsigned pitch, const char *msg, video_frame_info_t *video_info)
1050 {
1051 uint32_t i;
1052 wiiu_video_t *wiiu = (wiiu_video_t *) data;
1053 #ifdef HAVE_MENU
1054 bool menu_is_alive = video_info->menu_is_alive;
1055 #endif
1056 #ifdef HAVE_GFX_WIDGETS
1057 bool widgets_active = video_info->widgets_active;
1058 #endif
1059 struct font_params *osd_params = (struct font_params*)
1060 &video_info->osd_stat_params;
1061 bool statistics_show = video_info->statistics_show;
1062
1063 if (wiiu->vsync)
1064 {
1065 uint32_t swap_count;
1066 uint32_t flip_count;
1067 OSTime last_flip;
1068 OSTime last_vsync;
1069
1070 GX2GetSwapStatus(&swap_count, &flip_count, &last_flip, &last_vsync);
1071
1072 if (wiiu->last_vsync >= last_vsync)
1073 {
1074 GX2WaitForVsync();
1075 wiiu->last_vsync = last_vsync + ms_to_ticks(17);
1076 }
1077 else
1078 wiiu->last_vsync = last_vsync;
1079 }
1080
1081 GX2WaitForFlip();
1082
1083 if (!width || !height)
1084 return true;
1085
1086 if (wiiu->should_resize)
1087 wiiu_gfx_update_viewport(wiiu);
1088
1089 GX2ClearColor(&wiiu->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f);
1090 /* can't call GX2ClearColor after GX2SetContextState for whatever reason */
1091 GX2SetContextState(wiiu->ctx_state);
1092
1093 if (frame)
1094 {
1095 if ((width != wiiu->texture.surface.width) ||
1096 (height != wiiu->texture.surface.height))
1097 wiiu_init_frame_textures(wiiu, width, height);
1098
1099 wiiu->width = width;
1100 wiiu->height = height;
1101
1102 if (wiiu->rgb32)
1103 {
1104 const uint32_t *src = frame;
1105 uint32_t *dst = (uint32_t *)wiiu->texture.surface.image;
1106
1107 for (i = 0; i < height; i++)
1108 {
1109 uint32_t j;
1110
1111 for (j = 0; j < width; j++)
1112 dst[j] = src[j];
1113
1114 dst += wiiu->texture.surface.pitch;
1115 src += pitch / 4;
1116 }
1117 }
1118 else
1119 {
1120 const uint16_t *src = frame;
1121 uint16_t *dst = (uint16_t *)wiiu->texture.surface.image;
1122
1123 for (i = 0; i < height; i++)
1124 {
1125 unsigned j;
1126
1127 for (j = 0; j < width; j++)
1128 dst[j] = __builtin_bswap16(src[j]);
1129
1130 dst += wiiu->texture.surface.pitch;
1131 src += pitch / 2;
1132 }
1133 }
1134
1135 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->texture.surface.image,
1136 wiiu->texture.surface.imageSize);
1137
1138 wiiu_set_tex_coords(wiiu->v, &wiiu->texture, 0, 0, width, height, wiiu->rotation);
1139 }
1140
1141 GX2SetShaderMode(GX2_SHADER_MODE_UNIFORM_BLOCK);
1142
1143 GX2SetFetchShader(&frame_shader.fs);
1144 GX2SetAttribBuffer(0, 4 * sizeof(*wiiu->v), sizeof(*wiiu->v), wiiu->v);
1145
1146 GX2Texture *texture = &wiiu->texture;
1147
1148 if (wiiu->shader_preset && !wiiu->pass[0].texture.surface.image)
1149 wiiu_init_frame_textures(wiiu, width, height);
1150
1151 if (wiiu->shader_preset)
1152 {
1153 unsigned i;
1154 #ifdef HAVE_REWIND
1155 int32_t frame_direction = state_manager_frame_is_reversed() ? -1 : 1;
1156 #else
1157 int32_t frame_direction = 1;
1158 #endif
1159
1160 for (i = 0; i < wiiu->shader_preset->passes; i++)
1161 {
1162 unsigned j;
1163 GX2SetVertexShader(wiiu->pass[i].gfd->vs);
1164
1165 for (j = 0; j < 2 && j < wiiu->pass[i].gfd->vs->uniformBlockCount; j++)
1166 {
1167 wiiu_gfx_update_uniform_block(wiiu, i, wiiu->pass[i].vs_ubos[j], j,
1168 wiiu->pass[i].gfd->vs->uniformBlocks[j].size,
1169 wiiu->pass[i].gfd->vs->uniformVarCount, wiiu->pass[i].gfd->vs->uniformVars,
1170 frame_count, frame_direction);
1171 GX2SetVertexUniformBlock(wiiu->pass[i].gfd->vs->uniformBlocks[j].offset,
1172 wiiu->pass[i].gfd->vs->uniformBlocks[j].size, wiiu->pass[i].vs_ubos[j]);
1173 }
1174
1175 GX2SetPixelShader(wiiu->pass[i].gfd->ps);
1176
1177 for (j = 0; j < 2 && j < wiiu->pass[i].gfd->ps->uniformBlockCount; j++)
1178 {
1179 wiiu_gfx_update_uniform_block(wiiu, i, wiiu->pass[i].ps_ubos[j], j,
1180 wiiu->pass[i].gfd->ps->uniformBlocks[j].size,
1181 wiiu->pass[i].gfd->ps->uniformVarCount, wiiu->pass[i].gfd->ps->uniformVars,
1182 frame_count, frame_direction);
1183 GX2SetPixelUniformBlock(wiiu->pass[i].gfd->ps->uniformBlocks[j].offset,
1184 wiiu->pass[i].gfd->ps->uniformBlocks[j].size, wiiu->pass[i].ps_ubos[j]);
1185 }
1186
1187 for (j = 0; j < wiiu->pass[i].gfd->ps->samplerVarCount; j++)
1188 {
1189 if (string_is_equal(wiiu->pass[i].gfd->ps->samplerVars[j].name, "Source"))
1190 {
1191 GX2SetPixelTexture(texture, wiiu->pass[i].gfd->ps->samplerVars[j].location);
1192 GX2SetPixelSampler(wiiu->shader_preset->pass[i].filter ?
1193 &wiiu->sampler_linear[wiiu->shader_preset->pass[i].wrap] :
1194 &wiiu->sampler_nearest[wiiu->shader_preset->pass[i].wrap],
1195 wiiu->pass[i].gfd->ps->samplerVars[j].location);
1196 continue;
1197 }
1198
1199 if (string_is_equal(wiiu->pass[i].gfd->ps->samplerVars[j].name, "Original"))
1200 {
1201 GX2SetPixelTexture(&wiiu->texture, wiiu->pass[i].gfd->ps->samplerVars[j].location);
1202 GX2SetPixelSampler(wiiu->shader_preset->pass[0].filter ?
1203 &wiiu->sampler_linear[wiiu->shader_preset->pass[0].wrap] :
1204 &wiiu->sampler_nearest[wiiu->shader_preset->pass[0].wrap],
1205 wiiu->pass[i].gfd->ps->samplerVars[j].location);
1206 continue;
1207 }
1208
1209 if (!strncmp(wiiu->pass[i].gfd->ps->samplerVars[j].name, "OriginalHistory", STRLEN_CONST("OriginalHistory")))
1210 {
1211 unsigned index = strtoul(wiiu->pass[i].gfd->ps->samplerVars[j].name + STRLEN_CONST("OriginalHistory"), NULL, 0);
1212 if(index > i)
1213 index = 0;
1214
1215 if(index)
1216 index = i - index;
1217
1218 GX2Texture *source = (index > 0) ? &wiiu->pass[index - 1].texture : &wiiu->texture;
1219 GX2SetPixelTexture(source, wiiu->pass[i].gfd->ps->samplerVars[j].location);
1220 GX2SetPixelSampler(wiiu->shader_preset->pass[index].filter ?
1221 &wiiu->sampler_linear[wiiu->shader_preset->pass[index].wrap] :
1222 &wiiu->sampler_nearest[wiiu->shader_preset->pass[index].wrap],
1223 wiiu->pass[i].gfd->ps->samplerVars[j].location);
1224 continue;
1225 }
1226
1227 if ((i > 0) && !strncmp(wiiu->pass[i].gfd->ps->samplerVars[j].name, "PassOutput", STRLEN_CONST("PassOutput")))
1228 {
1229 unsigned index = strtoul(wiiu->pass[i].gfd->ps->samplerVars[j].name + STRLEN_CONST("PassOutput"), NULL, 0);
1230 if(index > i - 1)
1231 index = i - 1;
1232 GX2SetPixelTexture(&wiiu->pass[index].texture, wiiu->pass[i].gfd->ps->samplerVars[j].location);
1233 GX2SetPixelSampler(wiiu->shader_preset->pass[index].filter ?
1234 &wiiu->sampler_linear[wiiu->shader_preset->pass[index].wrap] :
1235 &wiiu->sampler_nearest[wiiu->shader_preset->pass[index].wrap],
1236 wiiu->pass[i].gfd->ps->samplerVars[j].location);
1237 continue;
1238 }
1239
1240 /* feedback not supported yet */
1241 if (!strncmp(wiiu->pass[i].gfd->ps->samplerVars[j].name, "PassFeedback", STRLEN_CONST("PassFeedback")))
1242 {
1243 unsigned index = strtoul(wiiu->pass[i].gfd->ps->samplerVars[j].name + STRLEN_CONST("PassFeedback"), NULL, 0);
1244 if(index > wiiu->shader_preset->passes - 1)
1245 index = wiiu->shader_preset->passes - 1;
1246
1247 GX2SetPixelTexture(&wiiu->pass[index].texture, wiiu->pass[i].gfd->ps->samplerVars[j].location);
1248 GX2SetPixelSampler(wiiu->shader_preset->pass[i].filter ?
1249 &wiiu->sampler_linear[wiiu->shader_preset->pass[i].wrap] :
1250 &wiiu->sampler_nearest[wiiu->shader_preset->pass[i].wrap],
1251 wiiu->pass[i].gfd->ps->samplerVars[j].location);
1252 continue;
1253 }
1254
1255 for (int k = 0; k < wiiu->shader_preset->luts; k++)
1256 {
1257 if (wiiu->luts[k].surface.image
1258 && string_is_equal(wiiu->pass[i].gfd->ps->samplerVars[j].name, wiiu->shader_preset->lut[k].id))
1259 {
1260 GX2SetPixelTexture(&wiiu->luts[k], wiiu->pass[i].gfd->ps->samplerVars[j].location);
1261 GX2SetPixelSampler(wiiu->shader_preset->lut[k].filter ?
1262 &wiiu->sampler_linear[wiiu->shader_preset->lut[k].wrap] :
1263 &wiiu->sampler_nearest[wiiu->shader_preset->lut[k].wrap],
1264 wiiu->pass[i].gfd->ps->samplerVars[j].location);
1265 }
1266
1267 }
1268
1269 }
1270
1271 if (wiiu->pass[i].color_buffer.surface.image)
1272 {
1273 GX2SetColorBuffer(&wiiu->pass[i].color_buffer, GX2_RENDER_TARGET_0);
1274 GX2SetViewport(0.0f, 0.0f, wiiu->pass[i].color_buffer.surface.width,
1275 wiiu->pass[i].color_buffer.surface.height, 0.0f,
1276 1.0f);
1277 GX2SetScissor(0, 0, wiiu->pass[i].color_buffer.surface.width,
1278 wiiu->pass[i].color_buffer.surface.height);
1279 GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1);
1280
1281 GX2Invalidate(GX2_INVALIDATE_MODE_TEXTURE, wiiu->pass[i].texture.surface.image,
1282 wiiu->pass[i].texture.surface.imageSize);
1283 texture = &wiiu->pass[i].texture;
1284 }
1285 else
1286 {
1287 texture = NULL;
1288 break;
1289 }
1290 }
1291
1292 GX2SetColorBuffer(&wiiu->color_buffer, GX2_RENDER_TARGET_0);
1293 }
1294
1295 if (texture)
1296 {
1297 GX2SetVertexShader(&frame_shader.vs);
1298 GX2SetVertexUniformBlock(frame_shader.vs.uniformBlocks[0].offset,
1299 frame_shader.vs.uniformBlocks[0].size, wiiu->ubo_mvp);
1300
1301 GX2SetPixelShader(&frame_shader.ps);
1302 GX2SetPixelTexture(texture, frame_shader.ps.samplerVars[0].location);
1303 GX2SetPixelSampler(wiiu->smooth ? &wiiu->sampler_linear[RARCH_WRAP_DEFAULT] :
1304 &wiiu->sampler_nearest[RARCH_WRAP_DEFAULT],
1305 frame_shader.ps.samplerVars[0].location);
1306 }
1307
1308 GX2SetViewport(wiiu->vp.x, wiiu->vp.y, wiiu->vp.width, wiiu->vp.height, 0.0f, 1.0f);
1309 GX2SetScissor(0, 0, wiiu->color_buffer.surface.width, wiiu->color_buffer.surface.height);
1310 GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1);
1311
1312 GX2SetShaderMode(GX2_SHADER_MODE_GEOMETRY_SHADER);
1313 GX2SetShader(&sprite_shader);
1314 GX2SetGeometryShaderInputRingBuffer(wiiu->input_ring_buffer, wiiu->input_ring_buffer_size);
1315 GX2SetGeometryShaderOutputRingBuffer(wiiu->output_ring_buffer, wiiu->output_ring_buffer_size);
1316 GX2SetVertexUniformBlock(sprite_shader.vs.uniformBlocks[0].offset,
1317 sprite_shader.vs.uniformBlocks[0].size,
1318 wiiu->ubo_vp);
1319 GX2SetVertexUniformBlock(sprite_shader.vs.uniformBlocks[1].offset,
1320 sprite_shader.vs.uniformBlocks[1].size,
1321 wiiu->ubo_tex);
1322 GX2SetViewport(0.0f, 0.0f, wiiu->color_buffer.surface.width, wiiu->color_buffer.surface.height,
1323 0.0f, 1.0f);
1324
1325 #ifdef HAVE_OVERLAY
1326 if (wiiu->overlay_enable)
1327 gx2_render_overlay(wiiu);
1328 #endif
1329
1330 #ifdef HAVE_MENU
1331 if (wiiu->menu.enable)
1332 {
1333 GX2SetAttribBuffer(0, 4 * sizeof(*wiiu->menu.v), sizeof(*wiiu->menu.v), wiiu->menu.v);
1334
1335 GX2SetPixelTexture(&wiiu->menu.texture, sprite_shader.ps.samplerVars[0].location);
1336 GX2SetPixelSampler(wiiu->smooth ? &wiiu->sampler_linear[RARCH_WRAP_DEFAULT] :
1337 &wiiu->sampler_nearest[RARCH_WRAP_DEFAULT],
1338 sprite_shader.ps.samplerVars[0].location);
1339
1340 GX2DrawEx(GX2_PRIMITIVE_MODE_POINTS, 1, 0, 1);
1341 }
1342 #endif
1343
1344 wiiu->vertex_cache.current = 0;
1345 wiiu->vertex_cache_tex.current = 0;
1346 GX2SetAttribBuffer(0, wiiu->vertex_cache.size * sizeof(*wiiu->vertex_cache.v),
1347 sizeof(*wiiu->vertex_cache.v), wiiu->vertex_cache.v);
1348 GX2SetPixelSampler(&wiiu->sampler_linear[RARCH_WRAP_EDGE],
1349 sprite_shader.ps.samplerVars[0].location);
1350
1351 wiiu->render_msg_enabled = true;
1352
1353 #ifdef HAVE_MENU
1354 if (wiiu->menu.enable)
1355 menu_driver_frame(menu_is_alive, video_info);
1356 else
1357 #endif
1358 if (statistics_show)
1359 {
1360 if (osd_params)
1361 font_driver_render_msg(wiiu, video_info->stat_text,
1362 osd_params, NULL);
1363 }
1364
1365 #ifdef HAVE_GFX_WIDGETS
1366 if (widgets_active)
1367 gfx_widgets_frame(video_info);
1368 #endif
1369
1370 if (msg)
1371 font_driver_render_msg(wiiu, msg, NULL, NULL);
1372
1373 wiiu->render_msg_enabled = false;
1374
1375 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER,
1376 wiiu->vertex_cache.v,
1377 wiiu->vertex_cache.current
1378 * sizeof(*wiiu->vertex_cache.v));
1379 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER,
1380 wiiu->vertex_cache_tex.v,
1381 wiiu->vertex_cache_tex.current
1382 * sizeof(*wiiu->vertex_cache_tex.v));
1383
1384 if (wiiu->menu.enable)
1385 GX2DrawDone();
1386
1387 GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC);
1388 GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV);
1389
1390 GX2SwapScanBuffers();
1391 GX2Flush();
1392
1393 return true;
1394 }
1395
wiiu_gfx_set_nonblock_state(void * data,bool toggle,bool adaptive_vsync_enabled,unsigned swap_interval)1396 static void wiiu_gfx_set_nonblock_state(void *data, bool toggle,
1397 bool adaptive_vsync_enabled, unsigned swap_interval)
1398 {
1399 wiiu_video_t *wiiu = (wiiu_video_t *) data;
1400
1401 if (!wiiu)
1402 return;
1403
1404 wiiu->vsync = !toggle;
1405 GX2SetSwapInterval(!toggle); /* do we need this ? */
1406 }
1407
wiiu_gfx_alive(void * data)1408 static bool wiiu_gfx_alive(void *data)
1409 {
1410 (void)data;
1411 return true;
1412 }
1413
wiiu_gfx_focus(void * data)1414 static bool wiiu_gfx_focus(void *data)
1415 {
1416 (void)data;
1417 return true;
1418 }
1419
wiiu_gfx_suppress_screensaver(void * data,bool enable)1420 static bool wiiu_gfx_suppress_screensaver(void *data, bool enable)
1421 {
1422 (void)data;
1423 (void)enable;
1424 return false;
1425 }
1426
wiiu_gfx_set_shader(void * data,enum rarch_shader_type type,const char * path)1427 static bool wiiu_gfx_set_shader(void *data,
1428 enum rarch_shader_type type, const char *path)
1429 {
1430 unsigned i;
1431 wiiu_video_t *wiiu = (wiiu_video_t *)data;
1432
1433 if (!wiiu)
1434 return false;
1435
1436 GX2DrawDone();
1437 wiiu_free_shader_preset(wiiu);
1438
1439 if (string_is_empty(path))
1440 return true;
1441
1442 if (type != RARCH_SHADER_SLANG)
1443 {
1444 RARCH_WARN("[GX2] Only Slang shaders are supported. Falling back to stock.\n");
1445 return false;
1446 }
1447
1448 wiiu->shader_preset = calloc(1, sizeof(*wiiu->shader_preset));
1449
1450 if (!video_shader_load_preset_into_shader(path, wiiu->shader_preset))
1451 {
1452 free(wiiu->shader_preset);
1453 wiiu->shader_preset = NULL;
1454 return false;
1455 }
1456
1457 for (i = 0; i < wiiu->shader_preset->passes; i++)
1458 {
1459 unsigned j;
1460 char gfdpath[PATH_MAX_LENGTH];
1461 struct video_shader_pass *pass = &wiiu->shader_preset->pass[i];
1462
1463 strncpy(gfdpath, pass->source.path, PATH_MAX_LENGTH);
1464
1465 char *ptr = strrchr(gfdpath, '.');
1466
1467 if (!ptr)
1468 ptr = gfdpath + strlen(gfdpath);
1469
1470 *ptr++ = '.';
1471 *ptr++ = 'g';
1472 *ptr++ = 's';
1473 *ptr++ = 'h';
1474 *ptr++ = '\0';
1475
1476 wiiu->pass[i].gfd = gfd_open(gfdpath);
1477
1478 if (!wiiu->pass[i].gfd)
1479 {
1480 wiiu_free_shader_preset(wiiu);
1481 return false;
1482 }
1483
1484 for (j = 0; j < 2 && j < wiiu->pass[i].gfd->vs->uniformBlockCount; j++)
1485 {
1486 wiiu->pass[i].vs_ubos[j] = MEM2_alloc(wiiu->pass[i].gfd->vs->uniformBlocks[j].size,
1487 GX2_UNIFORM_BLOCK_ALIGNMENT);
1488 memset(wiiu->pass[i].vs_ubos[j], 0, wiiu->pass[i].gfd->vs->uniformBlocks[j].size);
1489 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->pass[i].vs_ubos[j],
1490 wiiu->pass[i].gfd->vs->uniformBlocks[j].size);
1491 }
1492
1493 for (j = 0; j < 2 && j < wiiu->pass[i].gfd->ps->uniformBlockCount; j++)
1494 {
1495 wiiu->pass[i].ps_ubos[j] = MEM2_alloc(wiiu->pass[i].gfd->ps->uniformBlocks[j].size,
1496 GX2_UNIFORM_BLOCK_ALIGNMENT);
1497 memset(wiiu->pass[i].ps_ubos[j], 0, wiiu->pass[i].gfd->ps->uniformBlocks[j].size);
1498 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->pass[i].ps_ubos[j],
1499 wiiu->pass[i].gfd->ps->uniformBlocks[j].size);
1500 }
1501 }
1502
1503 for (i = 0; i < wiiu->shader_preset->luts; i++)
1504 {
1505 struct texture_image image = {};
1506
1507 if (image_texture_load(&image, wiiu->shader_preset->lut[i].path))
1508 {
1509 unsigned j;
1510
1511 wiiu->luts[i].surface.width = image.width;
1512 wiiu->luts[i].surface.height = image.height;
1513 wiiu->luts[i].surface.depth = 1;
1514 wiiu->luts[i].surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
1515 wiiu->luts[i].surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
1516 wiiu->luts[i].viewNumSlices = 1;
1517
1518 wiiu->luts[i].surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
1519 wiiu->luts[i].compMap = GX2_COMP_SEL(_G, _B, _A, _R);
1520
1521 GX2CalcSurfaceSizeAndAlignment(&wiiu->luts[i].surface);
1522 GX2InitTextureRegs(&wiiu->luts[i]);
1523 wiiu->luts[i].surface.image = MEM2_alloc(wiiu->luts[i].surface.imageSize,
1524 wiiu->luts[i].surface.alignment);
1525
1526 for (j = 0; (j < image.height) && (j < wiiu->luts[i].surface.height); j++)
1527 memcpy((uint32_t *)wiiu->luts[i].surface.image + (j * wiiu->luts[i].surface.pitch),
1528 image.pixels + (j * image.width), image.width * sizeof(image.pixels));
1529
1530 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->luts[i].surface.image,
1531 wiiu->luts[i].surface.imageSize);
1532
1533 image_texture_free(&image);
1534 }
1535 }
1536
1537 return true;
1538 }
1539
wiiu_gfx_get_current_shader(void * data)1540 static struct video_shader *wiiu_gfx_get_current_shader(void *data)
1541 {
1542 wiiu_video_t *wiiu = (wiiu_video_t *)data;
1543
1544 if (!wiiu)
1545 return NULL;
1546
1547 return wiiu->shader_preset;
1548 }
1549
wiiu_gfx_set_rotation(void * data,unsigned rotation)1550 static void wiiu_gfx_set_rotation(void *data,
1551 unsigned rotation)
1552 {
1553 wiiu_video_t *wiiu = (wiiu_video_t *) data;
1554
1555 if (wiiu)
1556 {
1557 wiiu->rotation = rotation;
1558 wiiu_set_projection(wiiu);
1559 wiiu->should_resize = true;
1560 }
1561 }
1562
wiiu_gfx_viewport_info(void * data,struct video_viewport * vp)1563 static void wiiu_gfx_viewport_info(void *data,
1564 struct video_viewport *vp)
1565 {
1566 wiiu_video_t *wiiu = (wiiu_video_t *) data;
1567
1568 if (wiiu)
1569 *vp = wiiu->vp;
1570 }
1571
wiiu_gfx_load_texture(void * video_data,void * data,bool threaded,enum texture_filter_type filter_type)1572 static uintptr_t wiiu_gfx_load_texture(void *video_data, void *data,
1573 bool threaded, enum texture_filter_type filter_type)
1574 {
1575 uint32_t i;
1576 wiiu_video_t *wiiu = (wiiu_video_t *) video_data;
1577 struct texture_image *image = (struct texture_image *)data;
1578
1579 if (!wiiu)
1580 return 0;
1581
1582 GX2Texture *texture = calloc(1, sizeof(GX2Texture));
1583
1584 texture->surface.width = image->width;
1585 texture->surface.height = image->height;
1586 texture->surface.depth = 1;
1587 texture->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
1588 texture->surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
1589 texture->viewNumSlices = 1;
1590
1591 texture->surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
1592 texture->compMap = GX2_COMP_SEL(_G, _B, _A, _R);
1593
1594 GX2CalcSurfaceSizeAndAlignment(&texture->surface);
1595 GX2InitTextureRegs(texture);
1596 texture->surface.image = MEM2_alloc(texture->surface.imageSize, texture->surface.alignment);
1597
1598 for (i = 0; (i < image->height) && (i < texture->surface.height); i++)
1599 memcpy((uint32_t *)texture->surface.image + (i * texture->surface.pitch),
1600 image->pixels + (i * image->width), image->width * sizeof(image->pixels));
1601
1602 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, texture->surface.image, texture->surface.imageSize);
1603
1604 return (uintptr_t)texture;
1605 }
wiiu_gfx_unload_texture(void * data,bool threaded,uintptr_t handle)1606 static void wiiu_gfx_unload_texture(void *data,
1607 bool threaded, uintptr_t handle)
1608 {
1609 GX2Texture *texture = (GX2Texture *)handle;
1610
1611 if (!texture)
1612 return;
1613
1614 MEM2_free(texture->surface.image);
1615 free(texture);
1616 }
wiiu_gfx_set_filtering(void * data,unsigned index,bool smooth,bool ctx_scaling)1617 static void wiiu_gfx_set_filtering(void *data, unsigned index, bool smooth, bool ctx_scaling)
1618 {
1619 wiiu_video_t *wiiu = (wiiu_video_t *) data;
1620
1621 if (wiiu)
1622 wiiu->smooth = smooth;
1623 }
1624
wiiu_gfx_apply_state_changes(void * data)1625 static void wiiu_gfx_apply_state_changes(void *data)
1626 {
1627 wiiu_video_t *wiiu = (wiiu_video_t *)data;
1628
1629 if (wiiu)
1630 wiiu->should_resize = true;
1631 }
1632
wiiu_gfx_set_texture_frame(void * data,const void * frame,bool rgb32,unsigned width,unsigned height,float alpha)1633 static void wiiu_gfx_set_texture_frame(void *data, const void *frame, bool rgb32,
1634 unsigned width, unsigned height, float alpha)
1635 {
1636 uint32_t i;
1637 const uint16_t *src = NULL;
1638 uint16_t *dst = NULL;
1639 wiiu_video_t *wiiu = (wiiu_video_t *) data;
1640
1641 if (!wiiu)
1642 return;
1643
1644 if (!frame || !width || !height)
1645 return;
1646
1647 if (width > wiiu->menu.texture.surface.width)
1648 width = wiiu->menu.texture.surface.width;
1649
1650 if (height > wiiu->menu.texture.surface.height)
1651 height = wiiu->menu.texture.surface.height;
1652
1653 wiiu->menu.width = width;
1654 wiiu->menu.height = height;
1655
1656 src = frame;
1657 dst = (uint16_t *)wiiu->menu.texture.surface.image;
1658
1659 for (i = 0; i < height; i++)
1660 {
1661 memcpy(dst, src, width * sizeof(uint16_t));
1662 dst += wiiu->menu.texture.surface.pitch;
1663 src += width;
1664 }
1665
1666 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->menu.texture.surface.image,
1667 wiiu->menu.texture.surface.imageSize);
1668
1669 wiiu->menu.v->pos.x = wiiu->vp.x;
1670 wiiu->menu.v->pos.y = wiiu->vp.y;
1671 wiiu->menu.v->pos.width = wiiu->vp.width;
1672 wiiu->menu.v->pos.height = wiiu->vp.height;
1673 wiiu->menu.v->coord.u = 0.0f;
1674 wiiu->menu.v->coord.v = 0.0f;
1675 wiiu->menu.v->coord.width = (float)width / wiiu->menu.texture.surface.width;
1676 wiiu->menu.v->coord.height = (float)height / wiiu->menu.texture.surface.height;
1677 GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, wiiu->menu.v, 4 * sizeof(*wiiu->menu.v));
1678
1679 }
1680
wiiu_gfx_set_texture_enable(void * data,bool state,bool full_screen)1681 static void wiiu_gfx_set_texture_enable(void *data, bool state, bool full_screen)
1682 {
1683 (void) full_screen;
1684 wiiu_video_t *wiiu = (wiiu_video_t *) data;
1685
1686 if (wiiu)
1687 wiiu->menu.enable = state;
1688
1689 }
1690
wiiu_gfx_set_osd_msg(void * data,const char * msg,const void * params,void * font)1691 static void wiiu_gfx_set_osd_msg(void *data,
1692 const char *msg,
1693 const void *params, void *font)
1694 {
1695 wiiu_video_t *wiiu = (wiiu_video_t *)data;
1696
1697 if (wiiu)
1698 {
1699 if (wiiu->render_msg_enabled)
1700 font_driver_render_msg(wiiu, msg, params, font);
1701 }
1702 }
1703
wiiu_gfx_get_flags(void * data)1704 static uint32_t wiiu_gfx_get_flags(void *data)
1705 {
1706 uint32_t flags = 0;
1707
1708 BIT32_SET(flags, GFX_CTX_FLAGS_SCREENSHOTS_SUPPORTED);
1709 #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
1710 BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG);
1711 #endif
1712
1713 return flags;
1714 }
1715
1716 static const video_poke_interface_t wiiu_poke_interface = {
1717 wiiu_gfx_get_flags,
1718 wiiu_gfx_load_texture,
1719 wiiu_gfx_unload_texture,
1720 NULL, /* set_video_mode */
1721 NULL, /* get_refresh_rate */
1722 wiiu_gfx_set_filtering,
1723 NULL, /* get_video_output_size */
1724 NULL, /* get_video_output_prev */
1725 NULL, /* get_video_output_next */
1726 NULL, /* get_current_framebuffer */
1727 NULL, /* get_proc_address */
1728 wiiu_gfx_set_aspect_ratio,
1729 wiiu_gfx_apply_state_changes,
1730 wiiu_gfx_set_texture_frame,
1731 wiiu_gfx_set_texture_enable,
1732 wiiu_gfx_set_osd_msg,
1733 NULL, /* show_mouse */
1734 NULL, /* grab_mouse_toggle */
1735 wiiu_gfx_get_current_shader,
1736 NULL, /* get_current_software_framebuffer */
1737 NULL, /* get_hw_render_interface */
1738 };
1739
wiiu_gfx_get_poke_interface(void * data,const video_poke_interface_t ** iface)1740 static void wiiu_gfx_get_poke_interface(void *data,
1741 const video_poke_interface_t **iface)
1742 {
1743 (void)data;
1744 *iface = &wiiu_poke_interface;
1745 }
1746
1747 #ifdef HAVE_GFX_WIDGETS
wiiu_gfx_widgets_enabled(void * data)1748 static bool wiiu_gfx_widgets_enabled(void *data)
1749 {
1750 (void)data;
1751 return true;
1752 }
1753 #endif
1754
1755 video_driver_t video_wiiu =
1756 {
1757 wiiu_gfx_init,
1758 wiiu_gfx_frame,
1759 wiiu_gfx_set_nonblock_state,
1760 wiiu_gfx_alive,
1761 wiiu_gfx_focus,
1762 wiiu_gfx_suppress_screensaver,
1763 NULL, /* has_windowed */
1764 wiiu_gfx_set_shader,
1765 wiiu_gfx_free,
1766 "gx2",
1767 NULL, /* set_viewport */
1768 wiiu_gfx_set_rotation,
1769 wiiu_gfx_viewport_info,
1770 NULL, /* read_viewport */
1771 NULL, /* read_frame_raw */
1772 #ifdef HAVE_OVERLAY
1773 gx2_get_overlay_interface, /* overlay_interface */
1774 #endif
1775 #ifdef HAVE_VIDEO_LAYOUT
1776 NULL,
1777 #endif
1778 wiiu_gfx_get_poke_interface,
1779 NULL, /* wrap_type_to_enum */
1780 #ifdef HAVE_GFX_WIDGETS
1781 wiiu_gfx_widgets_enabled
1782 #endif
1783 };
1784