mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-11 21:21:57 -04:00
Make JUTResFont load all texture data into one texture
Together with the previous change, this enables entire blocks of text to be rendered in one draw call.
This commit is contained in:
@@ -7,8 +7,7 @@
|
||||
|
||||
#if TARGET_PC
|
||||
struct FontDrawContext {
|
||||
int loadedBlock = -1;
|
||||
int loadedPage = -1;
|
||||
bool isTextureLoaded = false;
|
||||
};
|
||||
#define FONT_DRAW_CTX , FontDrawContext* context
|
||||
#define FONT_DRAW_CTX_ARG , context
|
||||
|
||||
@@ -18,10 +18,6 @@ struct BlockHeader {
|
||||
BE(u32) size;
|
||||
};
|
||||
|
||||
#if TARGET_PC
|
||||
struct GlyphTextures;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup jsystem-jutility
|
||||
*
|
||||
@@ -91,6 +87,16 @@ public:
|
||||
/* 0x66 */ u16 field_0x66;
|
||||
/* 0x68 */ u16 mMaxCode;
|
||||
/* 0x6C */ const IsLeadByte_func* mIsLeadByte;
|
||||
|
||||
#if TARGET_PC
|
||||
// Dusk change: we use a single large texture for all characters.
|
||||
// This enables better draw call merging, ideally enabling entire blocks of
|
||||
// text to be one draw call.
|
||||
TGXTexObj mJoinedTextureObject;
|
||||
u16 mJoinedTextureHeight;
|
||||
|
||||
void initJoinedTexture();
|
||||
#endif
|
||||
};
|
||||
|
||||
extern u8 const JUTResFONT_Ascfont_fix12[];
|
||||
|
||||
@@ -6,26 +6,13 @@
|
||||
#include "JSystem/JUtility/JUTAssert.h"
|
||||
#include "JSystem/JUtility/JUTConsole.h"
|
||||
#include <gx.h>
|
||||
#include "absl/container/node_hash_map.h"
|
||||
|
||||
#if TARGET_PC
|
||||
struct GlyphTextures {
|
||||
absl::node_hash_map<int, TGXTexObj> textures;
|
||||
};
|
||||
#endif
|
||||
|
||||
JUTResFont::JUTResFont() {
|
||||
#if TARGET_PC
|
||||
mGlyphTextures = new GlyphTextures();
|
||||
#endif
|
||||
initialize_state();
|
||||
JUTFont::initialize_state();
|
||||
}
|
||||
|
||||
JUTResFont::JUTResFont(const ResFONT* pFont, JKRHeap* pHeap) {
|
||||
#if TARGET_PC
|
||||
mGlyphTextures = new GlyphTextures();
|
||||
#endif
|
||||
initialize_state();
|
||||
JUTFont::initialize_state();
|
||||
initiate(pFont, pHeap);
|
||||
@@ -33,10 +20,7 @@ JUTResFont::JUTResFont(const ResFONT* pFont, JKRHeap* pHeap) {
|
||||
|
||||
JUTResFont::~JUTResFont() {
|
||||
#if TARGET_PC
|
||||
for (auto& pair : mGlyphTextures->textures) {
|
||||
pair.second.reset();
|
||||
}
|
||||
delete mGlyphTextures;
|
||||
mJoinedTextureObject.reset();
|
||||
#endif
|
||||
|
||||
if (mValid) {
|
||||
@@ -70,6 +54,33 @@ bool JUTResFont::initiate(const ResFONT* pFont, JKRHeap* pHeap) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void JUTResFont::initJoinedTexture() {
|
||||
if (mGly1BlockNum != 1) {
|
||||
CRASH("mGly1BlockNum must be 1!");
|
||||
}
|
||||
|
||||
const auto& block = *mpGlyphBlocks[0];
|
||||
if (block.textureWidth % 8 != 0 || block.textureHeight % 8 != 0) {
|
||||
// Idk how the GameCube's tiling texture format works so this is a safety check.
|
||||
CRASH("Texture size not divisible!");
|
||||
}
|
||||
|
||||
int pageCount = 0;
|
||||
u32 pageNumCells = block.numRows * block.numColumns;
|
||||
for (u32 code = block.startCode; code < block.endCode; code += pageNumCells) {
|
||||
pageCount += 1;
|
||||
}
|
||||
|
||||
mJoinedTextureHeight = block.textureHeight * pageCount;
|
||||
GXInitTexObj(&mJoinedTextureObject, block.data, block.textureWidth,
|
||||
mJoinedTextureHeight, static_cast<GXTexFmt>(block.textureFormat.host()),
|
||||
GX_CLAMP, GX_CLAMP, false);
|
||||
|
||||
GXInitTexObjLOD(&mJoinedTextureObject, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, 0U, 0U, GX_ANISO_1);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool JUTResFont::protected_initiate(const ResFONT* pFont, JKRHeap* pHeap) {
|
||||
void** p;
|
||||
delete_and_initialize();
|
||||
@@ -100,8 +111,10 @@ bool JUTResFont::protected_initiate(const ResFONT* pFont, JKRHeap* pHeap) {
|
||||
mpMapBlocks = JKR_NEW_ARRAY_ARGS(ResFONT::MAP1*, mMap1BlockNum, p);
|
||||
}
|
||||
setBlock();
|
||||
return true;
|
||||
|
||||
IF_DUSK(initJoinedTexture());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JUTResFont::countBlock() {
|
||||
@@ -258,8 +271,13 @@ f32 JUTResFont::drawChar_scale(f32 pos_x, f32 pos_y, f32 scale_x, f32 scale_y, i
|
||||
f32 y2 = getDescent() * (scale_y / getHeight()) + pos_y;
|
||||
|
||||
u16 texW = mpGlyphBlocks[field_0x66]->textureWidth;
|
||||
#if TARGET_PC
|
||||
u16 texH = mJoinedTextureHeight;
|
||||
#else
|
||||
u16 texH = mpGlyphBlocks[field_0x66]->textureHeight;
|
||||
#endif
|
||||
u16 cellW = mpGlyphBlocks[field_0x66]->cellWidth;
|
||||
|
||||
u16 cellH = mpGlyphBlocks[field_0x66]->cellHeight;
|
||||
s32 u1 = (mWidth * 0x8000) / texW;
|
||||
s32 v1 = (mHeight * 0x8000) / texH;
|
||||
@@ -456,26 +474,12 @@ void JUTResFont::loadImage(int code, GXTexMapID id FONT_DRAW_CTX){
|
||||
mHeight = cellRow * cellH;
|
||||
|
||||
#if TARGET_PC
|
||||
if (!context || context->loadedPage != pageIdx || context->loadedBlock != i) {
|
||||
const auto found = mGlyphTextures->textures.find(pageIdx);
|
||||
GXTexObj* texObj;
|
||||
if (found == mGlyphTextures->textures.end()) {
|
||||
texObj = &mGlyphTextures->textures[pageIdx];
|
||||
void* pImg = &mpGlyphBlocks[i]->data[pageIdx * mpGlyphBlocks[i]->textureSize];
|
||||
GXInitTexObj(texObj, pImg, mpGlyphBlocks[i]->textureWidth,
|
||||
mpGlyphBlocks[i]->textureHeight, (GXTexFmt)(u16)mpGlyphBlocks[i]->textureFormat,
|
||||
GX_CLAMP, GX_CLAMP, 0);
|
||||
|
||||
GXInitTexObjLOD(texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, 0U, 0U, GX_ANISO_1);
|
||||
} else {
|
||||
texObj = &found->second;
|
||||
}
|
||||
|
||||
GXLoadTexObj(texObj, id);
|
||||
mHeight += texH * pageIdx;
|
||||
|
||||
if (!context || !context->isTextureLoaded) {
|
||||
GXLoadTexObj(&mJoinedTextureObject, id);
|
||||
if (context) {
|
||||
context->loadedBlock = i;
|
||||
context->loadedPage = pageIdx;
|
||||
context->isTextureLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user