3DS: Use system font for menus
Jeffrey Pfau jeffrey@endrift.com
Thu, 28 Jul 2016 00:32:00 -0700
6 files changed,
69 insertions(+),
50 deletions(-)
M
src/platform/3ds/CMakeLists.txt
→
src/platform/3ds/CMakeLists.txt
@@ -30,7 +30,6 @@ set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE)
list(APPEND GUI_SRC ${CMAKE_CURRENT_BINARY_DIR}/icons.c - ${CMAKE_CURRENT_BINARY_DIR}/font.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h@@ -44,7 +43,6 @@ ${CMAKE_CURRENT_SOURCE_DIR}/ctr-gpu.h)
set_source_files_properties( ${CMAKE_CURRENT_BINARY_DIR}/icons.c - ${CMAKE_CURRENT_BINARY_DIR}/font.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h@@ -64,10 +62,6 @@
add_custom_command(OUTPUT ${BINARY_NAME}.bnr COMMAND ${BANNERTOOL} makebanner -i ${CMAKE_CURRENT_SOURCE_DIR}/logo.png -a ${CMAKE_CURRENT_SOURCE_DIR}/bios.wav -o ${BINARY_NAME}.bnr DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/logo.png ${CMAKE_CURRENT_SOURCE_DIR}/bios.wav) - -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/font.c - COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/font.raw - DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/3ds/font.raw) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.c COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw
M
src/platform/3ds/ctr-gpu.c
→
src/platform/3ds/ctr-gpu.c
@@ -27,11 +27,12 @@ short uw, vh;
u32 abgr; }; -#define MAX_NUM_QUADS 1024 +#define MAX_NUM_QUADS 2048 #define VERTEX_BUFFER_SIZE MAX_NUM_QUADS * sizeof(struct ctrUIVertex) static struct ctrUIVertex* ctrVertexBuffer = NULL; -static u16 ctrNumQuads = 0; +static int ctrNumVerts = 0; +static int ctrVertStart = 0; static C3D_Tex* activeTexture = NULL;@@ -70,12 +71,6 @@ if (ctrVertexBuffer == NULL) {
return false; } - // Set up TexEnv and other parameters - C3D_TexEnv* env = C3D_GetTexEnv(0); - C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0); - C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); - C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); - C3D_CullFace(GPU_CULL_NONE); C3D_DepthTest(false, GPU_ALWAYS, GPU_WRITE_ALL); C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);@@ -88,10 +83,6 @@ AttrInfo_AddLoader(attrInfo, 0, GPU_SHORT, 4); // in_pos
AttrInfo_AddLoader(attrInfo, 1, GPU_SHORT, 4); // in_tc0 AttrInfo_AddLoader(attrInfo, 2, GPU_UNSIGNED_BYTE, 4); // in_col - C3D_BufInfo* bufInfo = C3D_GetBufInfo(); - BufInfo_Init(bufInfo); - BufInfo_Add(bufInfo, ctrVertexBuffer, sizeof(struct ctrUIVertex), 3, 0x210); - return true; }@@ -129,9 +120,20 @@ if (activeTexture) {
ctrFlushBatch(); } - C3D_TexBind(0, texture); activeTexture = texture; + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + if (texture->fmt < GPU_LA8) { + C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0); + C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); + } else { + C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR, 0, 0); + C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0); + C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE); + C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE); + } + C3D_Mtx textureMtx = { .m = { // Rows are in the order w z y x, because ctrulib@@ -143,11 +145,14 @@ C3D_FVUnifMtx2x4(GPU_GEOMETRY_SHADER, GSH_FVEC_textureMtx, &textureMtx);
} void ctrAddRectScaled(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s16 vh) { - if (ctrNumQuads == MAX_NUM_QUADS) { + if (ctrNumVerts + ctrVertStart == MAX_NUM_QUADS) { ctrFlushBatch(); + C3D_Flush(); + ctrNumVerts = 0; + ctrVertStart = 0; } - struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrNumQuads]; + struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrVertStart + ctrNumVerts]; vtx->x = x; vtx->y = y; vtx->w = w;@@ -158,7 +163,7 @@ vtx->uw = uw;
vtx->vh = vh; vtx->abgr = color; - ++ctrNumQuads; + ++ctrNumVerts; } void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h) {@@ -166,13 +171,19 @@ ctrAddRectScaled(color, x, y, w, h, u, v, w, h);
} void ctrFlushBatch(void) { - if (ctrNumQuads == 0) { + if (ctrNumVerts == 0) { return; } + C3D_TexBind(0, activeTexture); + + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, &ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex), 3, 0x210); + GSPGPU_FlushDataCache(ctrVertexBuffer, VERTEX_BUFFER_SIZE); - C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, ctrNumQuads); - C3D_Flush(); + C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, ctrNumVerts); - ctrNumQuads = 0; + ctrVertStart += ctrNumVerts; + ctrNumVerts = 0; }
M
src/platform/3ds/gui-font.c
→
src/platform/3ds/gui-font.c
@@ -8,35 +8,42 @@ #include "util/gui/font-metrics.h"
#include "util/png-io.h" #include "util/vfs.h" #include "icons.h" -#include "font.h" #include "ctr-gpu.h" #define CELL_HEIGHT 16 #define CELL_WIDTH 16 -#define GLYPH_HEIGHT 12 +#define FONT_SIZE 0.52f struct GUIFont { - C3D_Tex texture; + C3D_Tex* sheets; C3D_Tex icons; }; struct GUIFont* GUIFontCreate(void) { + fontEnsureMapped(); struct GUIFont* guiFont = malloc(sizeof(struct GUIFont)); if (!guiFont) { return 0; } + C3D_Tex* tex; - C3D_Tex* tex = &guiFont->texture; - C3D_TexInitVRAM(tex, 256, 128, GPU_RGBA5551); + TGLP_s* glyphInfo = fontGetGlyphInfo(); + guiFont->sheets = malloc(sizeof(*guiFont->sheets) * glyphInfo->nSheets); - GSPGPU_FlushDataCache(font, font_size); - GX_RequestDma((u32*) font, tex->data, font_size); - gspWaitForDMA(); + int i; + for (i = 0; i < glyphInfo->nSheets; ++i) { + tex = &guiFont->sheets[i]; + tex->data = fontGetGlyphSheetTex(i); + tex->fmt = glyphInfo->sheetFmt; + tex->size = glyphInfo->sheetSize; + tex->width = glyphInfo->sheetWidth; + tex->height = glyphInfo->sheetHeight; + tex->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE); + } tex = &guiFont->icons; C3D_TexInitVRAM(tex, 256, 64, GPU_RGBA5551); - GSPGPU_FlushDataCache(icons, icons_size); GX_RequestDma((u32*) icons, tex->data, icons_size);@@ -46,22 +53,24 @@ return guiFont;
} void GUIFontDestroy(struct GUIFont* font) { - C3D_TexDelete(&font->texture); + free(font->sheets); C3D_TexDelete(&font->icons); free(font); } unsigned GUIFontHeight(const struct GUIFont* font) { UNUSED(font); - return GLYPH_HEIGHT; + return fontGetInfo()->lineFeed * FONT_SIZE; } unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) { UNUSED(font); - if (glyph > 0x7F) { - glyph = 0; + int index = fontGlyphIndexFromCodePoint(glyph); + charWidthInfo_s* info = fontGetCharWidthInfo(index); + if (info) { + return info->charWidth * FONT_SIZE; } - return defaultFontMetrics[glyph].width; + return 0; } void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) {@@ -84,19 +93,21 @@ }
} void GUIFontDrawGlyph(const struct GUIFont* font, int glyph_x, int glyph_y, uint32_t color, uint32_t glyph) { - ctrActivateTexture(&font->texture); + int index = fontGlyphIndexFromCodePoint(glyph); + fontGlyphPos_s data; + fontCalcGlyphPos(&data, index, GLYPH_POS_CALC_VTXCOORD, 1.0, 1.0); - if (glyph > 0x7F) { - glyph = '?'; - } + C3D_Tex* tex = &font->sheets[data.sheetIndex]; + ctrActivateTexture(tex); - struct GUIFontGlyphMetric metric = defaultFontMetrics[glyph]; - u16 x = glyph_x - metric.padding.left; - u16 y = glyph_y - GLYPH_HEIGHT; - u16 u = (glyph % 16u) * CELL_WIDTH; - u16 v = (glyph / 16u) * CELL_HEIGHT; + float width = data.texcoord.right - data.texcoord.left; + float height = data.texcoord.top - data.texcoord.bottom; + u16 x = glyph_x; + u16 y = glyph_y + tex->height * height / 8; + u16 u = tex->width * data.texcoord.left; + u16 v = tex->height * data.texcoord.bottom; - ctrAddRect(color, x, y, u, v, CELL_WIDTH, CELL_HEIGHT); + ctrAddRectScaled(color, x, y, tex->width * width * FONT_SIZE, tex->height * height * -FONT_SIZE, u, v, tex->width * width, tex->height * height); } void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
M
src/platform/3ds/main.c
→
src/platform/3ds/main.c
@@ -178,6 +178,8 @@ C3D_RenderBufClear(&topScreen);
} static void _drawEnd(void) { + ctrFlushBatch(); + C3D_Flush(); C3D_RenderBufTransfer(&topScreen, (u32*) gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); C3D_RenderBufTransfer(&bottomScreen, (u32*) gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); gfxSwapBuffersGpu();