ref: a12e971509617b9ac8e1a8bbfbd21611eadc7179
parent: 31cd840297b58142ba8a87ac7954c0eef5457bef
author: Clownacy <Clownacy@users.noreply.github.com>
date: Tue Apr 21 14:45:58 EDT 2020
Make Wii U software renderer support any res
--- a/src/Backends/WiiU/Window-Software-Polygon.cpp
+++ b/src/Backends/WiiU/Window-Software-Polygon.cpp
@@ -8,7 +8,9 @@
#include <stdlib.h>
#include <string.h>
+#include <gx2/display.h>
#include <gx2/draw.h>
+#include <gx2/registers.h>
#include <gx2/sampler.h>
#include <gx2/texture.h>
#include <gx2r/buffer.h>
@@ -21,6 +23,14 @@
#include "shaders/texture.gsh.h"
+typedef struct Viewport
+{
+ float x;
+ float y;
+ float width;
+ float height;
+} Viewport;
+
static unsigned char *fake_framebuffer;
static size_t fake_framebuffer_width;
@@ -35,6 +45,29 @@
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)
{
(void)window_title;
@@ -57,10 +90,10 @@
// Initialise vertex position buffer
const float vertex_positions[4][2] = {
- {-640.0f / 854.0f, 1.0f},
- { 640.0f / 854.0f, 1.0f},
- { 640.0f / 854.0f, -1.0f},
- {-640.0f / 854.0f, -1.0f}
+ {-1.0f, 1.0f},
+ { 1.0f, 1.0f},
+ { 1.0f, -1.0f},
+ {-1.0f, -1.0f}
};
vertex_position_buffer.flags = (GX2RResourceFlags)(GX2R_RESOURCE_BIND_VERTEX_BUFFER |
@@ -118,6 +151,29 @@
GX2RSetAttributeBuffer(&vertex_position_buffer, 0, vertex_position_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;
}
@@ -162,10 +218,11 @@
unsigned char *framebuffer = (unsigned char*)GX2RLockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0);
const unsigned char *in_pointer = fake_framebuffer;
- unsigned char *out_pointer = framebuffer;
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)
{
*out_pointer++ = *in_pointer++;
@@ -181,6 +238,7 @@
// Draw to the TV
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);
GX2SetFetchShader(&shader_group.fetchShader);
GX2SetVertexShader(shader_group.vertexShader);
@@ -190,6 +248,7 @@
// Draw to the gamepad
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);
GX2SetFetchShader(&shader_group.fetchShader);
GX2SetVertexShader(shader_group.vertexShader);