mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-09 07:18:34 -04:00
Gfx: Initial work on supporting graphics backends whose available VRAM size for texture storage is smaller than their maximum supported texture dimensions
This commit is contained in:
parent
542325c75c
commit
b603cad5ae
@ -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 (bmp->width > Gfx.MaxTexWidth || bmp->height > Gfx.MaxTexHeight) {
|
||||
if (!Gfx_CheckTextureSize(bmp->width, bmp->height)) {
|
||||
Chat_Add1("&cSkin %s is too large", skin);
|
||||
} else {
|
||||
if (e->Model->flags & MODEL_FLAG_CLEAR_HAT)
|
||||
|
14
src/Game.c
14
src/Game.c
@ -231,6 +231,8 @@ cc_bool Game_UpdateTexture(GfxResourceID* texId, struct Stream* src, const cc_st
|
||||
|
||||
cc_bool Game_ValidateBitmap(const cc_string* file, struct Bitmap* bmp) {
|
||||
int maxWidth = Gfx.MaxTexWidth, maxHeight = Gfx.MaxTexHeight;
|
||||
float texSize, maxSize;
|
||||
|
||||
if (!bmp->scan0) {
|
||||
Chat_Add1("&cError loading %s from the texture pack.", file);
|
||||
return false;
|
||||
@ -240,7 +242,17 @@ cc_bool Game_ValidateBitmap(const cc_string* file, struct Bitmap* bmp) {
|
||||
Chat_Add1("&cUnable to use %s from the texture pack.", file);
|
||||
|
||||
Chat_Add4("&c Its size is (%i,%i), your GPU supports (%i,%i) at most.",
|
||||
&bmp->width, &bmp->height, &maxWidth, &maxHeight);
|
||||
&bmp->width, &bmp->height, &maxWidth, &maxHeight);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Gfx.MaxTexSize && (bmp->width * bmp->height > Gfx.MaxTexSize)) {
|
||||
Chat_Add1("&cUnable to use %s from the texture pack.", file);
|
||||
texSize = (bmp->width * bmp->height) / (1024.0f * 1024.0f);
|
||||
maxSize = Gfx.MaxTexSize / (1024.0f * 1024.0f);
|
||||
|
||||
Chat_Add2("&c Its size is %f3 MB, your GPU supports %f3 MB at most.",
|
||||
&texSize, &maxSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,9 @@ CC_VAR extern struct _GfxData {
|
||||
/* Whether graphics context has been created */
|
||||
cc_bool Created;
|
||||
struct Matrix View, Projection;
|
||||
/* Maximum size in pixels a texture can consist of */
|
||||
/* NOTE: Not all graphics backends specify a value for this */
|
||||
int MaxTexSize;
|
||||
} Gfx;
|
||||
|
||||
extern GfxResourceID Gfx_defaultIb;
|
||||
@ -69,10 +72,10 @@ extern const cc_string Gfx_LowPerfMessage;
|
||||
|
||||
#define LOWPERF_EXIT_MESSAGE "&eExited reduced performance mode"
|
||||
|
||||
void Gfx_RecreateDynamicVb(GfxResourceID* vb, VertexFormat fmt, int maxVertices);
|
||||
void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
|
||||
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);
|
||||
/* Creates a new texture. (and also generates mipmaps if mipmaps) */
|
||||
/* Supported flags: TEXTURE_FLAG_MANAGED, TEXTURE_FLAG_DYNAMIC */
|
||||
/* NOTE: Only set mipmaps to true if Gfx_Mipmaps is also true, because whether textures
|
||||
@ -87,6 +90,7 @@ void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, i
|
||||
CC_API void Gfx_BindTexture(GfxResourceID texId);
|
||||
/* Deletes the given texture, then sets it to 0 */
|
||||
CC_API void Gfx_DeleteTexture(GfxResourceID* texId);
|
||||
|
||||
/* NOTE: Completely useless now, and does nothing in all graphics backends */
|
||||
/* (used to set whether texture colour is used when rendering vertices) */
|
||||
CC_API void Gfx_SetTexturing(cc_bool enabled);
|
||||
|
@ -339,7 +339,7 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
String_Format1(info, "-- Using 3DS --\n", NULL);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
|
@ -1160,7 +1160,7 @@ void Gfx_GetApiInfo(cc_string* info) {
|
||||
|
||||
String_Format1(info, "Adapter: %c\n", adapter);
|
||||
String_Format2(info, "Graphics memory: %f2 MB total (%f2 MB VRAM)\n", &tram_, &vram_);
|
||||
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
PrintMaxTextureInfo(info);
|
||||
|
||||
release_adapter:
|
||||
IDXGIAdapter_Release(dxgi_adapter);
|
||||
|
@ -880,7 +880,7 @@ void Gfx_GetApiInfo(cc_string* info) {
|
||||
String_Format1(info, "Adapter: %c\n", adapter.Description);
|
||||
String_Format1(info, "Processing mode: %c\n", D3D9_StrFlags());
|
||||
String_Format2(info, "Video memory: %f2 MB total, %f2 free\n", &totalMem, &curMem);
|
||||
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
PrintMaxTextureInfo(info);
|
||||
String_Format1(info, "Depth buffer bits: %i", &depthBits);
|
||||
}
|
||||
|
||||
|
@ -520,7 +520,7 @@ void Gfx_GetApiInfo(cc_string* info) {
|
||||
String_AppendConst(info, "GPU: PowerVR2 CLX2 100mHz\n");
|
||||
String_AppendConst(info, "T&L: GLdc library (KallistiOS / Kazade)\n");
|
||||
String_Format2(info, "Texture memory: %f2 MB used, %f2 MB free\n", &usedMemMB, &freeMemMB);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
|
@ -240,8 +240,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
|
||||
}
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
String_Format1(info, "-- Using GC/WII --", NULL);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
String_AppendConst(info, "-- Using GC/Wii --\n");
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
|
@ -62,7 +62,7 @@ void Gfx_GetApiInfo(cc_string* info) {
|
||||
String_AppendConst(info, "-- Using Nintendo 64 --\n");
|
||||
String_AppendConst(info, "GPU: Nintendo 64 RDP (LibDragon OpenGL)\n");
|
||||
String_AppendConst(info, "T&L: Nintendo 64 RSP (LibDragon OpenGL)\n");
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
@ -121,8 +121,6 @@ typedef struct CCTexture {
|
||||
} CCTexture;
|
||||
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
if (bmp->width > 32 || bmp->height > 32) return NULL;
|
||||
|
||||
CCTexture* tex = Mem_Alloc(1, sizeof(CCTexture), "texture");
|
||||
|
||||
glGenTextures(1, &tex->textureID);
|
||||
|
@ -617,9 +617,8 @@ void Gfx_OnWindowResize(void) {
|
||||
}
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
int pointerSize = sizeof(void*) * 8;
|
||||
String_Format1(info, "-- Using PS2 (%i bit) --\n", &pointerSize);
|
||||
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
String_AppendConst(info, "-- Using PS2 --\n");
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
cc_bool Gfx_TryRestoreContext(void) { return true; }
|
||||
|
@ -384,7 +384,7 @@ void Gfx_GetApiInfo(cc_string* info) {
|
||||
int pointerSize = sizeof(void*) * 8;
|
||||
|
||||
String_Format1(info, "-- Using PS3 (%i bit) --\n", &pointerSize);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
|
@ -239,8 +239,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
|
||||
}
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
String_Format1(info, "-- Using PSP--\n", NULL);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
String_AppendConst(info, "-- Using PSP--\n");
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
|
@ -750,10 +750,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
|
||||
}
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
int pointerSize = sizeof(void*) * 8;
|
||||
|
||||
String_Format1(info, "-- Using PS VITA (%i bit) --\n", &pointerSize);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
String_AppendConst(info, "-- Using PS Vita --\n");
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
|
@ -481,7 +481,7 @@ void Gfx_OnWindowResize(void) {
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
int pointerSize = sizeof(void*) * 8;
|
||||
String_Format1(info, "-- Using software (%i bit) --\n", &pointerSize);
|
||||
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
cc_bool Gfx_TryRestoreContext(void) { return true; }
|
||||
|
@ -345,7 +345,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
|
||||
}
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
String_AppendConst(info, "-- Using XBox --\n");
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
|
@ -357,10 +357,8 @@ void Gfx_EndFrame(void) {
|
||||
cc_bool Gfx_WarnIfNecessary(void) { return false; }
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
int pointerSize = sizeof(void*) * 8;
|
||||
|
||||
String_Format1(info, "-- Using XBox 360 (%i bit) --\n", &pointerSize);
|
||||
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
String_AppendConst(info, "-- Using XBox 360 --\n");
|
||||
PrintMaxTextureInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_OnWindowResize(void) {
|
||||
|
@ -435,7 +435,8 @@ void Screen_Render2Widgets(void* screen, double delta) {
|
||||
|
||||
void Screen_UpdateVb(void* screen) {
|
||||
struct Screen* s = (struct Screen*)screen;
|
||||
Gfx_RecreateDynamicVb(&s->vb, VERTEX_FORMAT_TEXTURED, s->maxVertices);
|
||||
Gfx_DeleteDynamicVb(&s->vb);
|
||||
s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, s->maxVertices);
|
||||
}
|
||||
|
||||
struct VertexTextured* Screen_LockVb(void* screen) {
|
||||
|
@ -63,8 +63,16 @@ static void Atlas_Convert2DTo1D(void) {
|
||||
|
||||
static void Atlas_Update1D(void) {
|
||||
int maxAtlasHeight, maxTilesPerAtlas, maxTiles;
|
||||
int maxTexHeight = Gfx.MaxTexHeight;
|
||||
|
||||
maxAtlasHeight = min(4096, Gfx.MaxTexHeight);
|
||||
/* E.g. a graphics backend may support textures up to 256 x 256 */
|
||||
/* dimension wise, but only have enough storage for 16 x 256 */
|
||||
if (Gfx.MaxTexSize) {
|
||||
int maxCurHeight = Gfx.MaxTexSize / Atlas2D.TileSize;
|
||||
maxTexHeight = min(maxTexHeight, maxCurHeight);
|
||||
}
|
||||
|
||||
maxAtlasHeight = min(4096, maxTexHeight);
|
||||
maxTilesPerAtlas = maxAtlasHeight / Atlas2D.TileSize;
|
||||
maxTiles = Atlas2D.RowsCount * ATLAS2D_TILES_PER_ROW;
|
||||
|
||||
@ -145,7 +153,7 @@ cc_bool Atlas_TryChange(struct Bitmap* atlas) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tileSize > Gfx.MaxTexWidth) {
|
||||
if (!Gfx_CheckTextureSize(tileSize, tileSize)) {
|
||||
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);
|
||||
|
@ -285,7 +285,7 @@ void Gfx_GetApiInfo(cc_string* info) {
|
||||
String_Format1(info, "Renderer: %c\n", glGetString(GL_RENDERER));
|
||||
String_Format1(info, "GL version: %c\n", glGetString(GL_VERSION));
|
||||
AppendVRAMStats(info);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
PrintMaxTextureInfo(info);
|
||||
String_Format1(info, "Depth buffer bits: %i\n", &depthBits);
|
||||
GLContext_GetApiInfo(info);
|
||||
}
|
||||
|
@ -51,11 +51,16 @@ static void MakeIndices(cc_uint16* indices, int count, void* obj) {
|
||||
}
|
||||
}
|
||||
|
||||
static void RecreateDynamicVb(GfxResourceID* vb, VertexFormat fmt, int maxVertices) {
|
||||
Gfx_DeleteDynamicVb(vb);
|
||||
*vb = Gfx_CreateDynamicVb(fmt, maxVertices);
|
||||
}
|
||||
|
||||
static void InitDefaultResources(void) {
|
||||
Gfx_defaultIb = Gfx_CreateIb2(GFX_MAX_INDICES, MakeIndices, NULL);
|
||||
|
||||
Gfx_RecreateDynamicVb(&Gfx_quadVb, VERTEX_FORMAT_COLOURED, 4);
|
||||
Gfx_RecreateDynamicVb(&Gfx_texVb, VERTEX_FORMAT_TEXTURED, 4);
|
||||
RecreateDynamicVb(&Gfx_quadVb, VERTEX_FORMAT_COLOURED, 4);
|
||||
RecreateDynamicVb(&Gfx_texVb, VERTEX_FORMAT_TEXTURED, 4);
|
||||
}
|
||||
|
||||
static void FreeDefaultResources(void) {
|
||||
@ -129,11 +134,6 @@ static void EndReducedPerformance(void) {
|
||||
}
|
||||
|
||||
|
||||
void Gfx_RecreateDynamicVb(GfxResourceID* vb, VertexFormat fmt, int maxVertices) {
|
||||
Gfx_DeleteDynamicVb(vb);
|
||||
*vb = Gfx_CreateDynamicVb(fmt, maxVertices);
|
||||
}
|
||||
|
||||
void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
Gfx_DeleteTexture(tex);
|
||||
*tex = Gfx_CreateTexture(bmp, flags, mipmaps);
|
||||
@ -252,6 +252,17 @@ static CC_INLINE float Reversed_CalcZNear(float fov, int depthbufferBits) {
|
||||
return 0.00390625f;
|
||||
}
|
||||
|
||||
static void PrintMaxTextureInfo(cc_string* info) {
|
||||
if (Gfx.MaxTexSize) {
|
||||
float maxSize = Gfx.MaxTexSize / (1024.0f * 1024.0f);
|
||||
String_Format3(info, "Max texture size: (%i, %i), up to %f3 MB\n",
|
||||
&Gfx.MaxTexWidth, &Gfx.MaxTexHeight, &maxSize);
|
||||
} else {
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n",
|
||||
&Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
@ -339,6 +350,15 @@ static CC_NOINLINE int CalcMipmapsLevels(int width, int height) {
|
||||
}
|
||||
}
|
||||
|
||||
cc_bool Gfx_CheckTextureSize(int width, int height) {
|
||||
if (width > Gfx.MaxTexWidth) return false;
|
||||
if (height > Gfx.MaxTexHeight) return false;
|
||||
|
||||
if (Gfx.MaxTexSize && (width * height > Gfx.MaxTexSize))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
@ -346,6 +366,7 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
if (Gfx.LostContext) return 0;
|
||||
if (!Gfx_CheckTextureSize(bmp->width, bmp->height)) return 0;
|
||||
|
||||
return Gfx_AllocTexture(bmp, flags, mipmaps);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user