Make Wii U software renderer support any res

This commit is contained in:
Clownacy 2020-04-21 18:45:58 +01:00
parent 31cd840297
commit a12e971509

View file

@ -8,7 +8,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <gx2/display.h>
#include <gx2/draw.h> #include <gx2/draw.h>
#include <gx2/registers.h>
#include <gx2/sampler.h> #include <gx2/sampler.h>
#include <gx2/texture.h> #include <gx2/texture.h>
#include <gx2r/buffer.h> #include <gx2r/buffer.h>
@ -21,6 +23,14 @@
#include "shaders/texture.gsh.h" #include "shaders/texture.gsh.h"
typedef struct Viewport
{
float x;
float y;
float width;
float height;
} Viewport;
static unsigned char *fake_framebuffer; static unsigned char *fake_framebuffer;
static size_t fake_framebuffer_width; static size_t fake_framebuffer_width;
@ -35,6 +45,29 @@ static GX2Sampler sampler;
static GX2Texture screen_texture; static GX2Texture screen_texture;
static Viewport tv_viewport;
static Viewport drc_viewport;
static void CalculateViewport(unsigned int actual_screen_width, unsigned int actual_screen_height, Viewport *viewport)
{
if ((float)actual_screen_width / (float)actual_screen_height > (float)fake_framebuffer_width / (float)fake_framebuffer_height)
{
viewport->y = 0.0f;
viewport->height = actual_screen_height;
viewport->width = fake_framebuffer_width * ((float)actual_screen_height / (float)fake_framebuffer_height);
viewport->x = (actual_screen_width - viewport->width) / 2;
}
else
{
viewport->x = 0.0f;
viewport->width = actual_screen_width;
viewport->height = fake_framebuffer_height * ((float)actual_screen_width / (float)fake_framebuffer_width);
viewport->y = (actual_screen_height - viewport->height) / 2;
}
}
bool WindowBackend_Software_CreateWindow(const char *window_title, int screen_width, int screen_height, bool fullscreen) bool WindowBackend_Software_CreateWindow(const char *window_title, int screen_width, int screen_height, bool fullscreen)
{ {
(void)window_title; (void)window_title;
@ -57,10 +90,10 @@ bool WindowBackend_Software_CreateWindow(const char *window_title, int screen_wi
// Initialise vertex position buffer // Initialise vertex position buffer
const float vertex_positions[4][2] = { const float vertex_positions[4][2] = {
{-640.0f / 854.0f, 1.0f}, {-1.0f, 1.0f},
{ 640.0f / 854.0f, 1.0f}, { 1.0f, 1.0f},
{ 640.0f / 854.0f, -1.0f}, { 1.0f, -1.0f},
{-640.0f / 854.0f, -1.0f} {-1.0f, -1.0f}
}; };
vertex_position_buffer.flags = (GX2RResourceFlags)(GX2R_RESOURCE_BIND_VERTEX_BUFFER | vertex_position_buffer.flags = (GX2RResourceFlags)(GX2R_RESOURCE_BIND_VERTEX_BUFFER |
@ -118,6 +151,29 @@ bool WindowBackend_Software_CreateWindow(const char *window_title, int screen_wi
GX2RSetAttributeBuffer(&vertex_position_buffer, 0, vertex_position_buffer.elemSize, 0); GX2RSetAttributeBuffer(&vertex_position_buffer, 0, vertex_position_buffer.elemSize, 0);
GX2RSetAttributeBuffer(&texture_coordinate_buffer, 1, texture_coordinate_buffer.elemSize, 0); GX2RSetAttributeBuffer(&texture_coordinate_buffer, 1, texture_coordinate_buffer.elemSize, 0);
// Calculate centred viewports
switch (GX2GetSystemTVScanMode())
{
case GX2_TV_SCAN_MODE_NONE: // lolwut
break;
case GX2_TV_SCAN_MODE_480I:
case GX2_TV_SCAN_MODE_480P:
CalculateViewport(854, 480, &tv_viewport);
break;
case GX2_TV_SCAN_MODE_720P:
CalculateViewport(1280, 720, &tv_viewport);
break;
case GX2_TV_SCAN_MODE_1080I:
case GX2_TV_SCAN_MODE_1080P:
CalculateViewport(1920, 1080, &tv_viewport);
break;
}
CalculateViewport(854, 480, &drc_viewport);
return true; return true;
} }
@ -162,10 +218,11 @@ ATTRIBUTE_HOT void WindowBackend_Software_Display(void)
unsigned char *framebuffer = (unsigned char*)GX2RLockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0); unsigned char *framebuffer = (unsigned char*)GX2RLockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0);
const unsigned char *in_pointer = fake_framebuffer; const unsigned char *in_pointer = fake_framebuffer;
unsigned char *out_pointer = framebuffer;
for (size_t y = 0; y < fake_framebuffer_height; ++y) for (size_t y = 0; y < fake_framebuffer_height; ++y)
{ {
unsigned char *out_pointer = &framebuffer[screen_texture.surface.pitch * 4 * y];
for (size_t x = 0; x < fake_framebuffer_width; ++x) for (size_t x = 0; x < fake_framebuffer_width; ++x)
{ {
*out_pointer++ = *in_pointer++; *out_pointer++ = *in_pointer++;
@ -181,6 +238,7 @@ ATTRIBUTE_HOT void WindowBackend_Software_Display(void)
// Draw to the TV // Draw to the TV
WHBGfxBeginRenderTV(); WHBGfxBeginRenderTV();
GX2SetViewport(tv_viewport.x, tv_viewport.y, tv_viewport.width, tv_viewport.height, 0.0f, 1.0f);
WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f); WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GX2SetFetchShader(&shader_group.fetchShader); GX2SetFetchShader(&shader_group.fetchShader);
GX2SetVertexShader(shader_group.vertexShader); GX2SetVertexShader(shader_group.vertexShader);
@ -190,6 +248,7 @@ ATTRIBUTE_HOT void WindowBackend_Software_Display(void)
// Draw to the gamepad // Draw to the gamepad
WHBGfxBeginRenderDRC(); WHBGfxBeginRenderDRC();
GX2SetViewport(drc_viewport.x, drc_viewport.y, drc_viewport.width, drc_viewport.height, 0.0f, 1.0f);
WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f); WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GX2SetFetchShader(&shader_group.fetchShader); GX2SetFetchShader(&shader_group.fetchShader);
GX2SetVertexShader(shader_group.vertexShader); GX2SetVertexShader(shader_group.vertexShader);