From 8945ca8275014adfee17725f6abc49816d3c1b35 Mon Sep 17 00:00:00 2001 From: Clownacy Date: Thu, 23 Apr 2020 21:06:36 +0100 Subject: [PATCH] Remove old Wii U window backend Made redundant by hardware-accelerated one. --- CMakeLists.txt | 2 +- src/Backends/WiiU/Window-Software-Polygon.cpp | 269 ---------------- src/Backends/WiiU/Window-Software.cpp | 297 +++++++++++++----- 3 files changed, 212 insertions(+), 356 deletions(-) delete mode 100644 src/Backends/WiiU/Window-Software-Polygon.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e3b404a..c6e39fdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,7 +391,7 @@ elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "Software") target_sources(CSE2 PRIVATE "src/Backends/GLFW3/Window-Software.cpp") elseif(BACKEND_PLATFORM MATCHES "WiiU" AND BACKEND_RENDERER MATCHES "WiiU") elseif(BACKEND_PLATFORM MATCHES "WiiU" AND BACKEND_RENDERER MATCHES "Software") - target_sources(CSE2 PRIVATE "src/Backends/WiiU/Window-Software-Polygon.cpp") + target_sources(CSE2 PRIVATE "src/Backends/WiiU/Window-Software.cpp") elseif(BACKEND_PLATFORM MATCHES "Null" AND BACKEND_RENDERER MATCHES "Software") target_sources(CSE2 PRIVATE "src/Backends/Null/Window-Software.cpp") else() diff --git a/src/Backends/WiiU/Window-Software-Polygon.cpp b/src/Backends/WiiU/Window-Software-Polygon.cpp deleted file mode 100644 index 7f4135fc..00000000 --- a/src/Backends/WiiU/Window-Software-Polygon.cpp +++ /dev/null @@ -1,269 +0,0 @@ -// Sexy new backend that bounces the software-rendered frame to the GPU, -// eliminating V-tearing, and gaining support for rendering to the TV for -// free! - -#include "../Window-Software.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../Attributes.h" - -#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; -static size_t fake_framebuffer_height; - -static WHBGfxShaderGroup shader_group; - -static GX2RBuffer vertex_position_buffer; -static GX2RBuffer texture_coordinate_buffer; - -static GX2Sampler sampler; - -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; - (void)fullscreen; - - fake_framebuffer_width = screen_width; - fake_framebuffer_height = screen_height; - - fake_framebuffer = (unsigned char*)malloc(fake_framebuffer_width * fake_framebuffer_height * 3); - - if (fake_framebuffer != NULL) - { - WHBGfxInit(); - - if (WHBGfxLoadGFDShaderGroup(&shader_group, 0, rtexture)) - { - WHBGfxInitShaderAttribute(&shader_group, "input_vertex_coordinates", 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32); - WHBGfxInitShaderAttribute(&shader_group, "input_texture_coordinates", 1, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32); - WHBGfxInitFetchShader(&shader_group); - - // Initialise vertex position buffer - const float vertex_positions[4][2] = { - {-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 | - GX2R_RESOURCE_USAGE_CPU_READ | - GX2R_RESOURCE_USAGE_CPU_WRITE | - GX2R_RESOURCE_USAGE_GPU_READ); - vertex_position_buffer.elemSize = sizeof(vertex_positions[0]); - vertex_position_buffer.elemCount = sizeof(vertex_positions) / sizeof(vertex_positions[0]); - GX2RCreateBuffer(&vertex_position_buffer); - memcpy(GX2RLockBufferEx(&vertex_position_buffer, (GX2RResourceFlags)0), vertex_positions, sizeof(vertex_positions)); - GX2RUnlockBufferEx(&vertex_position_buffer, (GX2RResourceFlags)0); - - // Initialise texture coordinate buffer - const float texture_coordinates[4][2] = { - {0.0f, 0.0f}, - {1.0f, 0.0f}, - {1.0f, 1.0f}, - {0.0f, 1.0f} - }; - - texture_coordinate_buffer.flags = (GX2RResourceFlags)(GX2R_RESOURCE_BIND_VERTEX_BUFFER | - GX2R_RESOURCE_USAGE_CPU_READ | - GX2R_RESOURCE_USAGE_CPU_WRITE | - GX2R_RESOURCE_USAGE_GPU_READ); - texture_coordinate_buffer.elemSize = sizeof(texture_coordinates[0]); - texture_coordinate_buffer.elemCount = sizeof(texture_coordinates) / sizeof(texture_coordinates[0]); - GX2RCreateBuffer(&texture_coordinate_buffer); - memcpy(GX2RLockBufferEx(&texture_coordinate_buffer, (GX2RResourceFlags)0), texture_coordinates, sizeof(texture_coordinates)); - GX2RUnlockBufferEx(&texture_coordinate_buffer, (GX2RResourceFlags)0); - - // Initialise sampler - GX2InitSampler(&sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_POINT); - - // Initialise screen texture - screen_texture.surface.width = fake_framebuffer_width; - screen_texture.surface.height = fake_framebuffer_height; - screen_texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; - screen_texture.surface.depth = 1; - screen_texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; - screen_texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; - screen_texture.surface.mipLevels = 1; - screen_texture.viewNumMips = 1; - screen_texture.viewNumSlices = 1; - screen_texture.compMap = 0x00010203; - GX2CalcSurfaceSizeAndAlignment(&screen_texture.surface); - GX2InitTextureRegs(&screen_texture); - - if (GX2RCreateSurface(&screen_texture.surface, (GX2RResourceFlags)(GX2R_RESOURCE_BIND_TEXTURE | GX2R_RESOURCE_BIND_COLOR_BUFFER | - GX2R_RESOURCE_USAGE_CPU_WRITE | GX2R_RESOURCE_USAGE_CPU_READ | - GX2R_RESOURCE_USAGE_GPU_WRITE | GX2R_RESOURCE_USAGE_GPU_READ))) - { - // Do some binding - GX2SetPixelSampler(&sampler, shader_group.pixelShader->samplerVars[0].location); - GX2SetPixelTexture(&screen_texture, shader_group.pixelShader->samplerVars[0].location); - 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: - case 4: // Why the hell doesn't WUT have an enum for this? It always returns this value for me! - 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; - } - - GX2RDestroyBufferEx(&texture_coordinate_buffer, (GX2RResourceFlags)0); - GX2RDestroyBufferEx(&vertex_position_buffer, (GX2RResourceFlags)0); - - WHBGfxFreeShaderGroup(&shader_group); - } - - WHBGfxShutdown(); - - free(fake_framebuffer); - } - - return false; -} - -void WindowBackend_Software_DestroyWindow(void) -{ - GX2RDestroySurfaceEx(&screen_texture.surface, (GX2RResourceFlags)0); - - GX2RDestroyBufferEx(&texture_coordinate_buffer, (GX2RResourceFlags)0); - GX2RDestroyBufferEx(&vertex_position_buffer, (GX2RResourceFlags)0); - - WHBGfxFreeShaderGroup(&shader_group); - - WHBGfxShutdown(); - - free(fake_framebuffer); -} - -unsigned char* WindowBackend_Software_GetFramebuffer(size_t *pitch) -{ - *pitch = fake_framebuffer_width * 3; - - return fake_framebuffer; -} - -ATTRIBUTE_HOT void WindowBackend_Software_Display(void) -{ - // Convert frame from RGB24 to RGBA32, and upload it to the GPU texture - unsigned char *framebuffer = (unsigned char*)GX2RLockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0); - - const unsigned char *in_pointer = fake_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++; - *out_pointer++ = *in_pointer++; - *out_pointer++ = *in_pointer++; - *out_pointer++ = 0; - } - } - - GX2RUnlockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0); - - WHBGfxBeginRender(); - - // 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); - GX2SetPixelShader(shader_group.pixelShader); - GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); - WHBGfxFinishRenderTV(); - - // 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); - GX2SetPixelShader(shader_group.pixelShader); - GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); - WHBGfxFinishRenderDRC(); - - WHBGfxFinishRender(); -} - -void WindowBackend_Software_HandleWindowResize(unsigned int width, unsigned int height) -{ - (void)width; - (void)height; - - // The window doesn't resize on the Wii U -} diff --git a/src/Backends/WiiU/Window-Software.cpp b/src/Backends/WiiU/Window-Software.cpp index f2190ab7..7f4135fc 100644 --- a/src/Backends/WiiU/Window-Software.cpp +++ b/src/Backends/WiiU/Window-Software.cpp @@ -1,144 +1,269 @@ +// Sexy new backend that bounces the software-rendered frame to the GPU, +// eliminating V-tearing, and gaining support for rendering to the TV for +// free! + #include "../Window-Software.h" +#include #include #include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../../Attributes.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 *tv_framebuffer; -static unsigned char *drc_framebuffer; +static size_t fake_framebuffer_width; +static size_t fake_framebuffer_height; -static size_t framebuffer_width; -static size_t framebuffer_height; +static WHBGfxShaderGroup shader_group; -//static uint32_t tv_buffer_size; -static uint32_t drc_buffer_size; +static GX2RBuffer vertex_position_buffer; +static GX2RBuffer texture_coordinate_buffer; + +static GX2Sampler sampler; + +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; (void)fullscreen; - framebuffer_width = screen_width; - framebuffer_height = screen_height; + fake_framebuffer_width = screen_width; + fake_framebuffer_height = screen_height; - OSScreenInit(); + fake_framebuffer = (unsigned char*)malloc(fake_framebuffer_width * fake_framebuffer_height * 3); - OSScreenEnableEx(SCREEN_TV, FALSE); - OSScreenEnableEx(SCREEN_DRC, TRUE); + if (fake_framebuffer != NULL) + { + WHBGfxInit(); -// tv_buffer_size = OSScreenGetBufferSizeEx(SCREEN_TV); - drc_buffer_size = OSScreenGetBufferSizeEx(SCREEN_DRC); + if (WHBGfxLoadGFDShaderGroup(&shader_group, 0, rtexture)) + { + WHBGfxInitShaderAttribute(&shader_group, "input_vertex_coordinates", 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32); + WHBGfxInitShaderAttribute(&shader_group, "input_texture_coordinates", 1, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32); + WHBGfxInitFetchShader(&shader_group); -// tv_framebuffer = (unsigned char*)aligned_alloc(0x100, tv_buffer_size); // C11 fun - drc_framebuffer = (unsigned char*)aligned_alloc(0x100, drc_buffer_size); // C11 fun + // Initialise vertex position buffer + const float vertex_positions[4][2] = { + {-1.0f, 1.0f}, + { 1.0f, 1.0f}, + { 1.0f, -1.0f}, + {-1.0f, -1.0f} + }; -// OSScreenSetBufferEx(SCREEN_TV, tv_framebuffer); - OSScreenSetBufferEx(SCREEN_DRC, drc_framebuffer); + vertex_position_buffer.flags = (GX2RResourceFlags)(GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_READ | + GX2R_RESOURCE_USAGE_CPU_WRITE | + GX2R_RESOURCE_USAGE_GPU_READ); + vertex_position_buffer.elemSize = sizeof(vertex_positions[0]); + vertex_position_buffer.elemCount = sizeof(vertex_positions) / sizeof(vertex_positions[0]); + GX2RCreateBuffer(&vertex_position_buffer); + memcpy(GX2RLockBufferEx(&vertex_position_buffer, (GX2RResourceFlags)0), vertex_positions, sizeof(vertex_positions)); + GX2RUnlockBufferEx(&vertex_position_buffer, (GX2RResourceFlags)0); - fake_framebuffer = (unsigned char*)malloc(framebuffer_width * framebuffer_height * 3); + // Initialise texture coordinate buffer + const float texture_coordinates[4][2] = { + {0.0f, 0.0f}, + {1.0f, 0.0f}, + {1.0f, 1.0f}, + {0.0f, 1.0f} + }; - return true; + texture_coordinate_buffer.flags = (GX2RResourceFlags)(GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_READ | + GX2R_RESOURCE_USAGE_CPU_WRITE | + GX2R_RESOURCE_USAGE_GPU_READ); + texture_coordinate_buffer.elemSize = sizeof(texture_coordinates[0]); + texture_coordinate_buffer.elemCount = sizeof(texture_coordinates) / sizeof(texture_coordinates[0]); + GX2RCreateBuffer(&texture_coordinate_buffer); + memcpy(GX2RLockBufferEx(&texture_coordinate_buffer, (GX2RResourceFlags)0), texture_coordinates, sizeof(texture_coordinates)); + GX2RUnlockBufferEx(&texture_coordinate_buffer, (GX2RResourceFlags)0); + + // Initialise sampler + GX2InitSampler(&sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_POINT); + + // Initialise screen texture + screen_texture.surface.width = fake_framebuffer_width; + screen_texture.surface.height = fake_framebuffer_height; + screen_texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; + screen_texture.surface.depth = 1; + screen_texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; + screen_texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; + screen_texture.surface.mipLevels = 1; + screen_texture.viewNumMips = 1; + screen_texture.viewNumSlices = 1; + screen_texture.compMap = 0x00010203; + GX2CalcSurfaceSizeAndAlignment(&screen_texture.surface); + GX2InitTextureRegs(&screen_texture); + + if (GX2RCreateSurface(&screen_texture.surface, (GX2RResourceFlags)(GX2R_RESOURCE_BIND_TEXTURE | GX2R_RESOURCE_BIND_COLOR_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE | GX2R_RESOURCE_USAGE_CPU_READ | + GX2R_RESOURCE_USAGE_GPU_WRITE | GX2R_RESOURCE_USAGE_GPU_READ))) + { + // Do some binding + GX2SetPixelSampler(&sampler, shader_group.pixelShader->samplerVars[0].location); + GX2SetPixelTexture(&screen_texture, shader_group.pixelShader->samplerVars[0].location); + 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: + case 4: // Why the hell doesn't WUT have an enum for this? It always returns this value for me! + 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; + } + + GX2RDestroyBufferEx(&texture_coordinate_buffer, (GX2RResourceFlags)0); + GX2RDestroyBufferEx(&vertex_position_buffer, (GX2RResourceFlags)0); + + WHBGfxFreeShaderGroup(&shader_group); + } + + WHBGfxShutdown(); + + free(fake_framebuffer); + } + + return false; } void WindowBackend_Software_DestroyWindow(void) { + GX2RDestroySurfaceEx(&screen_texture.surface, (GX2RResourceFlags)0); + + GX2RDestroyBufferEx(&texture_coordinate_buffer, (GX2RResourceFlags)0); + GX2RDestroyBufferEx(&vertex_position_buffer, (GX2RResourceFlags)0); + + WHBGfxFreeShaderGroup(&shader_group); + + WHBGfxShutdown(); + free(fake_framebuffer); - free(drc_framebuffer); -// free(tv_framebuffer); - OSScreenShutdown(); } unsigned char* WindowBackend_Software_GetFramebuffer(size_t *pitch) { - *pitch = framebuffer_width * 3; + *pitch = fake_framebuffer_width * 3; return fake_framebuffer; } ATTRIBUTE_HOT void WindowBackend_Software_Display(void) { - const size_t pitch = (drc_buffer_size / 480) / 2; - - static bool flipflop; + // Convert frame from RGB24 to RGBA32, and upload it to the GPU texture + unsigned char *framebuffer = (unsigned char*)GX2RLockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0); const unsigned char *in_pointer = fake_framebuffer; - if (framebuffer_width <= 426 && framebuffer_height <= 240) + for (size_t y = 0; y < fake_framebuffer_height; ++y) { - const size_t line_size = framebuffer_width * 2 * 4; - const size_t line_delta = pitch - line_size; + unsigned char *out_pointer = &framebuffer[screen_texture.surface.pitch * 4 * y]; - unsigned char *out_pointer = drc_framebuffer; - - if (!flipflop) - out_pointer += drc_buffer_size / 2; - - out_pointer += ((854 - (framebuffer_width * 2)) * 4) / 2; - - for (size_t y = 0; y < framebuffer_height; ++y) + for (size_t x = 0; x < fake_framebuffer_width; ++x) { - for (size_t x = 0; x < framebuffer_width; ++x) - { - *out_pointer++ = in_pointer[0]; - *out_pointer++ = in_pointer[1]; - *out_pointer++ = in_pointer[2]; - *out_pointer++ = 0; - *out_pointer++ = in_pointer[0]; - *out_pointer++ = in_pointer[1]; - *out_pointer++ = in_pointer[2]; - *out_pointer++ = 0; - - in_pointer += 3; - } - - memcpy(out_pointer + line_delta, out_pointer - line_size, line_size); - - out_pointer += line_delta + pitch; - } - } - else - { - const size_t line_size = framebuffer_width * 4; - const size_t line_delta = pitch - line_size; - - unsigned char *out_pointer = drc_framebuffer; - - if (!flipflop) - out_pointer += drc_buffer_size / 2; - - out_pointer += ((854 - framebuffer_width) * 4) / 2; - - for (size_t y = 0; y < framebuffer_height; ++y) - { - for (size_t x = 0; x < framebuffer_width; ++x) - { - *out_pointer++ = *in_pointer++; - *out_pointer++ = *in_pointer++; - *out_pointer++ = *in_pointer++; - *out_pointer++ = 0; - } - - out_pointer += line_delta; + *out_pointer++ = *in_pointer++; + *out_pointer++ = *in_pointer++; + *out_pointer++ = *in_pointer++; + *out_pointer++ = 0; } } - flipflop = !flipflop; + GX2RUnlockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0); -// DCStoreRange(tv_framebuffer, tv_buffer_size); - DCStoreRange(drc_framebuffer, drc_buffer_size); + WHBGfxBeginRender(); -// OSScreenFlipBuffersEx(SCREEN_TV); - OSScreenFlipBuffersEx(SCREEN_DRC); + // 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); + GX2SetPixelShader(shader_group.pixelShader); + GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); + WHBGfxFinishRenderTV(); + + // 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); + GX2SetPixelShader(shader_group.pixelShader); + GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); + WHBGfxFinishRenderDRC(); + + WHBGfxFinishRender(); } void WindowBackend_Software_HandleWindowResize(unsigned int width, unsigned int height) { (void)width; (void)height; + + // The window doesn't resize on the Wii U }