13#include <ogc/machine/processor.h>
15#include "OgcVideoDriver.h"
18#define DEFAULT_FIFO_SIZE 256 * 1024
19static Mtx GXmodelView2D;
21OgcVideoDriver::OgcVideoDriver() { }
23OgcVideoDriver::~OgcVideoDriver()
34 if (CONF_GetAspectRatio() == CONF_ASPECT_16_9 && (*(u32*)(0xCD8005A0) >> 16) == 0xCAFE)
36 write32(0xd8006a0, 0x30000004), mask32(0xd8006a8, 0, 2);
40 vmode = VIDEO_GetPreferredMode(
nullptr);
43 if (CONF_GetAspectRatio() == CONF_ASPECT_16_9)
48 if((vmode->viTVMode >> 2) == VI_NTSC)
50 vmode->viXOrigin = (VI_MAX_WIDTH_NTSC - vmode->viWidth) / 2;
51 vmode->viYOrigin = (VI_MAX_HEIGHT_NTSC - vmode->viHeight) / 2;
55 vmode->viXOrigin = (VI_MAX_WIDTH_PAL - vmode->viWidth) / 2;
56 vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - vmode->viHeight) / 2;
60 VIDEO_Configure (vmode);
62 xfb[0] = (uint32_t *) SYS_AllocateFramebuffer (vmode);
63 xfb[1] = (uint32_t *) SYS_AllocateFramebuffer (vmode);
64 DCInvalidateRange(xfb[0], VIDEO_GetFrameBufferSize(vmode));
65 DCInvalidateRange(xfb[1], VIDEO_GetFrameBufferSize(vmode));
66 xfb[0] = (uint32_t *) MEM_K0_TO_K1 (xfb[0]);
67 xfb[1] = (uint32_t *) MEM_K0_TO_K1 (xfb[1]);
69 VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK);
70 VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK);
71 VIDEO_SetNextFramebuffer (xfb[0]);
73 VIDEO_SetBlack (FALSE);
76 if (vmode->viTVMode & VI_NON_INTERLACE)
80 screenHeight = height;
83 GXColor background = { 0, 0, 0, 0xff };
84 gp_fifo = memalign(32, DEFAULT_FIFO_SIZE);
85 memset(gp_fifo, 0, DEFAULT_FIFO_SIZE);
86 GX_Init(gp_fifo, DEFAULT_FIFO_SIZE);
87 GX_SetCopyClear (background, GX_MAX_Z24);
88 GX_SetDispCopyGamma (GX_GM_1_0);
89 GX_SetCullMode (GX_CULL_NONE);
101 OgcFreeRetiredMeshes();
103 VIDEO_SetBlack(TRUE);
110 GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
111 GX_SetColorUpdate(GX_TRUE);
112 GX_CopyDisp(xfb[whichfb],GX_TRUE);
114 OgcFreeRetiredMeshes();
115 VIDEO_SetNextFramebuffer(xfb[whichfb]);
117 VIDEO_WaitForFlush();
123 GXColor background = { color.r, color.g, color.b, color.a };
124 GX_SetCopyClear(background, GX_MAX_Z24);
127void OgcVideoDriver::resetVideoMenu()
134 GXColor background = {0, 0, 0, 255};
135 GX_SetCopyClear (background, GX_MAX_Z24);
137 yscale = GX_GetYScaleFactor(vmode->efbHeight,vmode->xfbHeight);
138 xfbHeight = GX_SetDispCopyYScale(yscale);
139 GX_SetScissor(0,0,vmode->fbWidth,vmode->efbHeight);
140 GX_SetDispCopySrc(0,0,vmode->fbWidth,vmode->efbHeight);
141 GX_SetDispCopyDst(vmode->fbWidth,xfbHeight);
142 GX_SetCopyFilter(vmode->aa,vmode->sample_pattern,GX_TRUE,vmode->vfilter);
143 GX_SetFieldMode(vmode->field_rendering,((vmode->viHeight==2*vmode->xfbHeight)?GX_ENABLE:GX_DISABLE));
146 GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);
148 GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
154 GX_InvalidateTexAll();
156 GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
157 GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
158 GX_SetVtxDesc (GX_VA_CLR0, GX_DIRECT);
160 GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
161 GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
162 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
163 GX_SetZMode (GX_FALSE, GX_LEQUAL, GX_TRUE);
167 GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
168 GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
169 GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
171 guMtxIdentity(GXmodelView2D);
172 guMtxTransApply (GXmodelView2D, GXmodelView2D, 0.0F, 0.0F, -50.0F);
173 GX_LoadPosMtxImm(GXmodelView2D,GX_PNMTX0);
175 guOrtho(p,0,screenHeight-1,0,screenWidth-1,0,300);
176 GX_LoadProjectionMtx(p, GX_ORTHOGRAPHIC);
178 GX_SetViewport(0,0,vmode->fbWidth,vmode->efbHeight,0,1);
179 GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
180 GX_SetAlphaUpdate(GX_TRUE);
185 int padWidth = width + (4 - width % 4) % 4;
186 int padHeight = height + (4 - height % 4) % 4;
187 int len = (padWidth * padHeight) * 4;
188 if (len % 32) len += (32 - len % 32);
189 return memalign(32, len);
194 if(!texture || !rgba)
return;
195 uint8_t* dst = (uint8_t*)texture;
196 int padWidth = width + (4 - width % 4) % 4;
197 int padHeight = height + (4 - height % 4) % 4;
199 for (
int y = 0; y < padHeight; y++) {
200 for (
int x = 0; x < padWidth; x++) {
201 uint32_t offset = ((((y >> 2) * (padWidth >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1;
202 if (y >= height || x >= width) {
203 dst[offset] = 0; dst[offset+1] = 255; dst[offset+32] = 255; dst[offset+33] = 255;
205 const uint8_t* src = rgba + (y * width + x) * 4;
206 dst[offset] = src[3];
207 dst[offset+1] = src[0];
208 dst[offset+32] = src[1];
209 dst[offset+33] = src[2];
214 int len = (padWidth * padHeight) * 4;
215 if (len % 32) len += (32 - len % 32);
216 DCFlushRange(dst, len);
225void OgcImageRenderer::drawTexture(
void * texture,
float xpos,
float ypos, uint16_t width, uint16_t height,
float degrees,
float scaleX,
float scaleY, uint8_t alpha)
232 GX_InitTexObj(&texObj, texture, width, height, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
233 GX_LoadTexObj(&texObj, GX_TEXMAP0);
234 GX_InvalidateTexAll();
236 GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
237 GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT);
243 guMtxScale(m1, scaleX, scaleY, 1.0);
244 guVector axis = (guVector) {0 , 0, 1 };
245 guMtxRotAxisDeg (m2, &axis, degrees);
246 guMtxConcat(m2,m1,m);
248 guMtxTransApply(m,m, xpos+width,ypos+height,0);
249 guMtxConcat (GXmodelView2D, m, mv);
250 GX_LoadPosMtxImm (mv, GX_PNMTX0);
252 GX_Begin(GX_QUADS, GX_VTXFMT0,4);
253 GX_Position3f32(-width, -height, 0);
254 GX_Color4u8(0xFF,0xFF,0xFF,alpha);
255 GX_TexCoord2f32(0, 0);
257 GX_Position3f32(width, -height, 0);
258 GX_Color4u8(0xFF,0xFF,0xFF,alpha);
259 GX_TexCoord2f32(1, 0);
261 GX_Position3f32(width, height, 0);
262 GX_Color4u8(0xFF,0xFF,0xFF,alpha);
263 GX_TexCoord2f32(1, 1);
265 GX_Position3f32(-width, height, 0);
266 GX_Color4u8(0xFF,0xFF,0xFF,alpha);
267 GX_TexCoord2f32(0, 1);
269 GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
271 GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
272 GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
280 guVector v[] = {{x,y,0.0f}, {x2,y,0.0f}, {x2,y2,0.0f}, {x,y2,0.0f}, {x,y,0.0f}};
282 GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, n);
283 for(
long i=0; i<n; ++i)
285 GX_Position3f32(v[i].x, v[i].y, v[i].z);
286 GX_Color4u8(color.r, color.g, color.b, color.a);
302 const uint16_t n = (uint16_t)(count > 65535 ? 65535 : count);
304 GX_Begin(GX_TRIANGLES, GX_VTXFMT0, n);
305 for(uint16_t i = 0; i < n; ++i)
308 GX_Position3f32(v.
x, v.
y, 0.0f);
309 GX_Color4u8(v.
c.
r, v.
c.
g, v.
c.
b, v.
c.
a);
328static OgcMesh * retiredMeshes =
nullptr;
341 const size_t begins = (count + 65534) / 65535;
342 const size_t bytes = (begins * 3 + count * 16 + 63) & ~(
size_t)31;
344 void * list = memalign(32, bytes);
350 DCInvalidateRange(list, bytes);
351 GX_BeginDispList(list, bytes);
356 const uint16_t n = (uint16_t)(left > 65535 ? 65535 : left);
358 GX_Begin(GX_TRIANGLES, GX_VTXFMT0, n);
359 for(uint16_t i = 0; i < n; ++i)
361 GX_Position3f32(v[i].x, v[i].y, 0.0f);
362 GX_Color4u8(v[i].c.r, v[i].
c.
g, v[i].
c.
b, v[i].
c.
a);
369 const u32 used = GX_EndDispList();
375 DCFlushRange(list, used);
397 _CPU_ISR_Disable(level);
398 m->
next = retiredMeshes;
400 _CPU_ISR_Restore(level);
403void OgcFreeRetiredMeshes()
406 _CPU_ISR_Disable(level);
408 retiredMeshes =
nullptr;
409 _CPU_ISR_Restore(level);
429 guMtxScale(t, scaleX, scaleY, 1.0f);
430 guMtxTransApply(t, t, x, y, 0.0f);
431 guMtxConcat(GXmodelView2D, t, mv);
432 GX_LoadPosMtxImm(mv, GX_PNMTX0);
433 GX_CallDispList(m->list, m->size);
434 GX_LoadPosMtxImm(GXmodelView2D, GX_PNMTX0);
Umbrella header for the platform-agnostic libgui core.
GX-backed GlyphRenderer for GuiTextRenderer.
GX-backed ImageRenderer for GuiImage/GuiImageData textures.
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 destroyTexture(void *texture) override
Destroys a texture created by 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 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 drawRectangle(float x, float y, float width, float height, PixelColor color) override
Draws a solid-color rectangle (alpha-blended using color.a).
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.
void destroyMesh(void *mesh) override
Releases a mesh from createMesh().
void shutdown() override
Releases the video backend. Call after every other user of the renderers has finished.
void render() override
Flushes the current frame to the screen and swaps buffers.
void clearScreen(const PixelColor &color) override
Clears the current frame buffer.
void init(int width, int height) override
A single 2D vertex with its own color, in design-canvas coordinates.
float y
Y position (design-canvas pixels).
float x
X position (design-canvas pixels).
PixelColor c
Straight (non-premultiplied) RGBA color.
OgcMesh * next
Link in the retired list.
8-bit-per-channel RGBA color used by the video interfaces.
uint8_t g
Green color component.
uint8_t r
Red color component.
uint8_t b
Blue color component.
uint8_t a
Alpha component.