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