libgui 2.01
libgui is a GUI library for the GameCube, Wii, and Wii U
 
Loading...
Searching...
No Matches
WutVideoDriver.h
1/****************************************************************************
2 * Platform Abstraction Layer (WUT driver)
3 * Daryl Borth 2026
4 * WutVideoDriver.h
5 ***************************************************************************/
6#pragma once
7
8#include <vector>
9#include <coreinit/time.h>
10#include <gx2/sampler.h>
11#include <gx2/texture.h>
12#include "../VideoDriver.h"
13#include "../Mutex.h"
14
19enum class OutputTarget
20{
21 TV = 0,
22 DRC = 1
23};
24
25static const int OUTPUT_TARGET_COUNT = 2;
26
30struct WutMesh
31{
32 float * positions;
33 uint8_t * colors;
34 uint32_t count;
36};
37
43{
45 enum class Kind : uint8_t
46 {
52 };
53
54 Kind kind;
55 uint32_t slot;
56 const GX2Texture * texture;
57 const GX2Sampler * sampler;
58 float angle;
59 float offset[3];
60 float scale[3];
61 float colorIntensity[4];
62 uint32_t first;
63 uint32_t count;
64 const WutMesh * mesh;
65};
66
73class WutVideoDriver : public VideoDriver
74{
75 public:
76 WutVideoDriver();
77 ~WutVideoDriver() override;
78
79 void init(int width, int height) override;
80 void shutdown() override;
81 void render() override;
82 void clearScreen(const PixelColor& color) override;
83
84 int getScreenWidth() const override { return screenWidth; }
85 int getScreenHeight() const override { return screenHeight; }
86 uint32_t getFrameTimer() override;
87
88 int getRefreshRate() const override;
89 float getDeltaTime() const override;
90 float getUIScale() const override { return uiScale; }
91
96 int getTargetWidth(OutputTarget target) const { return targetWidth[(int)target]; }
97 int getTargetHeight(OutputTarget target) const { return targetHeight[(int)target]; }
98
99 ImageRenderer* getImageRenderer() override { return imageRenderer; }
100 GlyphRenderer* getGlyphRenderer() override { return glyphRenderer; }
101
106 bool isForeground() const;
107
108 // Copies the drawn TV/DRC contents to their scan buffers and submits
109 // the flip. Always pipelined: submits and returns without waiting for
110 // the GPU to finish (that wait is prepareFrame()'s job, below). The
111 // one wait done here is for the *previous* submit's flip, since the
112 // copy above can't safely land on a scan buffer the display hasn't
113 // finished swapping away from yet.
114 void presentBuffer();
115
118 void queueDraw(const WutDrawCmd& cmd);
119
125 void queueMesh(const MeshVertex* vertices, size_t count);
126
135 void queueMeshInstance(const WutMesh* mesh, float x, float y, float scaleX, float scaleY);
136
139 void retireMesh(WutMesh* mesh);
140
147 void flushDrawQueue();
148
153 static const unsigned kAllTargets = 3;
154 void setUiTargets(unsigned mask) { uiTargets = mask; }
155
160 void waitForIdle();
161
162 // Binds the TV context state and resets the per-frame render state
163 // (viewport/scissor/blend/depth/cull) that WHBGfxInit() doesn't set
164 // on its own, and rewinds the shared shader slot counters (see
165 // ColorShader::resetFrame() / Texture2DShader::resetFrame()).
166 // `targets` (a bit per OutputTarget, as for setUiTargets()) says which
167 // outputs are cleared and rebound; an output left out keeps what it
168 // shows now, and that is what presentBuffer() will send to it again.
169 void prepareFrame(unsigned targets = kAllTargets);
170
175 bool isPresentPending() const;
176 private:
177 static const size_t cuMaxQueuedDraws = 4096;
178 std::vector<WutDrawCmd> drawQueue;
179
180 // Vertex arena for Mesh draws. Written when a mesh is queued, made visible to the
181 // GPU in flushDrawQueue(), read by both the TV and GamePad replays, and rewound
182 // once per frame in prepareFrame() - never mid-frame, because a draw submitted
183 // earlier in the frame may still be reading it (same rule as ColorShader's slots).
184 static const uint32_t cuMeshArenaVertices = 1u << 18;
185 float * meshPositions = nullptr; // 3 floats (NDC x, y, 0) per vertex
186 uint8_t * meshColors = nullptr; // RGBA8 per vertex
187 uint32_t meshUsed = 0; // vertices written this frame
188 uint32_t meshFlushed = 0; // vertices already invalidated for the GPU
189
190 // Meshes whose owners let go of them, waiting for the GPU to finish with them
191 Mutex * retireLock = nullptr;
192 WutMesh * retiredMeshes = nullptr;
193 void freeRetiredMeshes();
194 void replayDrawQueue() const; // draws drawQueue into whichever context is currently bound
195
196 unsigned uiTargets = kAllTargets;
197 bool gpuFramesInFlight = false; // a pipelined frame was submitted and not yet retired/drained
198 OSTime lastSubmitTimeStamp = 0; // GX2 timestamp of that submit
199
200 // Queries GX2's current TV scan mode/aspect ratio and derives the
201 // physical TV and DRC target dims
202 void computeUIScale();
203
204 int screenWidth;
205 int screenHeight;
206 float uiScale = 1.0f;
207 int targetWidth[OUTPUT_TARGET_COUNT] = { 0, 0 };
208 int targetHeight[OUTPUT_TARGET_COUNT] = { 0, 0 };
209 PixelColor clearColor;
210
211 ImageRenderer * imageRenderer;
212 GlyphRenderer * glyphRenderer;
213};
214
218{
219 public:
222
223 void * createTexture(int width, int height) override;
224 void loadTextureData(void * texture, const uint8_t * rgba, int width, int height) override;
225 bool canReuseTexture(int allocWidth, int allocHeight, int width, int height) const override;
226 void destroyTexture(void * texture) override;
227 void drawTexture(void * texture, float xpos, float ypos, uint16_t width, uint16_t height, float degrees, float scaleX, float scaleY, uint8_t alpha) override;
228 void drawRectangle(float x, float y, float width, float height, PixelColor color) override;
229 void drawMesh(const MeshVertex* vertices, size_t count) override;
230 void* createMesh(const MeshVertex* vertices, size_t count) override;
231 void destroyMesh(void* mesh) override;
232 void drawMeshInstance(void* mesh, float x, float y, float scaleX, float scaleY) override;
233
234 private:
235 WutVideoDriver * driver;
236 GX2Sampler sampler;
237};
238
243{
244 public:
247
248 void* createTexture(uint16_t width, uint16_t height) override;
249 void loadTextureData(void* texture, FT_Bitmap* bitmap) override;
250 void destroyTexture(void* texture) override;
251
252 void drawQuad(void* texture, int16_t screenX, int16_t screenY, uint16_t width, uint16_t height, const PixelColor& color) override;
253 void drawFeature(int16_t screenX, int16_t screenY, uint16_t width, uint16_t height, const PixelColor& color) override;
254
255 private:
256 WutVideoDriver * driver;
257 GX2Sampler sampler;
258};
Draws glyph textures and solid rectangles on behalf of GuiTextRenderer.
Platform image/texture backend GuiImageData and GuiImage delegate to.
Definition VideoDriver.h:72
A simple mutual-exclusion lock.
Definition Mutex.h:14
Platform video backend owning the frame lifecycle (init/render/clear, screen size,...
Definition VideoDriver.h:28
void drawQuad(void *texture, int16_t screenX, int16_t screenY, uint16_t width, uint16_t height, const PixelColor &color) override
Draws a glyph texture as a quad tinted with color.
void drawFeature(int16_t screenX, int16_t screenY, uint16_t width, uint16_t height, const PixelColor &color) override
Draws a solid-color rectangle used for text decoration (underline/strike-through).
void destroyTexture(void *texture) override
Destroys a texture created by createTexture().
WutGlyphRenderer(WutVideoDriver *driver)
void * createTexture(uint16_t width, uint16_t height) override
Allocates an empty single-channel glyph texture. Returns an opaque handle.
void loadTextureData(void *texture, FT_Bitmap *bitmap) override
Uploads a rasterized FreeType glyph bitmap into a texture from createTexture().
void drawMeshInstance(void *mesh, float x, float y, float scaleX, float scaleY) override
Draws a mesh from createMesh() fully opaque, as its vertex colors say.
void destroyTexture(void *texture) override
Destroys a texture created by createTexture.
void destroyMesh(void *mesh) override
Releases a mesh from createMesh().
void loadTextureData(void *texture, const uint8_t *rgba, int width, int height) override
Loads raw RGBA8 pixels into the pre-allocated texture.
void * createTexture(int width, int height) override
Allocates an empty hardware-aligned texture buffer.
void drawRectangle(float x, float y, float width, float height, PixelColor color) override
Draws a solid-color rectangle (alpha-blended using color.a).
void drawMesh(const MeshVertex *vertices, size_t count) override
Draws a triangle list: three vertices per triangle, each with its own color.
void * createMesh(const MeshVertex *vertices, size_t count) override
Hands a triangle list to the backend to keep in its own ready-to-draw form (a GX display list,...
void drawTexture(void *texture, float xpos, float ypos, uint16_t width, uint16_t height, float degrees, float scaleX, float scaleY, uint8_t alpha) override
Draws a texture created by createTexture.
bool canReuseTexture(int allocWidth, int allocHeight, int width, int height) const override
Whether a texture allocated for allocWidth x allocHeight can be reloaded in place.
WutImageRenderer(WutVideoDriver *driver)
Wii U VideoDriver: GX2 + libwhb's WHBGfx* helpers.
uint32_t getFrameTimer() override
void clearScreen(const PixelColor &color) override
Clears the current frame buffer.
static const unsigned kAllTargets
Which outputs flushDrawQueue() replays into (bit per OutputTarget: 1 << TV, 1 << DRC).
void queueDraw(const WutDrawCmd &cmd)
Records a UI draw for the next flushDrawQueue().
int getScreenHeight() const override
float getUIScale() const override
Ratio of physical render-target pixels to design-canvas pixels (the width/height passed to init()).
GlyphRenderer * getGlyphRenderer() override
bool isPresentPending() const
True while the last presented frame has not finished: not yet on screen (the swap is waiting for the ...
void retireMesh(WutMesh *mesh)
Sets a mesh aside to be freed once the GPU is done with every frame that might draw it.
ImageRenderer * getImageRenderer() override
void queueMesh(const MeshVertex *vertices, size_t count)
Copies a triangle list into this frame's vertex arena (converting positions to NDC) and records a Mes...
float getDeltaTime() const override
void render() override
Flushes the current frame to the screen and swaps buffers.
int getRefreshRate() const override
void init(int width, int height) override
void queueMeshInstance(const WutMesh *mesh, float x, float y, float scaleX, float scaleY)
Records a draw of a mesh made by WutImageRenderer::createMesh().
void shutdown() override
Releases the video backend. Call after every other user of the renderers has finished.
int getTargetWidth(OutputTarget target) const
Physical pixel size of a render target (the TV follows the console's output setting,...
int getScreenWidth() const override
void flushDrawQueue()
Replays every recorded UI draw into the TV context, then the same list into the GamePad context,...
void waitForIdle()
Waits until the GPU has retired the last submitted frame.
bool isForeground() const
False once the OS has taken away the foreground (HOME menu overlay, forced exit, etc....
A single 2D vertex with its own color, in design-canvas coordinates.
Definition Mesh.h:27
8-bit-per-channel RGBA color used by the video interfaces.
Definition Mesh.h:16
One recorded UI draw (image, glyph quad or flat rectangle).
Kind
Which shader a queued draw goes through.
@ Mesh
triangle list from the mesh arena through ColorShader (see WutVideoDriver::queueMesh())
@ TextureRotated
textured quad whose corners were pre-rotated into a Texture2DShader rotated slot
@ Texture
textured quad through Texture2DShader, shader-side angle/offset/scale
@ Color
flat-color quad through ColorShader
@ MeshInstance
a WutMesh through ColorShader, placed by the shader-side offset/scale (see WutVideoDriver::queueMeshI...
float offset[3]
NDC position (unused by TextureRotated)
const GX2Sampler * sampler
Texture/TextureRotated only.
float angle
Texture only, radians.
float scale[3]
NDC half-extents (unused by TextureRotated)
uint32_t slot
TextureRotated only: slot from Texture2DShader::uploadRotatedQuad()
uint32_t first
Mesh only: index of the first vertex in the arena.
uint32_t count
Mesh only: number of vertices.
const GX2Texture * texture
Texture/TextureRotated only.
const WutMesh * mesh
MeshInstance only.
A mesh kept in GPU-readable vertex buffers across frames (ImageRenderer::createMesh()).
WutMesh * next
Link in the retired list.
uint32_t count
Number of vertices.
uint8_t * colors
RGBA8 per vertex.
float * positions
3 floats per vertex (x, y, 0)