mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-08 06:47:23 -04:00
N64: Support loading UI textures as 16bpp instead of 32bpp to squeeze even more out of the 4 KB TMEM
This commit is contained in:
parent
9661c34b4f
commit
cc048431f6
@ -301,13 +301,15 @@ void Drawer2D_MakeTextTexture(struct Texture* tex, struct DrawTextArgs* args) {
|
||||
}
|
||||
|
||||
void Context2D_MakeTexture(struct Texture* tex, struct Context2D* ctx) {
|
||||
Gfx_RecreateTexture(&tex->ID, &ctx->bmp, TEXTURE_FLAG_NONPOW2, false);
|
||||
int flags = TEXTURE_FLAG_NONPOW2 | TEXTURE_FLAG_LOWRES;
|
||||
Gfx_RecreateTexture(&tex->ID, &ctx->bmp, flags, false);
|
||||
|
||||
tex->Width = ctx->width;
|
||||
tex->Height = ctx->height;
|
||||
|
||||
tex->uv.U1 = 0.0f; tex->uv.V1 = 0.0f;
|
||||
tex->uv.U2 = (float)ctx->width / (float)ctx->bmp.width;
|
||||
tex->uv.V2 = (float)ctx->height / (float)ctx->bmp.height;
|
||||
|
||||
tex->uv.U1 = 0.0f; tex->uv.V1 = 0.0f;
|
||||
tex->uv.U2 = (float)ctx->width / (float)ctx->bmp.width;
|
||||
tex->uv.V2 = (float)ctx->height / (float)ctx->bmp.height;
|
||||
}
|
||||
|
||||
cc_bool Drawer2D_ValidColorCodeAt(const cc_string* text, int i) {
|
||||
@ -687,4 +689,4 @@ struct IGameComponent Drawer2D_Component = {
|
||||
OnInit, /* Init */
|
||||
OnFree, /* Free */
|
||||
OnReset, /* Reset */
|
||||
};
|
||||
};
|
||||
|
@ -326,7 +326,7 @@ static cc_result ApplySkin(struct Entity* e, struct Bitmap* bmp, struct Stream*
|
||||
if ((res = EnsurePow2Skin(e, bmp))) return res;
|
||||
e->SkinType = Utils_CalcSkinType(bmp);
|
||||
|
||||
if (!Gfx_CheckTextureSize(bmp->width, bmp->height)) {
|
||||
if (!Gfx_CheckTextureSize(bmp->width, bmp->height, 0)) {
|
||||
Chat_Add1("&cSkin %s is too large", skin);
|
||||
} else {
|
||||
if (e->Model->flags & MODEL_FLAG_CLEAR_HAT)
|
||||
|
@ -58,6 +58,9 @@ CC_VAR extern struct _GfxData {
|
||||
struct Matrix View, Projection;
|
||||
/* Whether the graphics backend supports non power of two textures */
|
||||
cc_bool SupportsNonPowTwoTextures;
|
||||
/* Maximum total size in pixels a low resolution texture can consist of */
|
||||
/* NOTE: Not all graphics backends specify a value for this */
|
||||
int MaxLowResTexSize;
|
||||
} Gfx;
|
||||
|
||||
extern GfxResourceID Gfx_defaultIb;
|
||||
@ -73,13 +76,15 @@ extern const cc_string Gfx_LowPerfMessage;
|
||||
#define TEXTURE_FLAG_DYNAMIC 0x02
|
||||
/* Texture is deliberately (and not accidentally) being created with non power of two dimensions */
|
||||
#define TEXTURE_FLAG_NONPOW2 0x04
|
||||
/* Texture can fallback to 16 bpp when necessary (most backends don't do this) */
|
||||
#define TEXTURE_FLAG_LOWRES 0x08
|
||||
|
||||
#define LOWPERF_EXIT_MESSAGE "&eExited reduced performance mode"
|
||||
|
||||
void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
|
||||
void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count);
|
||||
|
||||
cc_bool Gfx_CheckTextureSize(int width, int height);
|
||||
cc_bool Gfx_CheckTextureSize(int width, int height, cc_uint8 flags);
|
||||
/* Creates a new texture. (and also generates mipmaps if mipmaps) */
|
||||
/* See TEXTURE_FLAG values for supported flags */
|
||||
/* NOTE: Only set mipmaps to true if Gfx_Mipmaps is also true, because whether textures
|
||||
|
@ -28,10 +28,15 @@ void Gfx_Create(void) {
|
||||
//rdpq_debug_log(true);
|
||||
zbuffer = surface_alloc(FMT_RGBA16, display_get_width(), display_get_height());
|
||||
|
||||
Gfx.MaxTexWidth = 128;
|
||||
Gfx.MaxTexHeight = 128;
|
||||
Gfx.MaxTexSize = 1024; // TMEM only has 4 KB in it
|
||||
Gfx.MaxTexWidth = 256;
|
||||
Gfx.MaxTexHeight = 256;
|
||||
Gfx.Created = true;
|
||||
|
||||
// TMEM only has 4 KB in it, which can be interpreted as
|
||||
// - 1024 32bpp pixels
|
||||
// - 2048 16bpp pixels
|
||||
Gfx.MaxTexSize = 1024;
|
||||
Gfx.MaxLowResTexSize = 2048;
|
||||
|
||||
Gfx.SupportsNonPowTwoTextures = true;
|
||||
Gfx_RestoreState();
|
||||
@ -116,7 +121,12 @@ typedef struct CCTexture {
|
||||
GLuint textureID;
|
||||
} CCTexture;
|
||||
|
||||
// A8 B8 G8 R8 > A1 B5 G5 B5
|
||||
#define To16BitPixel(src) \
|
||||
((src & 0x80) >> 7) | ((src & 0xF800) >> 10) | ((src & 0xF80000) >> 13) | ((src & 0xF8000000) >> 16);
|
||||
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
cc_bool bit16 = flags & TEXTURE_FLAG_LOWRES;
|
||||
CCTexture* tex = Mem_Alloc(1, sizeof(CCTexture), "texture");
|
||||
|
||||
glGenTextures(1, &tex->textureID);
|
||||
@ -125,19 +135,34 @@ static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_boo
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
tex->surface = surface_alloc(FMT_RGBA32, bmp->width, bmp->height);
|
||||
|
||||
tex->surface = surface_alloc(bit16 ? FMT_RGBA16 : FMT_RGBA32, bmp->width, bmp->height);
|
||||
surface_t* fb = &tex->surface;
|
||||
cc_uint32* src = (cc_uint32*)bmp->scan0;
|
||||
cc_uint8* dst = (cc_uint8*)fb->buffer;
|
||||
|
||||
for (int y = 0; y < bmp->height; y++)
|
||||
{
|
||||
Mem_Copy(dst + y * fb->stride,
|
||||
src + y * bmp->width,
|
||||
bmp->width * 4);
|
||||
|
||||
if (bit16) {
|
||||
// 16 bpp requires reducing A8R8G8B8 to A1R5G5B5
|
||||
for (int y = 0; y < bmp->height; y++)
|
||||
{
|
||||
cc_uint32* src_row = src + y * bmp->width;
|
||||
cc_uint16* dst_row = (cc_uint16*)(dst + y * fb->stride);
|
||||
|
||||
for (int x = 0; x < bmp->width; x++)
|
||||
{
|
||||
dst_row[x] = To16BitPixel(src_row[x]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 32 bpp can just be copied straight across
|
||||
for (int y = 0; y < bmp->height; y++)
|
||||
{
|
||||
Mem_Copy(dst + y * fb->stride,
|
||||
src + y * bmp->width,
|
||||
bmp->width * 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rdpq_texparms_t params =
|
||||
{
|
||||
.s.repeats = (flags & TEXTURE_FLAG_NONPOW2) ? 1 : REPEAT_INFINITE,
|
||||
|
@ -153,7 +153,7 @@ cc_bool Atlas_TryChange(struct Bitmap* atlas) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Gfx_CheckTextureSize(tileSize, tileSize)) {
|
||||
if (!Gfx_CheckTextureSize(tileSize, tileSize, 0)) {
|
||||
Chat_AddRaw("&cUnable to use terrain.png from the texture pack.");
|
||||
Chat_Add4("&c Tile size is (%i,%i), your GPU supports (%i,%i) at most.",
|
||||
&tileSize, &tileSize, &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
|
@ -350,13 +350,17 @@ static CC_NOINLINE int CalcMipmapsLevels(int width, int height) {
|
||||
}
|
||||
}
|
||||
|
||||
cc_bool Gfx_CheckTextureSize(int width, int height) {
|
||||
cc_bool Gfx_CheckTextureSize(int width, int height, cc_uint8 flags) {
|
||||
int maxSize;
|
||||
if (width > Gfx.MaxTexWidth) return false;
|
||||
if (height > Gfx.MaxTexHeight) return false;
|
||||
|
||||
maxSize = Gfx.MaxTexSize;
|
||||
// low resolution textures may support higher sizes (e.g. Nintendo 64)
|
||||
if ((flags & TEXTURE_FLAG_LOWRES) && Gfx.MaxLowResTexSize)
|
||||
maxSize = Gfx.MaxLowResTexSize;
|
||||
|
||||
if (Gfx.MaxTexSize && (width * height > Gfx.MaxTexSize))
|
||||
return false;
|
||||
return true;
|
||||
return maxSize == 0 || (width * height <= maxSize);
|
||||
}
|
||||
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
|
||||
@ -370,7 +374,7 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm
|
||||
}
|
||||
|
||||
if (Gfx.LostContext) return 0;
|
||||
if (!Gfx_CheckTextureSize(bmp->width, bmp->height)) return 0;
|
||||
if (!Gfx_CheckTextureSize(bmp->width, bmp->height, flags)) return 0;
|
||||
|
||||
return Gfx_AllocTexture(bmp, flags, mipmaps);
|
||||
}
|
||||
@ -448,4 +452,4 @@ struct IGameComponent Gfx_Component = {
|
||||
/* first component freed, even though it MUST be the last */
|
||||
/* Instead, Game.c calls Gfx_Free after first freeing all */
|
||||
/* the other game components. */
|
||||
};
|
||||
};
|
||||
|
@ -2961,7 +2961,6 @@
|
||||
FT_Error error;
|
||||
FT_Memory memory;
|
||||
FT_Module module = NULL;
|
||||
FT_UInt nn;
|
||||
|
||||
memory = library->memory;
|
||||
error = FT_Err_Ok;
|
||||
|
Loading…
x
Reference in New Issue
Block a user