diff --git a/misc/build_scripts/buildbot.sh b/misc/build_scripts/buildbot.sh index 7a9cac289..ec18e7a13 100644 --- a/misc/build_scripts/buildbot.sh +++ b/misc/build_scripts/buildbot.sh @@ -61,8 +61,8 @@ build_win64() { # ----------------------------- compile linux # I installed gcc and gcc-multilib packages -NIX32_FLAGS="-no-pie -fno-pie -m32 -fvisibility=hidden -rdynamic -DCC_BUILD_ICON" -NIX64_FLAGS="-no-pie -fno-pie -m64 -fvisibility=hidden -rdynamic -DCC_BUILD_ICON" +NIX32_FLAGS="-no-pie -fno-pie -m32 -fvisibility=hidden -fcf-protection=none -rdynamic -DCC_BUILD_ICON" +NIX64_FLAGS="-no-pie -fno-pie -m64 -fvisibility=hidden -fcf-protection=none -rdynamic -DCC_BUILD_ICON" build_nix32() { echo "Building linux32.." diff --git a/src/AxisLinesRenderer.c b/src/AxisLinesRenderer.c index 7798f0f26..44bb75895 100644 --- a/src/AxisLinesRenderer.c +++ b/src/AxisLinesRenderer.c @@ -34,7 +34,7 @@ void AxisLinesRenderer_Render(void) { if (!AxisLinesRenderer_Enabled) return; /* Don't do it in a ContextRecreated handler, because we only want VB recreated if ShowAxisLines in on. */ if (!axisLines_vb) { - Gfx_RecreateDynamicVb(&axisLines_vb, VERTEX_FORMAT_COLOURED, AXISLINES_NUM_VERTICES); + axisLines_vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_COLOURED, AXISLINES_NUM_VERTICES); } if (Camera.Active->isThirdPerson) { diff --git a/src/Entity.c b/src/Entity.c index 6e3c13d1a..98af1a2c6 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -9,8 +9,6 @@ #include "Funcs.h" #include "Graphics.h" #include "Lighting.h" -#include "Drawer2D.h" -#include "Particle.h" #include "Http.h" #include "Chat.h" #include "Model.h" @@ -22,6 +20,7 @@ #include "Options.h" #include "Errors.h" #include "Utils.h" +#include "EntityRenderers.h" const char* const NameMode_Names[NAME_MODE_COUNT] = { "None", "Hovered", "All", "AllHovered", "AllUnscaled" }; const char* const ShadowMode_Names[SHADOW_MODE_COUNT] = { "None", "SnapToBlock", "Circle", "CircleAll" }; @@ -47,6 +46,11 @@ void Entity_Init(struct Entity* e) { Entity_SetModel(e, &model); } +void Entity_SetName(struct Entity* e, const cc_string* name) { + EntityNames_Delete(e); + String_CopyToRawArray(e->NameRaw, name); +} + Vec3 Entity_GetEyePosition(struct Entity* e) { Vec3 pos = e->Position; pos.Y += Entity_GetEyeHeight(e); return pos; } @@ -191,103 +195,6 @@ cc_bool Entity_TouchesAnyWater(struct Entity* e) { } - -/*########################################################################################################################* -*-----------------------------------------------------Entity nametag------------------------------------------------------* -*#########################################################################################################################*/ -#define NAME_IS_EMPTY -30000 -#define NAME_OFFSET 3 /* offset of back layer of name above an entity */ - -static void MakeNameTexture(struct Entity* e) { - cc_string colorlessName; char colorlessBuffer[STRING_SIZE]; - BitmapCol shadowColor = BitmapCol_Make(80, 80, 80, 255); - BitmapCol origWhiteColor; - - struct DrawTextArgs args; - struct FontDesc font; - struct Context2D ctx; - int width, height; - cc_string name; - - /* Names are always drawn using default.png font */ - Font_MakeBitmapped(&font, 24, FONT_FLAGS_NONE); - /* Don't want DPI scaling or padding */ - font.size = 24; font.height = 24; - - name = String_FromRawArray(e->NameRaw); - DrawTextArgs_Make(&args, &name, &font, false); - width = Drawer2D_TextWidth(&args); - - if (!width) { - e->NameTex.ID = 0; - e->NameTex.X = NAME_IS_EMPTY; - } else { - String_InitArray(colorlessName, colorlessBuffer); - width += NAME_OFFSET; - height = Drawer2D_TextHeight(&args) + NAME_OFFSET; - - Context2D_Alloc(&ctx, width, height); - { - origWhiteColor = Drawer2D.Colors['f']; - - Drawer2D.Colors['f'] = shadowColor; - Drawer2D_WithoutColors(&colorlessName, &name); - args.text = colorlessName; - Context2D_DrawText(&ctx, &args, NAME_OFFSET, NAME_OFFSET); - - Drawer2D.Colors['f'] = origWhiteColor; - args.text = name; - Context2D_DrawText(&ctx, &args, 0, 0); - } - Context2D_MakeTexture(&e->NameTex, &ctx); - Context2D_Free(&ctx); - } -} - -static void DrawName(struct Entity* e) { - struct VertexTextured vertices[4]; - struct Model* model; - struct Matrix mat; - Vec3 pos; - float scale; - Vec2 size; - - if (e->NameTex.X == NAME_IS_EMPTY) return; - if (!e->NameTex.ID) MakeNameTexture(e); - Gfx_BindTexture(e->NameTex.ID); - - model = e->Model; - Vec3_TransformY(&pos, model->GetNameY(e), &e->Transform); - - scale = model->nameScale * e->ModelScale.Y; - scale = scale > 1.0f ? (1.0f/70.0f) : (scale/70.0f); - size.X = e->NameTex.Width * scale; size.Y = e->NameTex.Height * scale; - - if (Entities.NamesMode == NAME_MODE_ALL_UNSCALED && LocalPlayer_Instance.Hacks.CanSeeAllNames) { - Matrix_Mul(&mat, &Gfx.View, &Gfx.Projection); /* TODO: This mul is slow, avoid it */ - /* Get W component of transformed position */ - scale = pos.X * mat.row1.W + pos.Y * mat.row2.W + pos.Z * mat.row3.W + mat.row4.W; - size.X *= scale * 0.2f; size.Y *= scale * 0.2f; - } - - Particle_DoRender(&size, &pos, &e->NameTex.uv, PACKEDCOL_WHITE, vertices); - Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); - Gfx_UpdateDynamicVb_IndexedTris(Gfx_texVb, vertices, 4); -} - -/* Deletes the texture containing the entity's nametag */ -CC_NOINLINE static void DeleteNameTex(struct Entity* e) { - Gfx_DeleteTexture(&e->NameTex.ID); - e->NameTex.X = 0; /* X is used as an 'empty name' flag */ -} - -void Entity_SetName(struct Entity* e, const cc_string* name) { - DeleteNameTex(e); - String_CopyToRawArray(e->NameRaw, name); - /* name texture redraw deferred until necessary */ -} - - /*########################################################################################################################* *------------------------------------------------------Entity skins-------------------------------------------------------* *#########################################################################################################################*/ @@ -529,7 +436,6 @@ void Entity_LerpAngles(struct Entity* e, float t) { *--------------------------------------------------------Entities---------------------------------------------------------* *#########################################################################################################################*/ struct _EntitiesData Entities; -static EntityID entities_closestId; void Entities_Tick(struct ScheduledTask* task) { int i; @@ -549,83 +455,17 @@ void Entities_RenderModels(double delta, float t) { } Gfx_SetAlphaTest(false); } - - -void Entities_RenderNames(void) { - struct LocalPlayer* p = &LocalPlayer_Instance; - cc_bool hadFog; - int i; - - if (Entities.NamesMode == NAME_MODE_NONE) return; - entities_closestId = Entities_GetClosest(&p->Base); - if (!p->Hacks.CanSeeAllNames || Entities.NamesMode != NAME_MODE_ALL) return; - - Gfx_SetAlphaTest(true); - hadFog = Gfx_GetFog(); - if (hadFog) Gfx_SetFog(false); - - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - if (i != entities_closestId || i == ENTITIES_SELF_ID) { - Entities.List[i]->VTABLE->RenderName(Entities.List[i]); - } - } - - Gfx_SetAlphaTest(false); - if (hadFog) Gfx_SetFog(true); -} - -void Entities_RenderHoveredNames(void) { - struct LocalPlayer* p = &LocalPlayer_Instance; - cc_bool allNames, hadFog; - int i; - - if (Entities.NamesMode == NAME_MODE_NONE) return; - allNames = !(Entities.NamesMode == NAME_MODE_HOVERED || Entities.NamesMode == NAME_MODE_ALL) - && p->Hacks.CanSeeAllNames; - - Gfx_SetAlphaTest(true); - Gfx_SetDepthTest(false); - hadFog = Gfx_GetFog(); - if (hadFog) Gfx_SetFog(false); - - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - if ((i == entities_closestId || allNames) && i != ENTITIES_SELF_ID) { - Entities.List[i]->VTABLE->RenderName(Entities.List[i]); - } - } - - Gfx_SetAlphaTest(false); - Gfx_SetDepthTest(true); - if (hadFog) Gfx_SetFog(true); -} - -static void Entity_ContextLost(struct Entity* e) { DeleteNameTex(e); } static void Entities_ContextLost(void* obj) { int i; - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - Entity_ContextLost(Entities.List[i]); - } - if (Gfx.ManagedTextures) return; + for (i = 0; i < ENTITIES_MAX_COUNT; i++) { if (!Entities.List[i]) continue; DeleteSkin(Entities.List[i]); } } -/* No OnContextCreated, names/skin textures remade when needed */ - -static void Entities_ChatFontChanged(void* obj) { - int i; - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - DeleteNameTex(Entities.List[i]); - /* name redraw is deferred until rendered */ - } -} +/* No OnContextCreated, skin textures remade when needed */ void Entities_Remove(EntityID id) { struct Entity* e = Entities.List[id]; @@ -747,7 +587,7 @@ struct IGameComponent TabList_Component = { static void Player_Despawn(struct Entity* e) { DeleteSkin(e); - Entity_ContextLost(e); + EntityNames_Delete(e); } @@ -868,9 +708,8 @@ static void LocalPlayer_RenderModel(struct Entity* e, double deltaTime, float t) Model_Render(e->Model, e); } -static void LocalPlayer_RenderName(struct Entity* e) { - if (!Camera.Active->isThirdPerson) return; - DrawName(e); +static cc_bool LocalPlayer_ShouldRenderName(struct Entity* e) { + return Camera.Active->isThirdPerson; } static void LocalPlayer_CheckJumpVelocity(void* obj) { @@ -894,7 +733,7 @@ static void LocalPlayer_GetMovement(float* xMoving, float* zMoving) { static const struct EntityVTABLE localPlayer_VTABLE = { LocalPlayer_Tick, Player_Despawn, LocalPlayer_SetLocation, Entity_GetColor, - LocalPlayer_RenderModel, LocalPlayer_RenderName + LocalPlayer_RenderModel, LocalPlayer_ShouldRenderName }; static void LocalPlayer_Init(void) { struct LocalPlayer* p = &LocalPlayer_Instance; @@ -1150,19 +989,19 @@ static void NetPlayer_RenderModel(struct Entity* e, double deltaTime, float t) { if (e->ShouldRender) Model_Render(e->Model, e); } -static void NetPlayer_RenderName(struct Entity* e) { +static cc_bool NetPlayer_ShouldRenderName(struct Entity* e) { float distance; int threshold; - if (!e->ShouldRender) return; + if (!e->ShouldRender) return false; distance = Model_RenderDistance(e); threshold = Entities.NamesMode == NAME_MODE_ALL_UNSCALED ? 8192 * 8192 : 32 * 32; - if (distance <= (float)threshold) DrawName(e); + return distance <= (float)threshold; } static const struct EntityVTABLE netPlayer_VTABLE = { NetPlayer_Tick, Player_Despawn, NetPlayer_SetLocation, Entity_GetColor, - NetPlayer_RenderModel, NetPlayer_RenderName + NetPlayer_RenderModel, NetPlayer_ShouldRenderName }; void NetPlayer_Init(struct NetPlayer* p) { Mem_Set(p, 0, sizeof(struct NetPlayer)); @@ -1175,10 +1014,9 @@ void NetPlayer_Init(struct NetPlayer* p) { *---------------------------------------------------Entities component----------------------------------------------------* *#########################################################################################################################*/ static void Entities_Init(void) { - Event_Register_(&GfxEvents.ContextLost, NULL, Entities_ContextLost); - Event_Register_(&ChatEvents.FontChanged, NULL, Entities_ChatFontChanged); - Event_Register_(&InputEvents.Down, NULL, LocalPlayer_InputDown); - Event_Register_(&InputEvents.Up, NULL, LocalPlayer_InputUp); + Event_Register_(&GfxEvents.ContextLost, NULL, Entities_ContextLost); + Event_Register_(&InputEvents.Down, NULL, LocalPlayer_InputDown); + Event_Register_(&InputEvents.Up, NULL, LocalPlayer_InputUp); Entities.NamesMode = Options_GetEnum(OPT_NAMES_MODE, NAME_MODE_HOVERED, NameMode_Names, Array_Elems(NameMode_Names)); diff --git a/src/Entity.h b/src/Entity.h index b3e8e9202..22c6b1e45 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -71,7 +71,7 @@ struct EntityVTABLE { void (*SetLocation)(struct Entity* e, struct LocationUpdate* update); PackedCol (*GetCol)(struct Entity* e); void (*RenderModel)(struct Entity* e, double deltaTime, float t); - void (*RenderName)(struct Entity* e); + cc_bool (*ShouldRenderName)(struct Entity* e); }; /* Skin is still being downloaded asynchronously */ @@ -155,10 +155,6 @@ CC_VAR extern struct _EntitiesData { void Entities_Tick(struct ScheduledTask* task); /* Renders all entities */ void Entities_RenderModels(double delta, float t); -/* Renders the name tags of entities, depending on Entities.NamesMode */ -void Entities_RenderNames(void); -/* Renders hovered entity name tags (these appears through blocks) */ -void Entities_RenderHoveredNames(void); /* Removes the given entity, raising EntityEvents.Removed event */ void Entities_Remove(EntityID id); /* Gets the ID of the closest entity to the given entity */ diff --git a/src/EntityRenderers.c b/src/EntityRenderers.c index f0d2ff80b..d33f3dd21 100644 --- a/src/EntityRenderers.c +++ b/src/EntityRenderers.c @@ -9,15 +9,29 @@ #include "Graphics.h" #include "Model.h" #include "World.h" +#include "Particle.h" +#include "Drawer2D.h" /*########################################################################################################################* *------------------------------------------------------Entity Shadow------------------------------------------------------* *#########################################################################################################################*/ static cc_bool shadows_boundTex; +static GfxResourceID shadows_VB; static GfxResourceID shadows_tex; static float shadow_radius, shadow_uvScale; struct ShadowData { float Y; BlockID Block; cc_uint8 A; }; +/* Circle shadows extend at most 4 blocks vertically */ +#define SHADOW_MAX_RANGE 4 +/* Circle shadows on blocks underneath the top block can be chopped up into at most 4 pieces */ +#define SHADOW_MAX_PER_SUB_BLOCK (4 * 4) +/* Circle shadows use at most: + - 4 vertices for top most block + - MAX_PER_SUB_BLOCK for everyblock underneath the top block */ +#define SHADOW_MAX_PER_COLUMN (4 + SHADOW_MAX_PER_SUB_BLOCK * (SHADOW_MAX_RANGE - 1)) +/* Circle shadows may be split across (x,z), (x,z+1), (x+1,z), (x+1,z+1) */ +#define SHADOW_MAX_VERTS 4 * SHADOW_MAX_PER_COLUMN + static cc_bool lequal(float a, float b) { return a < b || Math_AbsF(a - b) < 0.001f; } static void EntityShadow_DrawCoords(struct VertexTextured** vertices, struct Entity* e, struct ShadowData* data, float x1, float z1, float x2, float z2) { PackedCol col; @@ -72,7 +86,8 @@ static void EntityShadow_DrawCircle(struct VertexTextured** vertices, struct Ent min = Blocks.MinBB[data[0].Block]; max = Blocks.MaxBB[data[0].Block]; EntityShadow_DrawCoords(vertices, e, &data[0], x + min.X, z + min.Z, x + max.X, z + max.Z); - for (i = 1; i < 4; i++) { + for (i = 1; i < 4; i++) + { if (data[i].Block == BLOCK_AIR) return; nMin = Blocks.MinBB[data[i].Block]; nMax = Blocks.MaxBB[data[i].Block]; @@ -112,7 +127,8 @@ static cc_bool EntityShadow_GetBlocks(struct Entity* e, int x, int y, int z, str posY = e->Position.Y; outside = !World_ContainsXZ(x, z); - for (i = 0; y >= 0 && i < 4; y--) { + for (i = 0; y >= 0 && i < 4; y--) + { if (!outside) { block = World_GetBlock(x, y, z); } else if (y == Env.EdgeHeight - 1) { @@ -146,10 +162,9 @@ static cc_bool EntityShadow_GetBlocks(struct Entity* e, int x, int y, int z, str } static void EntityShadow_Draw(struct Entity* e) { - struct VertexTextured vertices[128]; + struct VertexTextured vertices[128]; /* TODO this is less than maxVertes */ struct VertexTextured* ptr; struct ShadowData data[4]; - GfxResourceID vb; Vec3 pos; float radius; int y, count; @@ -163,16 +178,13 @@ static void EntityShadow_Draw(struct Entity* e) { shadow_radius = radius / 16.0f; shadow_uvScale = 16.0f / (radius * 2.0f); - /* TODO: Should shadow component use its own VB? */ ptr = vertices; if (Entities.ShadowsMode == SHADOW_MODE_SNAP_TO_BLOCK) { - vb = Gfx_texVb; x1 = Math_Floor(pos.X); z1 = Math_Floor(pos.Z); if (!EntityShadow_GetBlocks(e, x1, y, z1, data)) return; EntityShadow_DrawSquareShadow(&ptr, data[0].Y, x1, z1); } else { - vb = Models.Vb; x1 = Math_Floor(pos.X - shadow_radius); z1 = Math_Floor(pos.Z - shadow_radius); x2 = Math_Floor(pos.X + shadow_radius); z2 = Math_Floor(pos.Z + shadow_radius); @@ -198,7 +210,8 @@ static void EntityShadow_Draw(struct Entity* e) { } count = (int)(ptr - vertices); - Gfx_UpdateDynamicVb_IndexedTris(vb, vertices, count); + Gfx_SetDynamicVbData(shadows_VB, vertices, count); + Gfx_DrawVb_IndexedTris(count); } @@ -225,7 +238,7 @@ static void EntityShadows_MakeTexture(void) { row[x] = dist < sh_half * sh_half ? color : 0; } } - Gfx_RecreateTexture(&shadows_tex, &bmp, 0, false); + shadows_tex = Gfx_CreateTexture(&bmp, 0, false); } void EntityShadows_Render(void) { @@ -233,7 +246,10 @@ void EntityShadows_Render(void) { if (Entities.ShadowsMode == SHADOW_MODE_NONE) return; shadows_boundTex = false; - if (!shadows_tex) EntityShadows_MakeTexture(); + if (!shadows_tex) + EntityShadows_MakeTexture(); + if (!shadows_VB) + shadows_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, SHADOW_MAX_VERTS); Gfx_SetAlphaArgBlend(true); Gfx_SetDepthWrite(false); @@ -256,19 +272,193 @@ void EntityShadows_Render(void) { } +/*########################################################################################################################* +*-----------------------------------------------------Entity nametag------------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID names_VB; +#define NAME_IS_EMPTY -30000 +#define NAME_OFFSET 3 /* offset of back layer of name above an entity */ + +static void MakeNameTexture(struct Entity* e) { + cc_string colorlessName; char colorlessBuffer[STRING_SIZE]; + BitmapCol shadowColor = BitmapCol_Make(80, 80, 80, 255); + BitmapCol origWhiteColor; + + struct DrawTextArgs args; + struct FontDesc font; + struct Context2D ctx; + int width, height; + cc_string name; + + /* Names are always drawn using default.png font */ + Font_MakeBitmapped(&font, 24, FONT_FLAGS_NONE); + /* Don't want DPI scaling or padding */ + font.size = 24; font.height = 24; + + name = String_FromRawArray(e->NameRaw); + DrawTextArgs_Make(&args, &name, &font, false); + width = Drawer2D_TextWidth(&args); + + if (!width) { + e->NameTex.ID = 0; + e->NameTex.X = NAME_IS_EMPTY; + } else { + String_InitArray(colorlessName, colorlessBuffer); + width += NAME_OFFSET; + height = Drawer2D_TextHeight(&args) + NAME_OFFSET; + + Context2D_Alloc(&ctx, width, height); + { + origWhiteColor = Drawer2D.Colors['f']; + + Drawer2D.Colors['f'] = shadowColor; + Drawer2D_WithoutColors(&colorlessName, &name); + args.text = colorlessName; + Context2D_DrawText(&ctx, &args, NAME_OFFSET, NAME_OFFSET); + + Drawer2D.Colors['f'] = origWhiteColor; + args.text = name; + Context2D_DrawText(&ctx, &args, 0, 0); + } + Context2D_MakeTexture(&e->NameTex, &ctx); + Context2D_Free(&ctx); + } +} + +static void DrawName(struct Entity* e) { + struct VertexTextured* vertices; + struct Model* model; + struct Matrix mat; + Vec3 pos; + float scale; + Vec2 size; + + if (!e->VTABLE->ShouldRenderName(e)) return; + if (e->NameTex.X == NAME_IS_EMPTY) return; + if (!e->NameTex.ID) MakeNameTexture(e); + Gfx_BindTexture(e->NameTex.ID); + + if (!names_VB) + names_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, 4); + + model = e->Model; + Vec3_TransformY(&pos, model->GetNameY(e), &e->Transform); + + scale = model->nameScale * e->ModelScale.Y; + scale = scale > 1.0f ? (1.0f/70.0f) : (scale/70.0f); + size.X = e->NameTex.Width * scale; size.Y = e->NameTex.Height * scale; + + if (Entities.NamesMode == NAME_MODE_ALL_UNSCALED && LocalPlayer_Instance.Hacks.CanSeeAllNames) { + Matrix_Mul(&mat, &Gfx.View, &Gfx.Projection); /* TODO: This mul is slow, avoid it */ + /* Get W component of transformed position */ + scale = pos.X * mat.row1.W + pos.Y * mat.row2.W + pos.Z * mat.row3.W + mat.row4.W; + size.X *= scale * 0.2f; size.Y *= scale * 0.2f; + } + + Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); + + vertices = (struct VertexTextured*)Gfx_LockDynamicVb(names_VB, VERTEX_FORMAT_TEXTURED, 4); + Particle_DoRender(&size, &pos, &e->NameTex.uv, PACKEDCOL_WHITE, vertices); + Gfx_UnlockDynamicVb(names_VB); + + Gfx_DrawVb_IndexedTris(4); +} + +void EntityNames_Delete(struct Entity* e) { + Gfx_DeleteTexture(&e->NameTex.ID); + e->NameTex.X = 0; /* X is used as an 'empty name' flag */ +} + + +/*########################################################################################################################* +*-----------------------------------------------------Names rendering-----------------------------------------------------* +*#########################################################################################################################*/ +static EntityID closestEntityId; + +void EntityNames_Render(void) { + struct LocalPlayer* p = &LocalPlayer_Instance; + cc_bool hadFog; + int i; + + if (Entities.NamesMode == NAME_MODE_NONE) return; + closestEntityId = Entities_GetClosest(&p->Base); + if (!p->Hacks.CanSeeAllNames || Entities.NamesMode != NAME_MODE_ALL) return; + + Gfx_SetAlphaTest(true); + hadFog = Gfx_GetFog(); + if (hadFog) Gfx_SetFog(false); + + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + if (!Entities.List[i]) continue; + if (i != closestEntityId || i == ENTITIES_SELF_ID) { + DrawName(Entities.List[i]); + } + } + + Gfx_SetAlphaTest(false); + if (hadFog) Gfx_SetFog(true); +} + +void EntityNames_RenderHovered(void) { + struct LocalPlayer* p = &LocalPlayer_Instance; + cc_bool allNames, hadFog; + int i; + + if (Entities.NamesMode == NAME_MODE_NONE) return; + allNames = !(Entities.NamesMode == NAME_MODE_HOVERED || Entities.NamesMode == NAME_MODE_ALL) + && p->Hacks.CanSeeAllNames; + + Gfx_SetAlphaTest(true); + Gfx_SetDepthTest(false); + hadFog = Gfx_GetFog(); + if (hadFog) Gfx_SetFog(false); + + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + if (!Entities.List[i]) continue; + if ((i == closestEntityId || allNames) && i != ENTITIES_SELF_ID) { + DrawName(Entities.List[i]); + } + } + + Gfx_SetAlphaTest(false); + Gfx_SetDepthTest(true); + if (hadFog) Gfx_SetFog(true); +} + +static void DeleteAllNameTextures(void) { + int i; + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + if (!Entities.List[i]) continue; + EntityNames_Delete(Entities.List[i]); + } +} + +static void EntityNames_ChatFontChanged(void* obj) { + DeleteAllNameTextures(); +} + + /*########################################################################################################################* *-----------------------------------------------Entity renderers component------------------------------------------------* *#########################################################################################################################*/ static void EntityRenderers_ContextLost(void* obj) { Gfx_DeleteTexture(&shadows_tex); + Gfx_DeleteDynamicVb(&shadows_VB); + + Gfx_DeleteDynamicVb(&names_VB); + DeleteAllNameTextures(); } static void EntityRenderers_Init(void) { - Event_Register_(&GfxEvents.ContextLost, NULL, EntityRenderers_ContextLost); + Event_Register_(&GfxEvents.ContextLost, NULL, EntityRenderers_ContextLost); + Event_Register_(&ChatEvents.FontChanged, NULL, EntityNames_ChatFontChanged); } static void EntityRenderers_Free(void) { - Gfx_DeleteTexture(&shadows_tex); + EntityRenderers_ContextLost(NULL); } struct IGameComponent EntityRenderers_Component = { diff --git a/src/EntityRenderers.h b/src/EntityRenderers.h index a2f03131a..ab46eee46 100644 --- a/src/EntityRenderers.h +++ b/src/EntityRenderers.h @@ -1,13 +1,21 @@ #ifndef CC_ENTITYRENDERERS_H #define CC_ENTITYRENDERERS_H #include "Core.h" -/* Renders supporting objects for entities (shadows) +/* Renders supporting objects for entities (shadows and names) Copyright 2014-2023 ClassiCube | Licensed under BSD-3 */ struct IGameComponent; extern struct IGameComponent EntityRenderers_Component; +struct Entity; /* Draws shadows under entities, depending on Entities.ShadowsMode */ void EntityShadows_Render(void); +/* Deletes the texture containing the entity's nametag */ +void EntityNames_Delete(struct Entity* e); +/* Renders the name tags of entities, depending on Entities.NamesMode */ +void EntityNames_Render(void); +/* Renders hovered entity name tags (these appears through blocks) */ +void EntityNames_RenderHovered(void); + #endif diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index 8261cf78a..ce63c8378 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -272,11 +272,42 @@ static GfxResourceID skybox_tex, skybox_vb; #define SKYBOX_COUNT (6 * 4) cc_bool EnvRenderer_ShouldRenderSkybox(void) { return skybox_tex && !EnvRenderer_Minimal; } +static void AllocateSkyboxVB(void) { + static const struct VertexTextured vertices[SKYBOX_COUNT] = { + /* Front quad */ + { -1, -1, -1, 0, 0.25f, 1.00f }, { 1, -1, -1, 0, 0.50f, 1.00f }, + { 1, 1, -1, 0, 0.50f, 0.50f }, { -1, 1, -1, 0, 0.25f, 0.50f }, + /* Left quad */ + { -1, -1, 1, 0, 0.00f, 1.00f }, { -1, -1, -1, 0, 0.25f, 1.00f }, + { -1, 1, -1, 0, 0.25f, 0.50f }, { -1, 1, 1, 0, 0.00f, 0.50f }, + /* Back quad */ + { 1, -1, 1, 0, 0.75f, 1.00f }, { -1, -1, 1, 0, 1.00f, 1.00f }, + { -1, 1, 1, 0, 1.00f, 0.50f }, { 1, 1, 1, 0, 0.75f, 0.50f }, + /* Right quad */ + { 1, -1, -1, 0, 0.50f, 1.00f }, { 1, -1, 1, 0, 0.75f, 1.00f }, + { 1, 1, 1, 0, 0.75f, 0.50f }, { 1, 1, -1, 0, 0.50f, 0.50f }, + /* Top quad */ + { 1, 1, -1, 0, 0.50f, 0.50f }, { 1, 1, 1, 0, 0.50f, 0.00f }, + { -1, 1, 1, 0, 0.25f, 0.00f }, { -1, 1, -1, 0, 0.25f, 0.50f }, + /* Bottom quad */ + { 1, -1, -1, 0, 0.75f, 0.50f }, { 1, -1, 1, 0, 0.75f, 0.00f }, + { -1, -1, 1, 0, 0.50f, 0.00f }, { -1, -1, -1, 0, 0.50f, 0.50f }, + }; + struct VertexTextured* data; + int i; + + data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&skybox_vb, + VERTEX_FORMAT_TEXTURED, SKYBOX_COUNT); + Mem_Copy(data, vertices, sizeof(vertices)); + for (i = 0; i < SKYBOX_COUNT; i++) { data[i].Col = Env.SkyboxCol; } + Gfx_UnlockVb(skybox_vb); +} + void EnvRenderer_RenderSkybox(void) { struct Matrix m, rotX, rotY, view; float rotTime; Vec3 pos; - if (!skybox_vb) return; + if (!skybox_vb) AllocateSkyboxVB(); Gfx_SetDepthWrite(false); Gfx_BindTexture(skybox_tex); @@ -302,42 +333,6 @@ void EnvRenderer_RenderSkybox(void) { Gfx_SetDepthWrite(true); } -static void UpdateSkybox(void) { - static const struct VertexTextured vertices[SKYBOX_COUNT] = { - /* Front quad */ - { -1, -1, -1, 0, 0.25f, 1.00f }, { 1, -1, -1, 0, 0.50f, 1.00f }, - { 1, 1, -1, 0, 0.50f, 0.50f }, { -1, 1, -1, 0, 0.25f, 0.50f }, - /* Left quad */ - { -1, -1, 1, 0, 0.00f, 1.00f }, { -1, -1, -1, 0, 0.25f, 1.00f }, - { -1, 1, -1, 0, 0.25f, 0.50f }, { -1, 1, 1, 0, 0.00f, 0.50f }, - /* Back quad */ - { 1, -1, 1, 0, 0.75f, 1.00f }, { -1, -1, 1, 0, 1.00f, 1.00f }, - { -1, 1, 1, 0, 1.00f, 0.50f }, { 1, 1, 1, 0, 0.75f, 0.50f }, - /* Right quad */ - { 1, -1, -1, 0, 0.50f, 1.00f }, { 1, -1, 1, 0, 0.75f, 1.00f }, - { 1, 1, 1, 0, 0.75f, 0.50f }, { 1, 1, -1, 0, 0.50f, 0.50f }, - /* Top quad */ - { 1, 1, -1, 0, 0.50f, 0.50f }, { 1, 1, 1, 0, 0.50f, 0.00f }, - { -1, 1, 1, 0, 0.25f, 0.00f }, { -1, 1, -1, 0, 0.25f, 0.50f }, - /* Bottom quad */ - { 1, -1, -1, 0, 0.75f, 0.50f }, { 1, -1, 1, 0, 0.75f, 0.00f }, - { -1, -1, 1, 0, 0.50f, 0.00f }, { -1, -1, -1, 0, 0.50f, 0.50f }, - }; - struct VertexTextured* data; - int i; - - Gfx_DeleteVb(&skybox_vb); - if (Gfx.LostContext) return; - if (EnvRenderer_Minimal) return; - - data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&skybox_vb, - VERTEX_FORMAT_TEXTURED, SKYBOX_COUNT); - Mem_Copy(data, vertices, sizeof(vertices)); - for (i = 0; i < SKYBOX_COUNT; i++) { data[i].Col = Env.SkyboxCol; } - Gfx_UnlockVb(skybox_vb); -} - - /*########################################################################################################################* *----------------------------------------------------------Weather--------------------------------------------------------* *#########################################################################################################################*/ @@ -347,7 +342,10 @@ static double weather_accumulator; static IVec3 lastPos; #define WEATHER_EXTENT 4 -#define WEATHER_VERTS_COUNT 8 * (WEATHER_EXTENT * 2 + 1) * (WEATHER_EXTENT * 2 + 1) +#define WEATHER_VERTS 8 /* 2 quads per tile */ +#define WEATHER_RANGE (WEATHER_EXTENT * 2 + 1) + +#define WEATHER_VERTS_COUNT WEATHER_RANGE * WEATHER_RANGE * WEATHER_VERTS #define Weather_Pack(x, z) ((x) * World.Length + (z)) static void InitWeatherHeightmap(void) { @@ -428,26 +426,31 @@ static float CalcRainAlphaAt(float x) { return 178 + falloff * Env.WeatherFade; } +struct RainCoord { int dx, dz; float y; }; static RNGState snowDirRng; + void EnvRenderer_RenderWeather(double deltaTime) { - struct VertexTextured vertices[WEATHER_VERTS_COUNT]; + struct RainCoord coords[WEATHER_RANGE * WEATHER_RANGE]; + int i, weather, numCoords = 0; struct VertexTextured* v; - int weather, vCount; - IVec3 pos; cc_bool moved, particles; float speed, vOffsetBase, vOffset; + IVec3 pos; - PackedCol col; + PackedCol color; int dist, dx, dz, x, z; float alpha, y, height; - float uOffset1, uOffset2; + float uOffset1, uOffset2, uSpeed; float worldV, v1, v2, vPlane1Offset; float x1,y1,z1, x2,y2,z2; weather = Env.Weather; if (weather == WEATHER_SUNNY) return; - if (!Weather_Heightmap) InitWeatherHeightmap(); - Gfx_BindTexture(weather == WEATHER_RAINY ? rain_tex : snow_tex); + + if (!Weather_Heightmap) + InitWeatherHeightmap(); + if (!weather_vb) + weather_vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, WEATHER_VERTS_COUNT); IVec3_Floor(&pos, &Camera.CurrentPos); moved = pos.X != lastPos.X || pos.Y != lastPos.Y || pos.Z != lastPos.Z; @@ -457,75 +460,93 @@ void EnvRenderer_RenderWeather(double deltaTime) { pos.Y += 64; pos.Y = max(World.Height, pos.Y); - speed = (weather == WEATHER_RAINY ? 1.0f : 0.2f) * Env.WeatherSpeed; - vOffsetBase = (float)Game.Time * speed; - vPlane1Offset = weather == WEATHER_RAINY ? 0 : 0.25f; /* Offset v on 1 plane while snowing to avoid the unnatural mirrored texture effect */ - particles = weather == WEATHER_RAINY; weather_accumulator += deltaTime; - - v = vertices; - col = Env.SunCol; + particles = weather == WEATHER_RAINY && (weather_accumulator >= 0.25 || moved); for (dx = -WEATHER_EXTENT; dx <= WEATHER_EXTENT; dx++) { for (dz = -WEATHER_EXTENT; dz <= WEATHER_EXTENT; dz++) { x = pos.X + dx; z = pos.Z + dz; y = GetRainHeight(x, z); - height = pos.Y - y; - if (height <= 0) continue; + if (pos.Y <= y) continue; + if (particles) Particles_RainSnowEffect((float)x, y, (float)z); - if (particles && (weather_accumulator >= 0.25 || moved)) { - Particles_RainSnowEffect((float)x, y, (float)z); - } - - dist = dx * dx + dz * dz; - alpha = CalcRainAlphaAt((float)dist); - Math_Clamp(alpha, 0.0f, 255.0f); - col = (col & PACKEDCOL_RGB_MASK) | PackedCol_A_Bits(alpha); - - uOffset1 = 0; - uOffset2 = 0; - if (weather == WEATHER_SNOWY) { - Random_Seed(&snowDirRng, (x + 1217 * z) & 0x7fffffff); - /* Multiply horizontal speed by a random float from -1 to 1 */ - uOffset1 = ((float)Game.Time * (Random_Float(&snowDirRng) * 2 + -1)) * Env.WeatherSpeed * 0.5f; - uOffset2 = ((float)Game.Time * (Random_Float(&snowDirRng) * 2 + -1)) * Env.WeatherSpeed * 0.5f; - /* Multiply vertical speed by a random float from 1.0 to 0.25 */ - vOffset = vOffsetBase * (float)(Random_Float(&snowDirRng) * (1.0f - 0.25f) + 0.25f); - } else { - vOffset = vOffsetBase; - } - - worldV = vOffset + (z & 1) / 2.0f - (x & 0x0F) / 16.0f; - v1 = y / 6.0f + worldV; - v2 = (y + height) / 6.0f + worldV; - x1 = (float)x; y1 = (float)y; z1 = (float)z; - x2 = (float)(x + 1); y2 = (float)(y + height); z2 = (float)(z + 1); - - v->X = x1; v->Y = y1; v->Z = z1; v->Col = col; v->U = 0.0f + uOffset1; v->V = v1+vPlane1Offset; v++; - v->X = x1; v->Y = y2; v->Z = z1; v->Col = col; v->U = 0.0f + uOffset1; v->V = v2+vPlane1Offset; v++; - v->X = x2; v->Y = y2; v->Z = z2; v->Col = col; v->U = 1.0f + uOffset1; v->V = v2+vPlane1Offset; v++; - v->X = x2; v->Y = y1; v->Z = z2; v->Col = col; v->U = 1.0f + uOffset1; v->V = v1+vPlane1Offset; v++; - - v->X = x2; v->Y = y1; v->Z = z1; v->Col = col; v->U = 1.0f + uOffset2; v->V = v1; v++; - v->X = x2; v->Y = y2; v->Z = z1; v->Col = col; v->U = 1.0f + uOffset2; v->V = v2; v++; - v->X = x1; v->Y = y2; v->Z = z2; v->Col = col; v->U = 0.0f + uOffset2; v->V = v2; v++; - v->X = x1; v->Y = y1; v->Z = z2; v->Col = col; v->U = 0.0f + uOffset2; v->V = v1; v++; + coords[numCoords].dx = dx; + coords[numCoords].y = y; + coords[numCoords].dz = dz; + numCoords++; } } - if (particles && (weather_accumulator >= 0.25f || moved)) { - weather_accumulator = 0; - } - if (v == vertices) return; + Gfx_BindTexture(weather == WEATHER_RAINY ? rain_tex : snow_tex); + if (particles) weather_accumulator = 0; + if (!numCoords) return; Gfx_SetAlphaTest(false); Gfx_SetDepthWrite(false); Gfx_SetAlphaArgBlend(true); Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); - vCount = (int)(v - vertices); - Gfx_UpdateDynamicVb_IndexedTris(weather_vb, vertices, vCount); + v = (struct VertexTextured*)Gfx_LockDynamicVb(weather_vb, + VERTEX_FORMAT_TEXTURED, numCoords * WEATHER_VERTS); + + color = Env.SunCol; + speed = (weather == WEATHER_RAINY ? 1.0f : 0.2f) * Env.WeatherSpeed; + + vOffsetBase = (float)Game.Time * speed; + vPlane1Offset = weather == WEATHER_RAINY ? 0 : 0.25f; /* Offset v on 1 plane while snowing to avoid the unnatural mirrored texture effect */ + + for (i = 0; i < numCoords; i++) + { + dx = coords[i].dx; + y = coords[i].y; + dz = coords[i].dz; + + height = pos.Y - y; + + dist = dx * dx + dz * dz; + alpha = CalcRainAlphaAt((float)dist); + Math_Clamp(alpha, 0.0f, 255.0f); + color = (color & PACKEDCOL_RGB_MASK) | PackedCol_A_Bits(alpha); + + x = dx + pos.X; + z = dz + pos.Z; + + uOffset1 = 0; + uOffset2 = 0; + if (weather == WEATHER_SNOWY) { + Random_Seed(&snowDirRng, (x + 1217 * z) & 0x7fffffff); + + /* Multiply horizontal speed by a random float from -1 to 1 */ + uSpeed = (float)Game.Time * Env.WeatherSpeed * 0.5f; + uOffset1 = uSpeed * (Random_Float(&snowDirRng) * 2 + -1); + uOffset2 = uSpeed * (Random_Float(&snowDirRng) * 2 + -1); + + /* Multiply vertical speed by a random float from 1.0 to 0.25 */ + vOffset = vOffsetBase * (float)(Random_Float(&snowDirRng) * (1.0f - 0.25f) + 0.25f); + } else { + vOffset = vOffsetBase; + } + + worldV = vOffset + (z & 1) / 2.0f - (x & 0x0F) / 16.0f; + v1 = y / 6.0f + worldV; + v2 = (y + height) / 6.0f + worldV; + x1 = (float)x; y1 = (float)y; z1 = (float)z; + x2 = (float)(x + 1); y2 = (float)(y + height); z2 = (float)(z + 1); + + v->X = x1; v->Y = y1; v->Z = z1; v->Col = color; v->U = uOffset1; v->V = v1 + vPlane1Offset; v++; + v->X = x1; v->Y = y2; v->Z = z1; v->Col = color; v->U = uOffset1; v->V = v2 + vPlane1Offset; v++; + v->X = x2; v->Y = y2; v->Z = z2; v->Col = color; v->U = uOffset1 + 1.0f; v->V = v2 + vPlane1Offset; v++; + v->X = x2; v->Y = y1; v->Z = z2; v->Col = color; v->U = uOffset1 + 1.0f; v->V = v1 + vPlane1Offset; v++; + + v->X = x2; v->Y = y1; v->Z = z1; v->Col = color; v->U = uOffset2 + 1.0f; v->V = v1; v++; + v->X = x2; v->Y = y2; v->Z = z1; v->Col = color; v->U = uOffset2 + 1.0f; v->V = v2; v++; + v->X = x1; v->Y = y2; v->Z = z2; v->Col = color; v->U = uOffset2; v->V = v2; v++; + v->X = x1; v->Y = y1; v->Z = z2; v->Col = color; v->U = uOffset2; v->V = v1; v++; + } + + Gfx_UnlockDynamicVb(weather_vb); + Gfx_DrawVb_IndexedTris(numCoords * WEATHER_VERTS); Gfx_SetAlphaArgBlend(false); Gfx_SetDepthWrite(true); @@ -808,13 +829,12 @@ static void UpdateAll(void) { UpdateMapEdges(); UpdateClouds(); UpdateSky(); - UpdateSkybox(); + Gfx_DeleteVb(&skybox_vb); EnvRenderer_UpdateFog(); Gfx_DeleteDynamicVb(&weather_vb); + /* TODO: Unnecessary to delete the weather VB? */ if (Gfx.LostContext) return; - /* TODO: Don't allocate unless used? */ - Gfx_RecreateDynamicVb(&weather_vb, VERTEX_FORMAT_TEXTURED, WEATHER_VERTS_COUNT); /* TODO: Don't need to do this on every new map */ UpdateBorderTextures(); } @@ -873,7 +893,7 @@ static void OnEnvVariableChanged(void* obj, int envVar) { UpdateSky(); UpdateClouds(); } else if (envVar == ENV_VAR_SKYBOX_COLOR) { - UpdateSkybox(); + Gfx_DeleteVb(&skybox_vb); } } diff --git a/src/Game.c b/src/Game.c index aedc766ce..a197fdb0b 100644 --- a/src/Game.c +++ b/src/Game.c @@ -463,7 +463,7 @@ static void Game_Render3D(double delta, float t) { AxisLinesRenderer_Render(); Entities_RenderModels(delta, t); - Entities_RenderNames(); + EntityNames_Render(); Particles_Render(t); Camera.Active->GetPickedBlock(&Game_SelectedPos); /* TODO: only pick when necessary */ @@ -496,7 +496,7 @@ static void Game_Render3D(double delta, float t) { } Selections_Render(); - Entities_RenderHoveredNames(); + EntityNames_RenderHovered(); Camera_KeyLookUpdate(); InputHandler_Tick(); if (!Game_HideGui) HeldBlockRenderer_Render(delta); @@ -573,6 +573,7 @@ static void Game_RenderFrame(double delta) { Gfx_RecreateContext(); /* all good, context is back */ } else { + Game.Time += delta; /* TODO: Not set in two places? */ Server.Tick(NULL); Thread_Sleep(16); return; diff --git a/src/Graphics.h b/src/Graphics.h index f940bdade..8bd0116c0 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -25,14 +25,14 @@ typedef enum MatrixType_ { #define SIZEOF_VERTEX_TEXTURED 24 #if defined CC_BUILD_PSP -/* 3 floats for position (XYZ), 4 bytes for colour. */ +/* 3 floats for position (XYZ), 4 bytes for colour */ struct VertexColoured { PackedCol Col; float X, Y, Z; }; -/* 3 floats for position (XYZ), 2 floats for texture coordinates (UV), 4 bytes for colour. */ +/* 3 floats for position (XYZ), 2 floats for texture coordinates (UV), 4 bytes for colour */ struct VertexTextured { float U, V; PackedCol Col; float X, Y, Z; }; #else -/* 3 floats for position (XYZ), 4 bytes for colour. */ +/* 3 floats for position (XYZ), 4 bytes for colour */ struct VertexColoured { float X, Y, Z; PackedCol Col; }; -/* 3 floats for position (XYZ), 2 floats for texture coordinates (UV), 4 bytes for colour. */ +/* 3 floats for position (XYZ), 2 floats for texture coordinates (UV), 4 bytes for colour */ struct VertexTextured { float X, Y, Z; PackedCol Col; float U, V; }; #endif @@ -45,9 +45,9 @@ CC_VAR extern struct _GfxData { float _unused; /* Whether context graphics has been lost (all creation/render calls fail) */ cc_bool LostContext; - /* Whether some textures are created with mipmaps. */ + /* Whether some textures are created with mipmaps */ cc_bool Mipmaps; - /* Whether managed textures are actually supported. */ + /* Whether managed textures are actually supported */ /* If not, you must free/create them just like normal textures */ cc_bool ManagedTextures; /* Whether graphics context has been created */ @@ -56,7 +56,6 @@ CC_VAR extern struct _GfxData { } Gfx; extern GfxResourceID Gfx_defaultIb; -extern GfxResourceID Gfx_quadVb, Gfx_texVb; extern const cc_string Gfx_LowPerfMessage; #define ICOUNT(verticesCount) (((verticesCount) >> 2) * 6) @@ -77,58 +76,58 @@ void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count); /* 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 -use mipmapping may be either a per-texture or global state depending on the backend. */ +use mipmapping may be either a per-texture or global state depending on the backend */ CC_API GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps); /* Updates a region of the given texture. (and mipmapped regions if mipmaps) */ CC_API void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, struct Bitmap* part, cc_bool mipmaps); /* Updates a region of the given texture. (and mipmapped regions if mipmaps) */ /* NOTE: rowWidth is in pixels (so for normal bitmaps, rowWidth equals width) */ /* OBSOLETE */ void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps); -/* Sets the currently active texture. */ +/* Sets the currently active texture */ CC_API void Gfx_BindTexture(GfxResourceID texId); -/* Deletes the given texture, then sets it to 0. */ +/* 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); /* Turns on mipmapping. (if Gfx_Mipmaps is enabled) */ -/* NOTE: You must have created textures with mipmaps true for this to work. */ +/* NOTE: You must have created textures with mipmaps true for this to work */ CC_API void Gfx_EnableMipmaps(void); /* Turns off mipmapping. (if Gfx_Mipmaps is enabled) */ -/* NOTE: You must have created textures with mipmaps true for this to work. */ +/* NOTE: You must have created textures with mipmaps true for this to work */ CC_API void Gfx_DisableMipmaps(void); -/* Returns whether fog blending is enabled. */ +/* Returns whether fog blending is enabled */ CC_API cc_bool Gfx_GetFog(void); -/* Sets whether fog blending is enabled. */ +/* Sets whether fog blending is enabled */ CC_API void Gfx_SetFog(cc_bool enabled); -/* Sets the colour of the blended fog. */ +/* Sets the colour of the blended fog */ CC_API void Gfx_SetFogCol(PackedCol col); -/* Sets thickness of fog for FOG_EXP/FOG_EXP2 modes. */ +/* Sets thickness of fog for FOG_EXP/FOG_EXP2 modes */ CC_API void Gfx_SetFogDensity(float value); -/* Sets extent/end of fog for FOG_LINEAR mode. */ +/* Sets extent/end of fog for FOG_LINEAR mode */ CC_API void Gfx_SetFogEnd(float value); -/* Sets in what way fog is blended. */ +/* Sets in what way fog is blended */ CC_API void Gfx_SetFogMode(FogFunc func); -/* Sets whether backface culling is performed. */ +/* Sets whether backface culling is performed */ CC_API void Gfx_SetFaceCulling(cc_bool enabled); -/* Sets whether pixels with an alpha of less than 128 are discarded. */ +/* Sets whether pixels with an alpha of less than 128 are discarded */ CC_API void Gfx_SetAlphaTest(cc_bool enabled); -/* Sets whether existing and new pixels are blended together. */ +/* Sets whether existing and new pixels are blended together */ CC_API void Gfx_SetAlphaBlending(cc_bool enabled); -/* Sets whether blending between the alpha components of texture and vertex colour is performed. */ +/* Sets whether blending between the alpha components of texture and vertex colour is performed */ CC_API void Gfx_SetAlphaArgBlend(cc_bool enabled); -/* Clears the colour and depth buffer to default. */ +/* Clears the colour and depth buffer to default */ CC_API void Gfx_Clear(void); -/* Sets the colour that the colour buffer is cleared to. */ +/* Sets the colour that the colour buffer is cleared to */ CC_API void Gfx_ClearCol(PackedCol col); -/* Sets whether pixels may be discard based on z/depth. */ +/* Sets whether pixels may be discard based on z/depth */ CC_API void Gfx_SetDepthTest(cc_bool enabled); -/* Sets whether R/G/B/A of pixels are actually written to the colour buffer channels. */ +/* Sets whether R/G/B/A of pixels are actually written to the colour buffer channels */ CC_API void Gfx_SetColWriteMask(cc_bool r, cc_bool g, cc_bool b, cc_bool a); -/* Sets whether z/depth of pixels is actually written to the depth buffer. */ +/* Sets whether z/depth of pixels is actually written to the depth buffer */ CC_API void Gfx_SetDepthWrite(cc_bool enabled); /* Sets whether the game should only write output to depth buffer */ /* NOTE: Implicitly calls Gfx_SetColWriteMask */ @@ -136,25 +135,25 @@ CC_API void Gfx_DepthOnlyRendering(cc_bool depthOnly); /* Callback function to initialise/fill out the contents of an index buffer */ typedef void (*Gfx_FillIBFunc)(cc_uint16* indices, int count, void* obj); -/* Creates a new index buffer and fills out its contents. */ +/* Creates a new index buffer and fills out its contents */ CC_API GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj); -/* Sets the currently active index buffer. */ +/* Sets the currently active index buffer */ CC_API void Gfx_BindIb(GfxResourceID ib); -/* Deletes the given index buffer, then sets it to 0. */ +/* Deletes the given index buffer, then sets it to 0 */ CC_API void Gfx_DeleteIb(GfxResourceID* ib); -/* Creates a new vertex buffer. */ +/* Creates a new vertex buffer */ CC_API GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count); -/* Sets the currently active vertex buffer. */ +/* Sets the currently active vertex buffer */ CC_API void Gfx_BindVb(GfxResourceID vb); -/* Deletes the given vertex buffer, then sets it to 0. */ +/* Deletes the given vertex buffer, then sets it to 0 */ CC_API void Gfx_DeleteVb(GfxResourceID* vb); -/* Acquires temp memory for changing the contents of a vertex buffer. */ +/* Acquires temp memory for changing the contents of a vertex buffer */ CC_API void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count); -/* Submits the changed contents of a vertex buffer. */ +/* Submits the changed contents of a vertex buffer */ CC_API void Gfx_UnlockVb(GfxResourceID vb); -/* TODO: How to make LockDynamicVb work with OpenGL 1.1 Builder stupidity.. */ +/* TODO: How to make LockDynamicVb work with OpenGL 1.1 Builder stupidity. */ #ifdef CC_BUILD_GL11 /* Special case of Gfx_Create/LockVb for building chunks in Builder.c */ GfxResourceID Gfx_CreateVb2(void* vertices, VertexFormat fmt, int count); @@ -166,39 +165,34 @@ void Gfx_BindVb_Textured(GfxResourceID vb); #define Gfx_BindVb_Textured Gfx_BindVb #endif -/* Creates a new dynamic vertex buffer, whose contents can be updated later. */ +/* Creates a new dynamic vertex buffer, whose contents can be updated later */ CC_API GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices); -#ifndef CC_BUILD_GL11 -/* Static and dynamic vertex buffers are drawn in the same way */ -#define Gfx_BindDynamicVb Gfx_BindVb -#define Gfx_DeleteDynamicVb Gfx_DeleteVb -#else -/* OpenGL 1.1 draws static vertex buffers completely differently. */ -void Gfx_BindDynamicVb(GfxResourceID vb); -void Gfx_DeleteDynamicVb(GfxResourceID* vb); -#endif -/* Acquires temp memory for changing the contents of a dynamic vertex buffer. */ +/* Sets the active vertex buffer to the given dynamic vertex buffer */ +CC_API void Gfx_BindDynamicVb(GfxResourceID vb); +/* Deletes the given dynamic vertex buffer, then sets it to 0 */ +CC_API void Gfx_DeleteDynamicVb(GfxResourceID* vb); +/* Acquires temp memory for changing the contents of a dynamic vertex buffer */ CC_API void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count); -/* Binds then submits the changed contents of a dynamic vertex buffer. */ +/* Binds then submits the changed contents of a dynamic vertex buffer */ CC_API void Gfx_UnlockDynamicVb(GfxResourceID vb); -/* Sets the format of the rendered vertices. */ +/* Sets the format of the rendered vertices */ CC_API void Gfx_SetVertexFormat(VertexFormat fmt); -/* Updates the data of a dynamic vertex buffer. */ +/* Updates the data of a dynamic vertex buffer */ CC_API void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount); -/* Renders vertices from the currently bound vertex buffer as lines. */ +/* Renders vertices from the currently bound vertex buffer as lines */ CC_API void Gfx_DrawVb_Lines(int verticesCount); -/* Renders vertices from the currently bound vertex and index buffer as triangles. */ -/* NOTE: Offsets each index by startVertex. */ +/* Renders vertices from the currently bound vertex and index buffer as triangles */ +/* NOTE: Offsets each index by startVertex */ CC_API void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex); -/* Renders vertices from the currently bound vertex and index buffer as triangles. */ +/* Renders vertices from the currently bound vertex and index buffer as triangles */ CC_API void Gfx_DrawVb_IndexedTris(int verticesCount); /* Special case Gfx_DrawVb_IndexedTris_Range for map renderer */ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex); -/* Loads the given matrix over the currently active matrix. */ +/* Loads the given matrix over the currently active matrix */ CC_API void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix); -/* Loads the identity matrix over the currently active matrix. */ +/* Loads the identity matrix over the currently active matrix */ CC_API void Gfx_LoadIdentityMatrix(MatrixType type); CC_API void Gfx_EnableTextureOffset(float x, float y); CC_API void Gfx_DisableTextureOffset(void); @@ -210,56 +204,52 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f /* NOTE: Projection matrix calculation is here because it can depend the graphics backend */ /* (e.g. OpenGL uses a Z clip space range of [-1, 1], whereas Direct3D9 uses [0, 1]) */ -/* Outputs a .png screenshot of the backbuffer. */ +/* Outputs a .png screenshot of the backbuffer */ cc_result Gfx_TakeScreenshot(struct Stream* output); -/* Warns in chat if the backend has problems with the user's GPU. */ -/* Returns whether legacy rendering mode for borders/sky/clouds is needed. */ +/* Warns in chat if the backend has problems with the user's GPU */ +/* Returns whether legacy rendering mode for borders/sky/clouds is needed */ cc_bool Gfx_WarnIfNecessary(void); -/* Sets up state for rendering a new frame. */ +/* Sets up state for rendering a new frame */ void Gfx_BeginFrame(void); -/* Finishes rendering a frame, and swaps it with the back buffer. */ +/* Finishes rendering a frame, and swaps it with the back buffer */ void Gfx_EndFrame(void); -/* Sets whether to synchronise with monitor refresh to avoid tearing, and maximum frame rate. */ -/* NOTE: VSync setting may be unsupported or just ignored. */ +/* Sets whether to synchronise with monitor refresh to avoid tearing, and maximum frame rate */ +/* NOTE: VSync setting may be unsupported or just ignored */ void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMillis); -/* Updates state when the window's dimensions have changed. */ -/* NOTE: This may require recreating the context depending on the backend. */ +/* Updates state when the window's dimensions have changed */ +/* NOTE: This may require recreating the context depending on the backend */ void Gfx_OnWindowResize(void); -/* Gets information about the user's GPU and current backend state. */ -/* Backend state may include depth buffer bits, free memory, etc. */ -/* NOTE: Each line is separated by \n. */ +/* Gets information about the user's GPU and current backend state */ +/* Backend state may include depth buffer bits, free memory, etc */ +/* NOTE: Each line is separated by \n */ void Gfx_GetApiInfo(cc_string* info); -/* Raises ContextLost event and updates state for lost contexts. */ +/* Raises ContextLost event and updates state for lost contexts */ void Gfx_LoseContext(const char* reason); -/* Raises ContextRecreated event and restores internal state. */ +/* Raises ContextRecreated event and restores internal state */ void Gfx_RecreateContext(void); -/* Attempts to restore a lost context. */ +/* Attempts to restore a lost context */ cc_bool Gfx_TryRestoreContext(void); -/* Binds and draws the specified subset of the vertices in the current dynamic vertex buffer. */ -/* NOTE: This replaces the dynamic vertex buffer's data first with the given vertices before drawing. */ -void Gfx_UpdateDynamicVb_IndexedTris(GfxResourceID vb, void* vertices, int vCount); - -/* Renders a 2D flat coloured rectangle. */ +/* Renders a 2D flat coloured rectangle */ void Gfx_Draw2DFlat(int x, int y, int width, int height, PackedCol color); -/* Renders a 2D flat vertical gradient rectangle. */ +/* Renders a 2D flat vertical gradient rectangle */ void Gfx_Draw2DGradient(int x, int y, int width, int height, PackedCol top, PackedCol bottom); -/* Renders a 2D coloured texture. */ +/* Renders a 2D coloured texture */ void Gfx_Draw2DTexture(const struct Texture* tex, PackedCol color); -/* Fills out the vertices for rendering a 2D coloured texture. */ +/* Fills out the vertices for rendering a 2D coloured texture */ void Gfx_Make2DQuad(const struct Texture* tex, PackedCol color, struct VertexTextured** vertices); -/* Switches state to be suitable for drawing 2D graphics. */ +/* Switches state to be suitable for drawing 2D graphics */ /* NOTE: This means turning off fog/depth test, changing matrices, etc.*/ void Gfx_Begin2D(int width, int height); -/* Switches state to be suitable for drawing 3D graphics. */ -/* NOTE: This means restoring fog/depth test, restoring matrices, etc. */ +/* Switches state to be suitable for drawing 3D graphics */ +/* NOTE: This means restoring fog/depth test, restoring matrices, etc */ void Gfx_End2D(void); -/* Sets appropriate alpha test/blending for given block draw type. */ +/* Sets appropriate alpha test/blending for given block draw type */ void Gfx_SetupAlphaState(cc_uint8 draw); -/* Undoes changes to alpha test/blending state by Gfx_SetupAlphaState. */ +/* Undoes changes to alpha test/blending state by Gfx_SetupAlphaState */ void Gfx_RestoreAlphaState(cc_uint8 draw); /* Statically initialises the position and dimensions of this texture */ @@ -272,8 +262,8 @@ void Gfx_RestoreAlphaState(cc_uint8 draw); /* Useful to only draw a sub-region of the texture's pixels */ #define Tex_SetUV(tex, u1,v1, u2,v2) tex.uv.U1 = u1; tex.uv.V1 = v1; tex.uv.U2 = u2; tex.uv.V2 = v2; -/* Binds then renders the given texture. */ +/* Binds then renders the given texture */ void Texture_Render(const struct Texture* tex); -/* Binds then renders the given texture. */ +/* Binds then renders the given texture */ void Texture_RenderShaded(const struct Texture* tex, PackedCol shadeColor); #endif diff --git a/src/Graphics_3DS.c b/src/Graphics_3DS.c index 6191e3d61..f12287ea9 100644 --- a/src/Graphics_3DS.c +++ b/src/Graphics_3DS.c @@ -228,7 +228,7 @@ static void ToMortonTexture(C3D_Tex* tex, int originX, int originY, } -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { C3D_Tex* tex = Mem_Alloc(1, sizeof(C3D_Tex), "GPU texture desc"); bool success = C3D_TexInit(tex, bmp->width, bmp->height, GPU_RGBA8); //if (!success) Logger_Abort("Failed to create 3DS texture"); @@ -379,12 +379,9 @@ static cc_uint8* gfx_vertices; static cc_uint16* gfx_indices; static void* AllocBuffer(int count, int elemSize) { - void* ptr = linearAlloc(count * elemSize); + return linearAlloc(count * elemSize); //cc_uintptr addr = ptr; //Platform_Log3("BUFFER CREATE: %i X %i = %x", &count, &elemSize, &addr); - - if (!ptr) Logger_Abort("Failed to allocate memory for buffer"); - return ptr; } static void FreeBuffer(GfxResourceID* buffer) { @@ -396,6 +393,8 @@ static void FreeBuffer(GfxResourceID* buffer) { GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { void* ib = AllocBuffer(count, sizeof(cc_uint16)); + if (!ib) Logger_Abort("Failed to allocate memory for index buffer"); + fillFunc(ib, count, obj); return ib; } @@ -405,7 +404,7 @@ void Gfx_BindIb(GfxResourceID ib) { gfx_indices = ib; } void Gfx_DeleteIb(GfxResourceID* ib) { FreeBuffer(ib); } -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return AllocBuffer(count, strideSizes[fmt]); } @@ -431,10 +430,12 @@ void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { void Gfx_UnlockVb(GfxResourceID vb) { gfx_vertices = vb; } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return AllocBuffer(maxVertices, strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } diff --git a/src/Graphics_D3D11.c b/src/Graphics_D3D11.c index 8d020abdc..f26fc3115 100644 --- a/src/Graphics_D3D11.c +++ b/src/Graphics_D3D11.c @@ -2,7 +2,6 @@ #ifdef CC_BUILD_D3D11 #include "_GraphicsBase.h" #include "Errors.h" -#include "Logger.h" #include "Window.h" #include "_D3D11Shaders.h" @@ -202,16 +201,11 @@ static void D3D11_DoMipmaps(ID3D11Resource* texture, int x, int y, struct Bitmap if (prev != bmp->scan0) Mem_Free(prev); } -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { ID3D11Texture2D* tex = NULL; ID3D11ShaderResourceView* view = NULL; HRESULT hr; - if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) { - Logger_Abort("Textures must have power of two dimensions"); - } - if (Gfx.LostContext) return 0; - D3D11_TEXTURE2D_DESC desc = { 0 }; desc.Width = bmp->width; desc.Height = bmp->height; @@ -343,11 +337,11 @@ static ID3D11Buffer* CreateVertexBuffer(VertexFormat fmt, int count, cc_bool dyn /* TODO set data initially */ HRESULT hr = ID3D11Device_CreateBuffer(device, &desc, NULL, &buffer); - if (hr) Logger_Abort2(hr, "Failed to create index buffer"); + if (hr) Logger_Abort2(hr, "Failed to create vertex buffer"); return buffer; } -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { /* TODO immutable? */ return CreateVertexBuffer(fmt, count, false); } @@ -371,6 +365,46 @@ void Gfx_UnlockVb(GfxResourceID vb) { tmp = NULL; } + +/*########################################################################################################################* +*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return CreateVertexBuffer(fmt, maxVertices, true); +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { + ID3D11Buffer* buffer = (ID3D11Buffer*)(*vb); + if (buffer) ID3D11Buffer_Release(buffer); + *vb = NULL; +} + +static D3D11_MAPPED_SUBRESOURCE mapDesc; +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + ID3D11Buffer* buffer = (ID3D11Buffer*)vb; + mapDesc.pData = NULL; + + HRESULT hr = ID3D11DeviceContext_Map(context, buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapDesc); + if (hr) Logger_Abort2(hr, "Failed to lock dynamic VB"); + return mapDesc.pData; +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + ID3D11Buffer* buffer = (ID3D11Buffer*)vb; + ID3D11DeviceContext_Unmap(context, buffer, 0); + Gfx_BindDynamicVb(vb); +} + +void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { + void* data = Gfx_LockDynamicVb(vb, gfx_format, vCount); + Mem_Copy(data, vertices, vCount * gfx_stride); + Gfx_UnlockDynamicVb(vb); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Vertex rendering----------------------------------------------------* +*#########################################################################################################################*/ void Gfx_SetVertexFormat(VertexFormat fmt) { if (fmt == gfx_format) return; gfx_format = fmt; @@ -400,37 +434,6 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { } -/*########################################################################################################################* -*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------* -*#########################################################################################################################*/ -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - // TODO pass true instead - return CreateVertexBuffer(fmt, maxVertices, true); -} - -static D3D11_MAPPED_SUBRESOURCE mapDesc; -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - ID3D11Buffer* buffer = (ID3D11Buffer*)vb; - mapDesc.pData = NULL; - - HRESULT hr = ID3D11DeviceContext_Map(context, buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapDesc); - if (hr) Logger_Abort2(hr, "Failed to lock dynamic VB"); - return mapDesc.pData; -} - -void Gfx_UnlockDynamicVb(GfxResourceID vb) { - ID3D11Buffer* buffer = (ID3D11Buffer*)vb; - ID3D11DeviceContext_Unmap(context, buffer, 0); - Gfx_BindVb(vb); -} - -void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { - void* data = Gfx_LockDynamicVb(vb, gfx_format, vCount); - Mem_Copy(data, vertices, vCount * gfx_stride); - Gfx_UnlockDynamicVb(vb); -} - - /*########################################################################################################################* *---------------------------------------------------------Matrices--------------------------------------------------------* *#########################################################################################################################*/ @@ -517,6 +520,12 @@ void Gfx_BindVb(GfxResourceID vb) { ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &buffer, &gfx_stride, offset); } +void Gfx_BindDynamicVb(GfxResourceID vb) { + ID3D11Buffer* buffer = (ID3D11Buffer*)vb; + static UINT32 offset[] = { 0 }; + ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &buffer, &gfx_stride, offset); +} + //######################################################################################################################## //--------------------------------------------------------Vertex shader--------------------------------------------------- diff --git a/src/Graphics_D3D9.c b/src/Graphics_D3D9.c index 436f75b21..187223d6d 100644 --- a/src/Graphics_D3D9.c +++ b/src/Graphics_D3D9.c @@ -2,7 +2,6 @@ #ifdef CC_BUILD_D3D9 #include "_GraphicsBase.h" #include "Errors.h" -#include "Logger.h" #include "Window.h" /* Avoid pointless includes */ @@ -19,7 +18,7 @@ /* https://docs.microsoft.com/en-us/windows/win32/dxtecharts/the-direct3d-transformation-pipeline */ /* https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dfvf-texcoordsizen */ -static DWORD d3d9_formatMappings[2] = { D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 }; +static DWORD d3d9_formatMappings[] = { D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 }; /* Current format and size of vertices */ static int gfx_stride, gfx_format = -1; @@ -247,17 +246,6 @@ static void Gfx_RestoreState(void) { D3D9_RestoreRenderStates(); } -static cc_bool D3D9_CheckResult(cc_result res, const char* func) { - if (!res) return true; - - if (res == D3DERR_OUTOFVIDEOMEMORY || res == E_OUTOFMEMORY) { - if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory!"); - } else { - Logger_Abort2(res, func); - } - return false; -} - /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* @@ -320,6 +308,17 @@ static void D3D9_DoMipmaps(IDirect3DTexture9* texture, int x, int y, struct Bitm if (prev != bmp->scan0) Mem_Free(prev); } +static cc_bool D3D9_CheckResult(cc_result res, const char* func) { + if (!res) return true; + + if (res == D3DERR_OUTOFVIDEOMEMORY || res == E_OUTOFMEMORY) { + if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory!"); + } else { + Logger_Abort2(res, func); + } + return false; +} + static IDirect3DTexture9* DoCreateTexture(struct Bitmap* bmp, int levels, int pool) { IDirect3DTexture9* tex; cc_result res; @@ -332,18 +331,13 @@ static IDirect3DTexture9* DoCreateTexture(struct Bitmap* bmp, int levels, int po return tex; } -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { IDirect3DTexture9* tex; IDirect3DTexture9* sys; cc_result res; int mipmapsLevels = CalcMipmapsLevels(bmp->width, bmp->height); int levels = 1 + (mipmaps ? mipmapsLevels : 0); - - if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) { - Logger_Abort("Textures must have power of two dimensions"); - } - if (Gfx.LostContext) return 0; if (flags & TEXTURE_FLAG_MANAGED) { while ((res = IDirect3DDevice9_CreateTexture(device, bmp->width, bmp->height, levels, @@ -596,14 +590,16 @@ void Gfx_DeleteIb(GfxResourceID* ib) { D3D9_FreeResource(ib); } *#########################################################################################################################*/ static IDirect3DVertexBuffer9* D3D9_AllocVertexBuffer(VertexFormat fmt, int count, DWORD usage) { IDirect3DVertexBuffer9* vbuffer; - cc_result res; int size = count * strideSizes[fmt]; + cc_result res; - for (;;) { - res = IDirect3DDevice9_CreateVertexBuffer(device, size, usage, - d3d9_formatMappings[fmt], D3DPOOL_DEFAULT, &vbuffer, NULL); - if (D3D9_CheckResult(res, "D3D9_CreateVb failed")) break; - } + res = IDirect3DDevice9_CreateVertexBuffer(device, size, usage, + d3d9_formatMappings[fmt], D3DPOOL_DEFAULT, &vbuffer, NULL); + + if (res == D3DERR_OUTOFVIDEOMEMORY || res == E_OUTOFMEMORY) + return NULL; + + if (res) Logger_Abort2(res, "D3D9_AllocVertexBuffer failed"); return vbuffer; } @@ -627,17 +623,18 @@ static void* D3D9_LockVb(GfxResourceID vb, VertexFormat fmt, int count, int lock return dst; } -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return D3D9_AllocVertexBuffer(fmt, count, D3DUSAGE_WRITEONLY); } +void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); } + void Gfx_BindVb(GfxResourceID vb) { IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb; cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, gfx_stride); if (res) Logger_Abort2(res, "D3D9_BindVb"); } -void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); } void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { return D3D9_LockVb(vb, fmt, count, 0); } @@ -649,6 +646,43 @@ void Gfx_UnlockVb(GfxResourceID vb) { } +/*########################################################################################################################* +*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return D3D9_AllocVertexBuffer(fmt, maxVertices, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { D3D9_FreeResource(vb); } + +void Gfx_BindDynamicVb(GfxResourceID vb) { + IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb; + cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, gfx_stride); + if (res) Logger_Abort2(res, "D3D9_BindDynamicVb"); +} + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return D3D9_LockVb(vb, fmt, count, D3DLOCK_DISCARD); +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + Gfx_UnlockVb(vb); + Gfx_BindDynamicVb(vb); /* TODO: Inline this? */ +} + +void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { + int size = vCount * gfx_stride; + IDirect3DVertexBuffer9* buffer = (IDirect3DVertexBuffer9*)vb; + D3D9_SetVbData(buffer, vertices, size, D3DLOCK_DISCARD); + + cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, gfx_stride); + if (res) Logger_Abort2(res, "D3D9_SetDynamicVbData - Bind"); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Vertex rendering----------------------------------------------------* +*#########################################################################################################################*/ void Gfx_SetVertexFormat(VertexFormat fmt) { cc_result res; if (fmt == gfx_format) return; @@ -689,33 +723,6 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { } -/*########################################################################################################################* -*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------* -*#########################################################################################################################*/ -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - if (Gfx.LostContext) return 0; - return D3D9_AllocVertexBuffer(fmt, maxVertices, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); -} - -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - return D3D9_LockVb(vb, fmt, count, D3DLOCK_DISCARD); -} - -void Gfx_UnlockDynamicVb(GfxResourceID vb) { - Gfx_UnlockVb(vb); - Gfx_BindVb(vb); /* TODO: Inline this? */ -} - -void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { - int size = vCount * gfx_stride; - IDirect3DVertexBuffer9* buffer = (IDirect3DVertexBuffer9*)vb; - D3D9_SetVbData(buffer, vertices, size, D3DLOCK_DISCARD); - - cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, gfx_stride); - if (res) Logger_Abort2(res, "D3D9_SetDynamicVbData - Bind"); -} - - /*########################################################################################################################* *---------------------------------------------------------Matrices--------------------------------------------------------* *#########################################################################################################################*/ diff --git a/src/Graphics_Dreamcast.c b/src/Graphics_Dreamcast.c index 106be5abb..0181f73cb 100644 --- a/src/Graphics_Dreamcast.c +++ b/src/Graphics_Dreamcast.c @@ -127,11 +127,8 @@ void Gfx_DeleteIb(GfxResourceID* ib) { } /*########################################################################################################################* *------------------------------------------------------Vertex buffers-----------------------------------------------------* *#########################################################################################################################*/ -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { - void* data = memalign(16, count * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; - //return Mem_Alloc(count, strideSizes[fmt], "gfx VB"); +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return memalign(16, count * strideSizes[fmt]); } void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } @@ -153,13 +150,12 @@ void Gfx_UnlockVb(GfxResourceID vb) { } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - void* data = memalign(16, maxVertices * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; - //return Mem_Alloc(maxVertices, strideSizes[fmt], "gfx VB"); +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return memalign(16, maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { vb_size = count * strideSizes[fmt]; return vb; @@ -283,12 +279,9 @@ static void ConvertTexture(cc_uint16* dst, struct Bitmap* bmp) { } } -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { GLuint texId = gldcGenTexture(); gldcBindTexture(texId); - if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) { - Logger_Abort("Textures must have power of two dimensions"); - } gldcAllocTexture(bmp->width, bmp->height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS); @@ -299,6 +292,7 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm ConvertTexture(pixels, bmp); return texId; } + // TODO: struct GPUTexture ?? static void ConvertSubTexture(cc_uint16* dst, int texWidth, int texHeight, int originX, int originY, diff --git a/src/Graphics_GCWii.c b/src/Graphics_GCWii.c index ca9b9871d..b211e5357 100644 --- a/src/Graphics_GCWii.c +++ b/src/Graphics_GCWii.c @@ -136,7 +136,7 @@ static void ReorderPixels(CCTexture* tex, struct Bitmap* bmp, } } -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { if (bmp->width < 4 || bmp->height < 4) { Platform_LogConst("ERROR: Tried to create texture smaller than 4x4"); return 0; @@ -293,10 +293,8 @@ void Gfx_DeleteIb(GfxResourceID* ib) { } static cc_uint8* gfx_vertices; static int vb_size; -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { - void* data = memalign(16, count * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return memalign(16, count * strideSizes[fmt]); } void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } @@ -318,12 +316,12 @@ void Gfx_UnlockVb(GfxResourceID vb) { } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - void* data = memalign(16, maxVertices * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return memalign(16, maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { vb_size = count * strideSizes[fmt]; return vb; diff --git a/src/Graphics_GL1.c b/src/Graphics_GL1.c index 1bdb88471..aaf55ca4c 100644 --- a/src/Graphics_GL1.c +++ b/src/Graphics_GL1.c @@ -2,7 +2,6 @@ #if defined CC_BUILD_GL && !defined CC_BUILD_GLMODERN #include "_GraphicsBase.h" #include "Errors.h" -#include "Logger.h" #include "Window.h" /* The OpenGL backend is a bit of a mess, since it's really 2 backends in one: * - OpenGL 1.1 (completely lacking GPU, fallbacks to say Windows built-in software rasteriser) @@ -243,18 +242,19 @@ void Gfx_DeleteIb(GfxResourceID* ib) { } *------------------------------------------------------Vertex buffers-----------------------------------------------------* *#########################################################################################################################*/ #ifndef CC_BUILD_GL11 -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { GfxResourceID id = _genBuffer(); _glBindBuffer(GL_ARRAY_BUFFER, id); return id; } -void Gfx_BindVb(GfxResourceID vb) { _glBindBuffer(GL_ARRAY_BUFFER, vb); } +void Gfx_BindVb(GfxResourceID vb) { + _glBindBuffer(GL_ARRAY_BUFFER, vb); +} void Gfx_DeleteVb(GfxResourceID* vb) { GfxResourceID id = *vb; - if (!id) return; - _delBuffer(id); + if (id) _delBuffer(id); *vb = 0; } @@ -266,7 +266,9 @@ void Gfx_UnlockVb(GfxResourceID vb) { _glBufferData(GL_ARRAY_BUFFER, tmpSize, tmpData, GL_STATIC_DRAW); } #else -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { return glGenLists(1); } +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return glGenLists(1); +} void Gfx_BindVb(GfxResourceID vb) { activeList = (GLuint)vb; } void Gfx_DeleteVb(GfxResourceID* vb) { @@ -317,19 +319,25 @@ GfxResourceID Gfx_CreateVb2(void* vertices, VertexFormat fmt, int count) { *--------------------------------------------------Dynamic vertex buffers-------------------------------------------------* *#########################################################################################################################*/ #ifndef CC_BUILD_GL11 -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - GfxResourceID id; - cc_uint32 size; - if (Gfx.LostContext) return 0; - - id = _genBuffer(); - size = maxVertices * strideSizes[fmt]; +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + GfxResourceID id = _genBuffer(); + cc_uint32 size = maxVertices * strideSizes[fmt]; _glBindBuffer(GL_ARRAY_BUFFER, id); _glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); return id; } +void Gfx_BindDynamicVb(GfxResourceID vb) { + _glBindBuffer(GL_ARRAY_BUFFER, vb); +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { + GfxResourceID id = *vb; + if (id) _delBuffer(id); + *vb = 0; +} + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return FastAllocTempMem(count * strideSizes[fmt]); } @@ -345,8 +353,8 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { _glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices); } #else -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - return (GfxResourceID)Mem_Alloc(maxVertices, strideSizes[fmt], "creating dynamic vb"); +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return (GfxResourceID)Mem_TryAlloc(maxVertices, strideSizes[fmt]); } void Gfx_BindDynamicVb(GfxResourceID vb) { @@ -370,6 +378,97 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { #endif +/*########################################################################################################################* +*----------------------------------------------------------Drawing--------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_BUILD_GL11 + /* point to client side dynamic array */ + #define VB_PTR ((cc_uint8*)dynamicListData) + #define IB_PTR gl_indices +#else + /* no client side array, use vertex buffer object */ + #define VB_PTR 0 + #define IB_PTR NULL +#endif + +static void GL_SetupVbColoured(void) { + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + 12)); +} + +static void GL_SetupVbTextured(void) { + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 16)); +} + +static void GL_SetupVbColoured_Range(int startVertex) { + cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED; + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset + 12)); +} + +static void GL_SetupVbTextured_Range(int startVertex) { + cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 16)); +} + +void Gfx_SetVertexFormat(VertexFormat fmt) { + if (fmt == gfx_format) return; + gfx_format = fmt; + gfx_stride = strideSizes[fmt]; + + if (fmt == VERTEX_FORMAT_TEXTURED) { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnable(GL_TEXTURE_2D); + + gfx_setupVBFunc = GL_SetupVbTextured; + gfx_setupVBRangeFunc = GL_SetupVbTextured_Range; + } else { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + + gfx_setupVBFunc = GL_SetupVbColoured; + gfx_setupVBRangeFunc = GL_SetupVbColoured_Range; + } +} + +void Gfx_DrawVb_Lines(int verticesCount) { + gfx_setupVBFunc(); + glDrawArrays(GL_LINES, 0, verticesCount); +} + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { +#ifdef CC_BUILD_GL11 + if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; } +#endif + gfx_setupVBRangeFunc(startVertex); + _glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { +#ifdef CC_BUILD_GL11 + if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; } +#endif + gfx_setupVBFunc(); + _glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); +} + +#ifdef CC_BUILD_GL11 +void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { glCallList(activeList); } +#else +void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { + cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 16)); + _glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); +} +#endif /* !CC_BUILD_GL11 */ + + /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ @@ -612,95 +711,4 @@ static void GLBackend_Init(void) { } } #endif - - -/*########################################################################################################################* -*----------------------------------------------------------Drawing--------------------------------------------------------* -*#########################################################################################################################*/ -#ifdef CC_BUILD_GL11 -/* point to client side dynamic array */ -#define VB_PTR ((cc_uint8*)dynamicListData) -#define IB_PTR gl_indices -#else -/* no client side array, use vertex buffer object */ -#define VB_PTR 0 -#define IB_PTR NULL -#endif - -static void GL_SetupVbColoured(void) { - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + 0)); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + 12)); -} - -static void GL_SetupVbTextured(void) { - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 0)); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 12)); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 16)); -} - -static void GL_SetupVbColoured_Range(int startVertex) { - cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset)); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset + 12)); -} - -static void GL_SetupVbTextured_Range(int startVertex) { - cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset)); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 12)); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 16)); -} - -void Gfx_SetVertexFormat(VertexFormat fmt) { - if (fmt == gfx_format) return; - gfx_format = fmt; - gfx_stride = strideSizes[fmt]; - - if (fmt == VERTEX_FORMAT_TEXTURED) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_TEXTURE_2D); - - gfx_setupVBFunc = GL_SetupVbTextured; - gfx_setupVBRangeFunc = GL_SetupVbTextured_Range; - } else { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); - - gfx_setupVBFunc = GL_SetupVbColoured; - gfx_setupVBRangeFunc = GL_SetupVbColoured_Range; - } -} - -void Gfx_DrawVb_Lines(int verticesCount) { - gfx_setupVBFunc(); - glDrawArrays(GL_LINES, 0, verticesCount); -} - -void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { -#ifdef CC_BUILD_GL11 - if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; } -#endif - gfx_setupVBRangeFunc(startVertex); - _glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); -} - -void Gfx_DrawVb_IndexedTris(int verticesCount) { -#ifdef CC_BUILD_GL11 - if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; } -#endif - gfx_setupVBFunc(); - _glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); -} - -#ifdef CC_BUILD_GL11 -void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { glCallList(activeList); } -#else -void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { - cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset)); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 12)); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 16)); - _glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); -} -#endif /* !CC_BUILD_GL11 */ #endif diff --git a/src/Graphics_GL2.c b/src/Graphics_GL2.c index 9b5e8455c..090fa3ff3 100644 --- a/src/Graphics_GL2.c +++ b/src/Graphics_GL2.c @@ -2,7 +2,6 @@ #if defined CC_BUILD_GL && defined CC_BUILD_GLMODERN #include "_GraphicsBase.h" #include "Errors.h" -#include "Logger.h" #include "Window.h" /* OpenGL 2.0 backend (alternative modern-ish backend) */ @@ -125,16 +124,17 @@ void Gfx_DeleteIb(GfxResourceID* ib) { /*########################################################################################################################* *------------------------------------------------------Vertex buffers-----------------------------------------------------* *#########################################################################################################################*/ -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return GL_GenAndBind(GL_ARRAY_BUFFER); } -void Gfx_BindVb(GfxResourceID vb) { glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); } +void Gfx_BindVb(GfxResourceID vb) { + glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); +} void Gfx_DeleteVb(GfxResourceID* vb) { GLuint id = (GLuint)(*vb); - if (!id) return; - glDeleteBuffers(1, &id); + if (id) glDeleteBuffers(1, &id); *vb = 0; } @@ -150,17 +150,24 @@ void Gfx_UnlockVb(GfxResourceID vb) { /*########################################################################################################################* *--------------------------------------------------Dynamic vertex buffers-------------------------------------------------* *#########################################################################################################################*/ -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - GLuint id; - cc_uint32 size; - if (Gfx.LostContext) return 0; +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + GLuint id = GL_GenAndBind(GL_ARRAY_BUFFER); + cc_uint32 size = maxVertices * strideSizes[fmt]; - id = GL_GenAndBind(GL_ARRAY_BUFFER); - size = maxVertices * strideSizes[fmt]; glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); return id; } +void Gfx_BindDynamicVb(GfxResourceID vb) { + glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { + GLuint id = (GLuint)(*vb); + if (id) glDeleteBuffers(1, &id); + *vb = 0; +} + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return FastAllocTempMem(count * strideSizes[fmt]); } diff --git a/src/Graphics_PS3.c b/src/Graphics_PS3.c index ca6cfd688..408ca52fe 100644 --- a/src/Graphics_PS3.c +++ b/src/Graphics_PS3.c @@ -494,10 +494,8 @@ void Gfx_DeleteIb(GfxResourceID* ib) { } /*########################################################################################################################* *------------------------------------------------------Vertex buffers-----------------------------------------------------* *#########################################################################################################################*/ -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { - void* data = rsxMemalign(128, count * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return rsxMemalign(128, count * strideSizes[fmt]); } void Gfx_BindVb(GfxResourceID vb) { @@ -536,12 +534,12 @@ void Gfx_UnlockVb(GfxResourceID vb) { } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - void* data = rsxMemalign(128, maxVertices * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) + return rsxMemalign(128, maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { vb_size = count * strideSizes[fmt]; return vb; @@ -568,7 +566,7 @@ typedef struct CCTexture_ { cc_uint32 pixels[]; } CCTexture; -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { int size = bmp->width * bmp->height * 4; CCTexture* tex = (CCTexture*)rsxMemalign(128, 128 + size); diff --git a/src/Graphics_PSP.c b/src/Graphics_PSP.c index f3282ae6c..30461db8c 100644 --- a/src/Graphics_PSP.c +++ b/src/Graphics_PSP.c @@ -114,7 +114,7 @@ typedef struct CCTexture_ { cc_uint32 pixels[]; } CCTexture; -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { int size = bmp->width * bmp->height * 4; CCTexture* tex = (CCTexture*)memalign(16, 16 + size); @@ -284,11 +284,8 @@ void Gfx_BindIb(GfxResourceID ib) { } void Gfx_DeleteIb(GfxResourceID* ib) { } -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { - void* data = memalign(16, count * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; - //return Mem_Alloc(count, strideSizes[fmt], "gfx VB"); +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return memalign(16, count * strideSizes[fmt]); } void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } @@ -310,13 +307,12 @@ void Gfx_UnlockVb(GfxResourceID vb) { } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - void* data = memalign(16, maxVertices * strideSizes[fmt]); - if (!data) Logger_Abort("Failed to allocate memory for GFX VB"); - return data; - //return Mem_Alloc(maxVertices, strideSizes[fmt], "gfx VB"); +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return memalign(16, maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { vb_size = count * strideSizes[fmt]; return vb; diff --git a/src/Graphics_PSVita.c b/src/Graphics_PSVita.c index a1aaaf2c3..88dbe685e 100644 --- a/src/Graphics_PSVita.c +++ b/src/Graphics_PSVita.c @@ -661,7 +661,7 @@ static void GPUTextures_DeleteUnreferenced(void) { /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { int size = bmp->width * bmp->height * 4; struct GPUTexture* tex = GPUTexture_Alloc(size); Mem_Copy(tex->data, bmp->scan0, size); @@ -891,7 +891,7 @@ void Gfx_DeleteIb(GfxResourceID* ib) { GPUBuffer_Unref(ib); } /*########################################################################################################################* *-------------------------------------------------------Vertex buffers----------------------------------------------------* *#########################################################################################################################*/ -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return GPUBuffer_Alloc(count * strideSizes[fmt]); } @@ -911,10 +911,12 @@ void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { void Gfx_UnlockVb(GfxResourceID vb) { Gfx_BindVb(vb); } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return GPUBuffer_Alloc(maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { struct GPUBuffer* buffer = (struct GPUBuffer*)vb; return buffer->data; diff --git a/src/Graphics_Xbox.c b/src/Graphics_Xbox.c index bbf63ff1b..25ffa4074 100644 --- a/src/Graphics_Xbox.c +++ b/src/Graphics_Xbox.c @@ -198,7 +198,7 @@ static void ConvertTexture(cc_uint32* dst, struct Bitmap* bmp) { } } -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { int size = 16 + bmp->width * bmp->height * 4; CCTexture* tex = MmAllocateContiguousMemoryEx(size, 0, MAX_RAM_ADDR, 0, 0x404); @@ -394,10 +394,7 @@ static cc_uint8* gfx_vertices; static cc_uint16* gfx_indices; static void* AllocBuffer(int count, int elemSize) { - void* ptr = MmAllocateContiguousMemoryEx(count * elemSize, 0, MAX_RAM_ADDR, 0, PAGE_WRITECOMBINE | PAGE_READWRITE); - - if (!ptr) Logger_Abort("Failed to allocate memory for buffer"); - return ptr; + return MmAllocateContiguousMemoryEx(count * elemSize, 0, MAX_RAM_ADDR, 0, PAGE_WRITECOMBINE | PAGE_READWRITE); } static void FreeBuffer(GfxResourceID* buffer) { @@ -409,6 +406,8 @@ static void FreeBuffer(GfxResourceID* buffer) { GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { void* ib = AllocBuffer(count, sizeof(cc_uint16)); + if (!ib) Logger_Abort("Failed to allocate memory for index buffer"); + fillFunc(ib, count, obj); return ib; } @@ -418,7 +417,7 @@ void Gfx_BindIb(GfxResourceID ib) { gfx_indices = ib; } void Gfx_DeleteIb(GfxResourceID* ib) { FreeBuffer(ib); } -GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return AllocBuffer(count, strideSizes[fmt]); } @@ -450,10 +449,12 @@ void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } void Gfx_UnlockVb(GfxResourceID vb) { } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return AllocBuffer(maxVertices, strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } diff --git a/src/Model.c b/src/Model.c index 7a13bca9d..9033e39ef 100644 --- a/src/Model.c +++ b/src/Model.c @@ -144,7 +144,9 @@ void Model_SetupState(struct Model* model, struct Entity* e) { void Model_UpdateVB(void) { struct Model* model = Models.Active; - Gfx_UpdateDynamicVb_IndexedTris(Models.Vb, Models.Vertices, model->index); + + Gfx_SetDynamicVbData(Models.Vb, Models.Vertices, model->index); + Gfx_DrawVb_IndexedTris(model->index); model->index = 0; } diff --git a/src/SelectionBox.c b/src/SelectionBox.c index 8d855d181..3a5b42709 100644 --- a/src/SelectionBox.c +++ b/src/SelectionBox.c @@ -108,7 +108,6 @@ static int selections_count; static struct SelectionBox selections_list[SELECTIONS_MAX]; static cc_uint8 selections_ids[SELECTIONS_MAX]; static GfxResourceID selections_VB, selections_LineVB; -static cc_bool selections_used; void Selections_Add(cc_uint8 id, const IVec3* p1, const IVec3* p2, PackedCol color) { struct SelectionBox sel; @@ -142,10 +141,9 @@ static void Selections_ContextLost(void* obj) { Gfx_DeleteDynamicVb(&selections_LineVB); } -static void Selections_ContextRecreated(void* obj) { - if (!selections_used) return; - Gfx_RecreateDynamicVb(&selections_VB, VERTEX_FORMAT_COLOURED, SELECTIONS_MAX_VERTICES); - Gfx_RecreateDynamicVb(&selections_LineVB, VERTEX_FORMAT_COLOURED, SELECTIONS_MAX_VERTICES); +static void AllocateVertexBuffers(void) { + selections_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_COLOURED, SELECTIONS_MAX_VERTICES); + selections_LineVB = Gfx_CreateDynamicVb(VERTEX_FORMAT_COLOURED, SELECTIONS_MAX_VERTICES); } static void Selections_QuickSort(int left, int right) { @@ -181,10 +179,9 @@ void Selections_Render(void) { } Selections_QuickSort(0, selections_count - 1); - if (!selections_VB) { /* lazy init as most servers don't use this */ - selections_used = true; - Selections_ContextRecreated(NULL); - } + /* lazy init as most servers don't use this */ + if (!selections_VB) AllocateVertexBuffers(); + count = selections_count * SELECTIONS_VERTICES; Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); @@ -215,8 +212,7 @@ void Selections_Render(void) { *--------------------------------------------------Selections component---------------------------------------------------* *#########################################################################################################################*/ static void OnInit(void) { - Event_Register_(&GfxEvents.ContextLost, NULL, Selections_ContextLost); - Event_Register_(&GfxEvents.ContextRecreated, NULL, Selections_ContextRecreated); + Event_Register_(&GfxEvents.ContextLost, NULL, Selections_ContextLost); } static void OnReset(void) { selections_count = 0; } diff --git a/src/_GLShared.h b/src/_GLShared.h index 68c7b6a6b..9394f82d2 100644 --- a/src/_GLShared.h +++ b/src/_GLShared.h @@ -102,17 +102,12 @@ static void Gfx_DoMipmaps(int x, int y, struct Bitmap* bmp, int rowWidth, cc_boo if (prev != bmp->scan0) Mem_Free(prev); } -GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { GLuint texId; glGenTextures(1, &texId); glBindTexture(GL_TEXTURE_2D, texId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) { - Logger_Abort("Textures must have power of two dimensions"); - } - if (Gfx.LostContext) return 0; - if (mipmaps) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); if (customMipmapsLevels) { @@ -163,8 +158,7 @@ void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, struct Bitmap* par void Gfx_DeleteTexture(GfxResourceID* texId) { GLuint id = (GLuint)(*texId); - if (!id) return; - glDeleteTextures(1, &id); + if (id) glDeleteTextures(1, &id); *texId = 0; } diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index 0da828c53..6e5c5a453 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -9,13 +9,14 @@ #include "Options.h" #include "Bitmap.h" #include "Chat.h" +#include "Logger.h" struct _GfxData Gfx; GfxResourceID Gfx_defaultIb; -GfxResourceID Gfx_quadVb, Gfx_texVb; +static GfxResourceID Gfx_quadVb, Gfx_texVb; const cc_string Gfx_LowPerfMessage = String_FromConst("&eRunning in reduced performance mode (game minimised or hidden)"); -static const int strideSizes[2] = { SIZEOF_VERTEX_COLOURED, SIZEOF_VERTEX_TEXTURED }; +static const int strideSizes[] = { SIZEOF_VERTEX_COLOURED, SIZEOF_VERTEX_TEXTURED }; /* Whether mipmaps must be created for all dimensions down to 1x1 or not */ static cc_bool customMipmapsLevels; @@ -142,44 +143,47 @@ void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count) { return Gfx_LockVb(*vb, fmt, count); } -void Gfx_UpdateDynamicVb_IndexedTris(GfxResourceID vb, void* vertices, int vCount) { - Gfx_SetDynamicVbData(vb, vertices, vCount); - Gfx_DrawVb_IndexedTris(vCount); -} - #ifndef CC_BUILD_3DS void Gfx_Draw2DFlat(int x, int y, int width, int height, PackedCol color) { - struct VertexColoured verts[4]; - struct VertexColoured* v = verts; + struct VertexColoured* v; + + Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); + v = (struct VertexColoured*)Gfx_LockDynamicVb(Gfx_quadVb, VERTEX_FORMAT_COLOURED, 4); v->X = (float)x; v->Y = (float)y; v->Z = 0; v->Col = color; v++; v->X = (float)(x + width); v->Y = (float)y; v->Z = 0; v->Col = color; v++; v->X = (float)(x + width); v->Y = (float)(y + height); v->Z = 0; v->Col = color; v++; v->X = (float)x; v->Y = (float)(y + height); v->Z = 0; v->Col = color; v++; - Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); - Gfx_UpdateDynamicVb_IndexedTris(Gfx_quadVb, verts, 4); + Gfx_UnlockDynamicVb(Gfx_quadVb); + Gfx_DrawVb_IndexedTris(4); } void Gfx_Draw2DGradient(int x, int y, int width, int height, PackedCol top, PackedCol bottom) { - struct VertexColoured verts[4]; - struct VertexColoured* v = verts; + struct VertexColoured* v; + + Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); + v = (struct VertexColoured*)Gfx_LockDynamicVb(Gfx_quadVb, VERTEX_FORMAT_COLOURED, 4); v->X = (float)x; v->Y = (float)y; v->Z = 0; v->Col = top; v++; v->X = (float)(x + width); v->Y = (float)y; v->Z = 0; v->Col = top; v++; v->X = (float)(x + width); v->Y = (float)(y + height); v->Z = 0; v->Col = bottom; v++; v->X = (float)x; v->Y = (float)(y + height); v->Z = 0; v->Col = bottom; v++; - Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); - Gfx_UpdateDynamicVb_IndexedTris(Gfx_quadVb, verts, 4); + Gfx_UnlockDynamicVb(Gfx_quadVb); + Gfx_DrawVb_IndexedTris(4); } void Gfx_Draw2DTexture(const struct Texture* tex, PackedCol color) { - struct VertexTextured texVerts[4]; - struct VertexTextured* ptr = texVerts; - Gfx_Make2DQuad(tex, color, &ptr); + struct VertexTextured* ptr; + Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); - Gfx_UpdateDynamicVb_IndexedTris(Gfx_texVb, texVerts, 4); + ptr = (struct VertexTextured*)Gfx_LockDynamicVb(Gfx_texVb, VERTEX_FORMAT_TEXTURED, 4); + + Gfx_Make2DQuad(tex, color, &ptr); + + Gfx_UnlockDynamicVb(Gfx_texVb); + Gfx_DrawVb_IndexedTris(4); } #endif @@ -333,6 +337,17 @@ static CC_NOINLINE int CalcMipmapsLevels(int width, int height) { } } +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) { + if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) { + Logger_Abort("Textures must have power of two dimensions"); + } + if (Gfx.LostContext) return 0; + + return Gfx_AllocTexture(bmp, flags, mipmaps); +} + void Texture_Render(const struct Texture* tex) { Gfx_BindTexture(tex->ID); Gfx_Draw2DTexture(tex, PACKEDCOL_WHITE); @@ -344,6 +359,37 @@ void Texture_RenderShaded(const struct Texture* tex, PackedCol shadeColor) { } +/*########################################################################################################################* +*------------------------------------------------------Vertex buffers-----------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID Gfx_AllocStaticVb( VertexFormat fmt, int count); +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices); + +GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { + GfxResourceID vb; + /* if (Gfx.LostContext) return 0; TODO check this ???? probably breaks things */ + + for (;;) + { + if ((vb = Gfx_AllocStaticVb(fmt, count))) return vb; + + if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory! (allocating static VB)"); + } +} + +GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { + GfxResourceID vb; + if (Gfx.LostContext) return 0; + + for (;;) + { + if ((vb = Gfx_AllocDynamicVb(fmt, maxVertices))) return vb; + + if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory! (allocating dynamic VB)"); + } +} + + /*########################################################################################################################* *----------------------------------------------------Graphics component---------------------------------------------------* *#########################################################################################################################*/