diff --git a/ClassicalSharp/Math/Vector3.cs b/ClassicalSharp/Math/Vector3.cs index 07a7232f6..afa52dd44 100644 --- a/ClassicalSharp/Math/Vector3.cs +++ b/ClassicalSharp/Math/Vector3.cs @@ -47,7 +47,7 @@ namespace OpenTK { public static readonly Vector3 UnitZ = new Vector3(0, 0, 1); public static readonly Vector3 Zero = new Vector3(0, 0, 0); - public static readonly Vector3 One = new Vector3(1, 1, 1); + public static readonly Vector3 One = new Vector3(1, 1, 1); public static Vector3 Lerp(Vector3 a, Vector3 b, float blend) { a.X = blend * (b.X - a.X) + a.X; diff --git a/src/Animations.c b/src/Animations.c index 24b2010c3..ce4aa5634 100644 --- a/src/Animations.c +++ b/src/Animations.c @@ -4,7 +4,7 @@ #include "Platform.h" #include "Event.h" #include "Funcs.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Chat.h" #include "World.h" #include "Options.h" diff --git a/src/AxisLinesRenderer.c b/src/AxisLinesRenderer.c index 6b90624bb..26056eac8 100644 --- a/src/AxisLinesRenderer.c +++ b/src/AxisLinesRenderer.c @@ -1,5 +1,5 @@ #include "AxisLinesRenderer.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Game.h" #include "GraphicsCommon.h" #include "SelectionBox.h" diff --git a/src/Builder.c b/src/Builder.c index 59f7f2838..bee92cef9 100644 --- a/src/Builder.c +++ b/src/Builder.c @@ -5,7 +5,7 @@ #include "Lighting.h" #include "Platform.h" #include "MapRenderer.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "ErrorHandler.h" #include "Drawer.h" #include "ExtMath.h" diff --git a/src/Camera.c b/src/Camera.c index c0e5a2341..ee3e75e97 100644 --- a/src/Camera.c +++ b/src/Camera.c @@ -2,7 +2,7 @@ #include "ExtMath.h" #include "Game.h" #include "Window.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Funcs.h" #include "Gui.h" #include "Entity.h" diff --git a/src/Chat.c b/src/Chat.c index f2a9cfa14..0c33708e5 100644 --- a/src/Chat.c +++ b/src/Chat.c @@ -9,13 +9,16 @@ #include "Inventory.h" #include "Entity.h" #include "Window.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "GraphicsCommon.h" #include "Funcs.h" #include "Block.h" #include "EnvRenderer.h" #include "GameStructs.h" +/*########################################################################################################################* +*-------------------------------------------------------Chat logging------------------------------------------------------* +*#########################################################################################################################*/ #define CHAT_LOGTIMES_DEF_ELEMS 256 TimeMS Chat_DefaultLogTimes[CHAT_LOGTIMES_DEF_ELEMS]; TimeMS* Chat_LogTimes = Chat_DefaultLogTimes; @@ -36,12 +39,6 @@ static void Chat_AppendLogTime(void) { Chat_LogTimes[Chat_LogTimesCount++] = now; } -static void ChatLine_Make(struct ChatLine* line, const String* text) { - String dst = String_ClearedArray(line->Buffer); - String_AppendString(&dst, text); - line->Received = DateTime_CurrentUTC_MS(); -} - char Chat_LogNameBuffer[STRING_SIZE]; String Chat_LogName = String_FromArray(Chat_LogNameBuffer); char Chat_LogPathBuffer[FILENAME_SIZE]; @@ -141,6 +138,12 @@ static void Chat_AppendLog(const String* text) { Chat_LogError2(res, "writing to", &Chat_LogPath); } +static void ChatLine_Make(struct ChatLine* line, const String* text) { + String dst = String_ClearedArray(line->Buffer); + String_AppendString(&dst, text); + line->Received = DateTime_CurrentUTC_MS(); +} + void Chat_LogError(ReturnCode result, const char* place) { Chat_Add4("&cError %h when %c", &result, place, NULL, NULL); } diff --git a/src/ChunkUpdater.c b/src/ChunkUpdater.c index f56c021f5..75497361e 100644 --- a/src/ChunkUpdater.c +++ b/src/ChunkUpdater.c @@ -4,7 +4,7 @@ #include "ExtMath.h" #include "Funcs.h" #include "Game.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Entity.h" #include "MapRenderer.h" #include "Platform.h" diff --git a/src/ClassiCube.vcxproj b/src/ClassiCube.vcxproj index b30fbace1..eadbf71dc 100644 --- a/src/ClassiCube.vcxproj +++ b/src/ClassiCube.vcxproj @@ -241,7 +241,7 @@ - + @@ -262,7 +262,6 @@ - @@ -273,6 +272,7 @@ + @@ -290,7 +290,6 @@ - diff --git a/src/ClassiCube.vcxproj.filters b/src/ClassiCube.vcxproj.filters index 135cae66e..c6ce8366b 100644 --- a/src/ClassiCube.vcxproj.filters +++ b/src/ClassiCube.vcxproj.filters @@ -141,9 +141,6 @@ Header Files\Math - - Header Files\Graphics - Header Files\Graphics @@ -315,6 +312,9 @@ Header Files\Blocks + + Header Files\Graphics + @@ -338,9 +338,6 @@ Source Files\Map - - Source Files\Graphics - Source Files\2D\Utils @@ -395,9 +392,6 @@ Source Files\IO - - Source Files\Graphics - Source Files\Map @@ -578,5 +572,8 @@ Source Files\Freetype + + Source Files\Graphics + \ No newline at end of file diff --git a/src/D3D9Api.c b/src/D3D9Api.c deleted file mode 100644 index 11b6736db..000000000 --- a/src/D3D9Api.c +++ /dev/null @@ -1,721 +0,0 @@ -#include "GraphicsAPI.h" -#ifdef CC_BUILD_D3D9 -#include "ErrorHandler.h" -#include "Platform.h" -#include "Window.h" -#include "GraphicsCommon.h" -#include "Funcs.h" -#include "Game.h" -#include "ExtMath.h" -#include "Bitmap.h" -#include "Event.h" - -//#define D3D_DISABLE_9EX causes compile errors -#ifdef CC_BUILD_WIN -#define WIN32_LEAN_AND_MEAN -#define NOSERVICE -#define NOMCX -#define NOIME -#endif -#include -#include -#include - -int Gfx_strideSizes[2] = GFX_STRIDE_SIZES; -D3DFORMAT d3d9_depthFormats[6] = { D3DFMT_D32, D3DFMT_D24X8, D3DFMT_D24S8, D3DFMT_D24X4S4, D3DFMT_D16, D3DFMT_D15S1 }; -D3DFORMAT d3d9_viewFormats[4] = { D3DFMT_X8R8G8B8, D3DFMT_R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 }; -D3DBLEND d3d9_blendFuncs[6] = { D3DBLEND_ZERO, D3DBLEND_ONE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_DESTALPHA, D3DBLEND_INVDESTALPHA }; -D3DCMPFUNC d3d9_compareFuncs[8] = { D3DCMP_ALWAYS, D3DCMP_NOTEQUAL, D3DCMP_NEVER, D3DCMP_LESS, D3DCMP_LESSEQUAL, D3DCMP_EQUAL, D3DCMP_GREATEREQUAL, D3DCMP_GREATER }; -D3DFOGMODE d3d9_modes[3] = { D3DFOG_LINEAR, D3DFOG_EXP, D3DFOG_EXP2 }; -DWORD d3d9_formatMappings[2] = { D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2 }; - -bool d3d9_vsync; -IDirect3D9* d3d; -IDirect3DDevice9* device; -D3DTRANSFORMSTATETYPE curMatrix; -DWORD createFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; -D3DFORMAT d3d9_viewFormat, d3d9_depthFormat; - -#define D3D9_SetRenderState(state, value, name) \ -ReturnCode res = IDirect3DDevice9_SetRenderState(device, state, value); if (res) ErrorHandler_Fail2(res, name); -#define D3D9_SetRenderState2(state, value, name) \ -res = IDirect3DDevice9_SetRenderState(device, state, value); if (res) ErrorHandler_Fail2(res, name); - - -/* Forward declarations for these two functions. */ -static void D3D9_SetDefaultRenderStates(void); -static void D3D9_RestoreRenderStates(void); - -static void D3D9_FreeResource(GfxResourceID* resource) { - if (!resource || *resource == GFX_NULL) return; - IUnknown* unk = (IUnknown*)(*resource); - ULONG refCount = unk->lpVtbl->Release(unk); - *resource = GFX_NULL; - if (refCount <= 0) return; - - uintptr_t addr = (uintptr_t)unk; - Platform_Log2("D3D9 resource has %i outstanding references! ID 0x%x", &refCount, &addr); -} - -static void D3D9_LoopUntilRetrieved(void) { - struct ScheduledTask task; - task.Interval = 1.0f / 60.0f; - task.Callback = Gfx_LostContextFunction; - - while (true) { - Thread_Sleep(16); - ReturnCode code = IDirect3DDevice9_TestCooperativeLevel(device); - if (code == D3DERR_DEVICENOTRESET) return; - - task.Callback(&task); - } -} - -static void D3D9_FindCompatibleFormat(void) { - int i, count = Array_Elems(d3d9_viewFormats); - ReturnCode res; - - for (i = 0; i < count; i++) { - d3d9_viewFormat = d3d9_viewFormats[i]; - res = IDirect3D9_CheckDeviceType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3d9_viewFormat, d3d9_viewFormat, true); - if (!res) break; - - if (i == count - 1) { - ErrorHandler_Fail("Unable to create a back buffer with sufficient precision."); - } - } - - count = Array_Elems(d3d9_depthFormats); - for (i = 0; i < count; i++) { - d3d9_depthFormat = d3d9_depthFormats[i]; - res = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3d9_viewFormat, d3d9_viewFormat, d3d9_depthFormat); - if (!res) break; - - if (i == count - 1) { - ErrorHandler_Fail("Unable to create a depth buffer with sufficient precision."); - } - } -} - -static void D3D9_FillPresentArgs(int width, int height, D3DPRESENT_PARAMETERS* args) { - args->AutoDepthStencilFormat = d3d9_depthFormat; - args->BackBufferWidth = width; - args->BackBufferHeight = height; - args->BackBufferFormat = d3d9_viewFormat; - args->BackBufferCount = 1; - args->EnableAutoDepthStencil = true; - args->PresentationInterval = d3d9_vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; - args->SwapEffect = D3DSWAPEFFECT_DISCARD; - args->Windowed = true; -} - -static void D3D9_RecreateDevice(void) { - D3DPRESENT_PARAMETERS args = { 0 }; - D3D9_FillPresentArgs(Game_Width, Game_Height, &args); - - while (IDirect3DDevice9_Reset(device, &args) == D3DERR_DEVICELOST) { - D3D9_LoopUntilRetrieved(); - } - - D3D9_SetDefaultRenderStates(); - D3D9_RestoreRenderStates(); - GfxCommon_RecreateContext(); -} - - -void Gfx_Init(void) { - Gfx_MinZNear = 0.05f; - void* winHandle = Window_GetWindowHandle(); - d3d = Direct3DCreate9(D3D_SDK_VERSION); - - D3D9_FindCompatibleFormat(); - D3DPRESENT_PARAMETERS args = { 0 }; - D3D9_FillPresentArgs(640, 480, &args); - ReturnCode res; - - /* Try to create a device with as much hardware usage as possible. */ - res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device); - if (res) { - createFlags = D3DCREATE_MIXED_VERTEXPROCESSING; - res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device); - } - if (res) { - createFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; - res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device); - } - if (res) ErrorHandler_Fail2(res, "Creating Direct3D9 device"); - - D3DCAPS9 caps; - res = IDirect3DDevice9_GetDeviceCaps(device, &caps); - if (res) ErrorHandler_Fail2(res, "Getting Direct3D9 capabilities"); - - Gfx_MaxTexWidth = caps.MaxTextureWidth; - Gfx_MaxTexHeight = caps.MaxTextureHeight; - - Gfx_CustomMipmapsLevels = true; - D3D9_SetDefaultRenderStates(); - GfxCommon_Init(); -} - -void Gfx_Free(void) { - GfxCommon_Free(); - D3D9_FreeResource(&device); - D3D9_FreeResource(&d3d); -} - -static void D3D9_SetTextureData(IDirect3DTexture9* texture, Bitmap* bmp, int lvl) { - D3DLOCKED_RECT rect; - ReturnCode res = IDirect3DTexture9_LockRect(texture, lvl, &rect, NULL, 0); - if (res) ErrorHandler_Fail2(res, "D3D9_SetTextureData - Lock"); - - uint32_t size = Bitmap_DataSize(bmp->Width, bmp->Height); - Mem_Copy(rect.pBits, bmp->Scan0, size); - - res = IDirect3DTexture9_UnlockRect(texture, lvl); - if (res) ErrorHandler_Fail2(res, "D3D9_SetTextureData - Unlock"); -} - -static void D3D9_SetTexturePartData(IDirect3DTexture9* texture, int x, int y, Bitmap* bmp, int lvl) { - RECT part; - part.left = x; part.right = x + bmp->Width; - part.top = y; part.bottom = y + bmp->Height; - - D3DLOCKED_RECT rect; - ReturnCode res = IDirect3DTexture9_LockRect(texture, lvl, &rect, &part, 0); - if (res) ErrorHandler_Fail2(res, "D3D9_SetTexturePartData - Lock"); - - /* We need to copy scanline by scanline, as generally rect.stride != data.stride */ - uint8_t* src = (uint8_t*)bmp->Scan0; - uint8_t* dst = (uint8_t*)rect.pBits; - int yy; - uint32_t stride = (uint32_t)(bmp->Width) * BITMAP_SIZEOF_PIXEL; - - for (yy = 0; yy < bmp->Height; yy++) { - Mem_Copy(dst, src, stride); - src += stride; - dst += rect.Pitch; - } - - res = IDirect3DTexture9_UnlockRect(texture, lvl); - if (res) ErrorHandler_Fail2(res, "D3D9_SetTexturePartData - Unlock"); -} - -static void D3D9_DoMipmaps(IDirect3DTexture9* texture, int x, int y, Bitmap* bmp, bool partial) { - uint8_t* prev = bmp->Scan0; - int lvls = GfxCommon_MipmapsLevels(bmp->Width, bmp->Height); - int lvl, width = bmp->Width, height = bmp->Height; - - for (lvl = 1; lvl <= lvls; lvl++) { - x /= 2; y /= 2; - if (width > 1) width /= 2; - if (height > 1) height /= 2; - - uint8_t* cur = Mem_Alloc(width * height, BITMAP_SIZEOF_PIXEL, "mipmaps"); - GfxCommon_GenMipmaps(width, height, cur, prev); - - Bitmap mipmap; - Bitmap_Create(&mipmap, width, height, cur); - if (partial) { - D3D9_SetTexturePartData(texture, x, y, &mipmap, lvl); - } else { - D3D9_SetTextureData(texture, &mipmap, lvl); - } - - if (prev != bmp->Scan0) Mem_Free(prev); - prev = cur; - } - if (prev != bmp->Scan0) Mem_Free(prev); -} - -GfxResourceID Gfx_CreateTexture(Bitmap* bmp, bool managedPool, bool mipmaps) { - IDirect3DTexture9* tex; - ReturnCode res; - int mipmapsLevels = GfxCommon_MipmapsLevels(bmp->Width, bmp->Height); - int levels = 1 + (mipmaps ? mipmapsLevels : 0); - - if (!Math_IsPowOf2(bmp->Width) || !Math_IsPowOf2(bmp->Height)) { - ErrorHandler_Fail("Textures must have power of two dimensions"); - } - - if (managedPool) { - res = IDirect3DDevice9_CreateTexture(device, bmp->Width, bmp->Height, levels, - 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex, NULL); - if (res) ErrorHandler_Fail2(res, "D3D9_CreateTexture"); - - D3D9_SetTextureData(tex, bmp, 0); - if (mipmaps) D3D9_DoMipmaps(tex, 0, 0, bmp, false); - } else { - IDirect3DTexture9* sys; - res = IDirect3DDevice9_CreateTexture(device, bmp->Width, bmp->Height, levels, - 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &sys, NULL); - if (res) ErrorHandler_Fail2(res, "D3D9_CreateTexture - SystemMem"); - - D3D9_SetTextureData(sys, bmp, 0); - if (mipmaps) D3D9_DoMipmaps(sys, 0, 0, bmp, false); - - res = IDirect3DDevice9_CreateTexture(device, bmp->Width, bmp->Height, levels, - 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); - if (res) ErrorHandler_Fail2(res, "D3D9_CreateTexture - GPU"); - - res = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)sys, (IDirect3DBaseTexture9*)tex); - if (res) ErrorHandler_Fail2(res, "D3D9_CreateTexture - Update"); - D3D9_FreeResource(&sys); - } - return tex; -} - -void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, Bitmap* part, bool mipmaps) { - IDirect3DTexture9* texture = (IDirect3DTexture9*)texId; - D3D9_SetTexturePartData(texture, x, y, part, 0); - if (mipmaps) D3D9_DoMipmaps(texture, x, y, part, true); -} - -void Gfx_BindTexture(GfxResourceID texId) { - ReturnCode res = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9*)texId); - if (res) ErrorHandler_Fail2(res, "D3D9_BindTexture"); -} - -void Gfx_DeleteTexture(GfxResourceID* texId) { D3D9_FreeResource(texId); } - -void Gfx_SetTexturing(bool enabled) { - if (enabled) return; - ReturnCode res = IDirect3DDevice9_SetTexture(device, 0, NULL); - if (res) ErrorHandler_Fail2(res, "D3D9_SetTexturing"); -} - -void Gfx_EnableMipmaps(void) { - if (Gfx_Mipmaps) { - ReturnCode res = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - if (res) ErrorHandler_Fail2(res, "D3D9_EnableMipmaps"); - } -} - -void Gfx_DisableMipmaps(void) { - if (Gfx_Mipmaps) { - ReturnCode res = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - if (res) ErrorHandler_Fail2(res, "D3D9_DisableMipmaps"); - } -} - - -bool d3d9_fogEnable = false; -bool Gfx_GetFog(void) { return d3d9_fogEnable; } -void Gfx_SetFog(bool enabled) { - if (d3d9_fogEnable == enabled) return; - d3d9_fogEnable = enabled; - if (Gfx_LostContext) return; - D3D9_SetRenderState(D3DRS_FOGENABLE, (uint32_t)enabled, "D3D9_SetFog"); -} - -uint32_t d3d9_fogCol = 0xFF000000; /* black */ -void Gfx_SetFogCol(PackedCol col) { - if (col.Packed == d3d9_fogCol) return; - d3d9_fogCol = col.Packed; - if (Gfx_LostContext) return; - D3D9_SetRenderState(D3DRS_FOGCOLOR, col.Packed, "D3D9_SetFogColour"); -} - -float d3d9_fogDensity = -1.0f; -void Gfx_SetFogDensity(float value) { - if (value == d3d9_fogDensity) return; - d3d9_fogDensity = value; - if (Gfx_LostContext) return; - union IntAndFloat raw; raw.f = value; - D3D9_SetRenderState(D3DRS_FOGDENSITY, raw.u, "D3D9_SetFogDensity"); -} - -float d3d9_fogEnd = -1.0f; -void Gfx_SetFogEnd(float value) { - if (value == d3d9_fogEnd) return; - d3d9_fogEnd = value; - if (Gfx_LostContext) return; - union IntAndFloat raw; raw.f = value; - D3D9_SetRenderState(D3DRS_FOGEND, raw.u, "D3D9_SetFogEnd"); -} - -D3DFOGMODE d3d9_fogTableMode = D3DFOG_NONE; -void Gfx_SetFogMode(int fogMode) { - D3DFOGMODE mode = d3d9_modes[fogMode]; - if (mode == d3d9_fogTableMode) return; - d3d9_fogTableMode = mode; - if (Gfx_LostContext) return; - D3D9_SetRenderState(D3DRS_FOGTABLEMODE, mode, "D3D9_SetFogMode"); -} - - -void Gfx_SetFaceCulling(bool enabled) { - D3DCULL mode = enabled ? D3DCULL_CW : D3DCULL_NONE; - D3D9_SetRenderState(D3DRS_CULLMODE, mode, "D3D9_SetFaceCulling"); -} - -bool d3d9_alphaTest = false; -void Gfx_SetAlphaTest(bool enabled) { - if (d3d9_alphaTest == enabled) return; - - d3d9_alphaTest = enabled; - D3D9_SetRenderState(D3DRS_ALPHATESTENABLE, (uint32_t)enabled, "D3D9_SetAlphaTest"); -} - -D3DCMPFUNC d3d9_alphaTestFunc = D3DCMP_ALWAYS; -int d3d9_alphaTestRef = 0; -void Gfx_SetAlphaTestFunc(int compareFunc, float refValue) { - d3d9_alphaTestFunc = d3d9_compareFuncs[compareFunc]; - D3D9_SetRenderState(D3DRS_ALPHAFUNC, d3d9_alphaTestFunc, "D3D9_SetAlphaTest_Func"); - d3d9_alphaTestRef = (int)(refValue * 255); - D3D9_SetRenderState2(D3DRS_ALPHAREF, d3d9_alphaTestRef, "D3D9_SetAlphaTest_Ref"); -} - -bool d3d9_alphaBlend = false; -void Gfx_SetAlphaBlending(bool enabled) { - if (d3d9_alphaBlend == enabled) return; - - d3d9_alphaBlend = enabled; - D3D9_SetRenderState(D3DRS_ALPHABLENDENABLE, (uint32_t)enabled, "D3D9_SetAlphaBlending"); -} - -D3DBLEND d3d9_srcBlendFunc = D3DBLEND_ONE; -D3DBLEND d3d9_dstBlendFunc = D3DBLEND_ZERO; -void Gfx_SetAlphaBlendFunc(int srcBlendFunc, int dstBlendFunc) { - d3d9_srcBlendFunc = d3d9_blendFuncs[srcBlendFunc]; - D3D9_SetRenderState(D3DRS_SRCBLEND, d3d9_srcBlendFunc, "D3D9_SetAlphaBlendFunc_Src"); - d3d9_dstBlendFunc = d3d9_blendFuncs[dstBlendFunc]; - D3D9_SetRenderState2(D3DRS_DESTBLEND, d3d9_dstBlendFunc, "D3D9_SetAlphaBlendFunc_Dst"); -} - -void Gfx_SetAlphaArgBlend(bool enabled) { - D3DTEXTUREOP op = enabled ? D3DTOP_MODULATE : D3DTOP_SELECTARG1; - ReturnCode res = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, op); - if (res) ErrorHandler_Fail2(res, "D3D9_SetAlphaArgBlend"); -} - - -uint32_t d3d9_clearCol = 0xFF000000; -void Gfx_Clear(void) { - DWORD flags = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER; - ReturnCode res = IDirect3DDevice9_Clear(device, 0, NULL, flags, d3d9_clearCol, 1.0f, 0); - if (res) ErrorHandler_Fail2(res, "D3D9_Clear"); -} - -void Gfx_ClearCol(PackedCol col) { - d3d9_clearCol = col.Packed; -} - -bool d3d9_depthTest = false; -void Gfx_SetDepthTest(bool enabled) { - d3d9_depthTest = enabled; - D3D9_SetRenderState(D3DRS_ZENABLE, (uint32_t)enabled, "D3D9_SetDepthTest"); -} - -D3DCMPFUNC d3d9_depthTestFunc = D3DCMP_LESSEQUAL; -void Gfx_SetDepthTestFunc(int compareFunc) { - d3d9_depthTestFunc = d3d9_compareFuncs[compareFunc]; - D3D9_SetRenderState(D3DRS_ZFUNC, d3d9_alphaTestFunc, "D3D9_SetDepthTestFunc"); -} - -void Gfx_SetColourWriteMask(bool r, bool g, bool b, bool a) { - uint32_t channels = (r ? 1u : 0u) | (g ? 2u : 0u) | (b ? 4u : 0u) | (a ? 8u : 0u); - D3D9_SetRenderState(D3DRS_COLORWRITEENABLE, channels, "D3D9_SetColourWrite"); -} - -bool d3d9_depthWrite = false; -void Gfx_SetDepthWrite(bool enabled) { - d3d9_depthWrite = enabled; - D3D9_SetRenderState(D3DRS_ZWRITEENABLE, (uint32_t)enabled, "D3D9_SetDepthWrite"); -} - - -GfxResourceID Gfx_CreateDynamicVb(int vertexFormat, int maxVertices) { - int size = maxVertices * Gfx_strideSizes[vertexFormat]; - IDirect3DVertexBuffer9* vbuffer; - ReturnCode res = IDirect3DDevice9_CreateVertexBuffer(device, size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, - d3d9_formatMappings[vertexFormat], D3DPOOL_DEFAULT, &vbuffer, NULL); - if (res) ErrorHandler_Fail2(res, "D3D9_CreateDynamicVb"); - - return vbuffer; -} - -static void D3D9_SetVbData(IDirect3DVertexBuffer9* buffer, void* data, int size, const char* lockMsg, const char* unlockMsg, int lockFlags) { - void* dst = NULL; - ReturnCode res = IDirect3DVertexBuffer9_Lock(buffer, 0, size, &dst, lockFlags); - if (res) ErrorHandler_Fail2(res, lockMsg); - - Mem_Copy(dst, data, size); - res = IDirect3DVertexBuffer9_Unlock(buffer); - if (res) ErrorHandler_Fail2(res, unlockMsg); -} - -GfxResourceID Gfx_CreateVb(void* vertices, int vertexFormat, int count) { - int size = count * Gfx_strideSizes[vertexFormat]; - IDirect3DVertexBuffer9* vbuffer; - - for (;;) { - ReturnCode res = IDirect3DDevice9_CreateVertexBuffer(device, size, D3DUSAGE_WRITEONLY, - d3d9_formatMappings[vertexFormat], D3DPOOL_DEFAULT, &vbuffer, NULL); - if (!res) break; - - if (res != D3DERR_OUTOFVIDEOMEMORY) ErrorHandler_Fail2(res, "D3D9_CreateVb"); - Event_RaiseVoid(&GfxEvents_LowVRAMDetected); - } - - D3D9_SetVbData(vbuffer, vertices, size, "D3D9_CreateVb - Lock", "D3D9_CreateVb - Unlock", 0); - return vbuffer; -} - -static void D3D9_SetIbData(IDirect3DIndexBuffer9* buffer, void* data, int size) { - void* dst = NULL; - ReturnCode res = IDirect3DIndexBuffer9_Lock(buffer, 0, size, &dst, 0); - if (res) ErrorHandler_Fail2(res, "D3D9_CreateIb - Lock"); - - Mem_Copy(dst, data, size); - res = IDirect3DIndexBuffer9_Unlock(buffer); - if (res) ErrorHandler_Fail2(res, "D3D9_CreateIb - Unlock"); -} - -GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { - int size = indicesCount * 2; - IDirect3DIndexBuffer9* ibuffer; - ReturnCode res = IDirect3DDevice9_CreateIndexBuffer(device, size, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ibuffer, NULL); - if (res) ErrorHandler_Fail2(res, "D3D9_CreateIb"); - - D3D9_SetIbData(ibuffer, indices, size); - return ibuffer; -} - -int d3d9_batchStride; -void Gfx_BindVb(GfxResourceID vb) { - IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb; - ReturnCode res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, d3d9_batchStride); - if (res) ErrorHandler_Fail2(res, "D3D9_BindVb"); -} - -void Gfx_BindIb(GfxResourceID ib) { - IDirect3DIndexBuffer9* ibuffer = (IDirect3DIndexBuffer9*)ib; - ReturnCode res = IDirect3DDevice9_SetIndices(device, ibuffer); - if (res) ErrorHandler_Fail2(res, "D3D9_BindIb"); -} - -void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); } -void Gfx_DeleteIb(GfxResourceID* ib) { D3D9_FreeResource(ib); } - -int d3d9_batchFormat = -1; -void Gfx_SetBatchFormat(int format) { - if (format == d3d9_batchFormat) return; - d3d9_batchFormat = format; - - ReturnCode res = IDirect3DDevice9_SetFVF(device, d3d9_formatMappings[format]); - if (res) ErrorHandler_Fail2(res, "D3D9_SetBatchFormat"); - d3d9_batchStride = Gfx_strideSizes[format]; -} - -void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { - int size = vCount * d3d9_batchStride; - IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb; - D3D9_SetVbData(vbuffer, vertices, size, "D3D9_SetDynamicVbData - Lock", "D3D9_SetDynamicVbData - Unlock", D3DLOCK_DISCARD); - - ReturnCode res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, d3d9_batchStride); - if (res) ErrorHandler_Fail2(res, "D3D9_SetDynamicVbData - Bind"); -} - -void Gfx_DrawVb_Lines(int verticesCount) { - ReturnCode res = IDirect3DDevice9_DrawPrimitive(device, D3DPT_LINELIST, 0, verticesCount >> 1); - if (res) ErrorHandler_Fail2(res, "D3D9_DrawVb_Lines"); -} - -void Gfx_DrawVb_IndexedTris(int verticesCount) { - ReturnCode res = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, - 0, 0, verticesCount, 0, verticesCount >> 1); - if (res) ErrorHandler_Fail2(res, "D3D9_DrawVb_IndexedTris"); -} - -void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { - ReturnCode res = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, - startVertex, 0, verticesCount, 0, verticesCount >> 1); - if (res) ErrorHandler_Fail2(res, "D3D9_DrawVb_IndexedTris"); -} - -void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) { - ReturnCode res = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, - startVertex, 0, verticesCount, 0, verticesCount >> 1); - if (res) ErrorHandler_Fail2(res, "D3D9_DrawIndexedVb_TrisT2fC4b"); -} - - -void Gfx_SetMatrixMode(int matrixType) { - if (matrixType == MATRIX_TYPE_PROJECTION) { - curMatrix = D3DTS_PROJECTION; - } else if (matrixType == MATRIX_TYPE_VIEW) { - curMatrix = D3DTS_VIEW; - } else if (matrixType == MATRIX_TYPE_TEXTURE) { - curMatrix = D3DTS_TEXTURE0; - } -} - -void Gfx_LoadMatrix(struct Matrix* matrix) { - if (curMatrix == D3DTS_TEXTURE0) { - matrix->Row2.X = matrix->Row3.X; /* NOTE: this hack fixes the texture movements. */ - IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); - } - - if (Gfx_LostContext) return; - ReturnCode res = IDirect3DDevice9_SetTransform(device, curMatrix, matrix); - if (res) ErrorHandler_Fail2(res, "D3D9_LoadMatrix"); -} - -void Gfx_LoadIdentityMatrix(void) { - if (curMatrix == D3DTS_TEXTURE0) { - IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); - } - - if (Gfx_LostContext) return; - ReturnCode res = IDirect3DDevice9_SetTransform(device, curMatrix, &Matrix_Identity); - if (res) ErrorHandler_Fail2(res, "D3D9_LoadIdentityMatrix"); -} - -#define d3d9_zN -10000.0f -#define d3d9_zF 10000.0f -void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) { - Matrix_OrthographicOffCenter(matrix, 0.0f, width, height, 0.0f, d3d9_zN, d3d9_zF); - matrix->Row2.Z = 1.0f / (d3d9_zN - d3d9_zF); - matrix->Row3.Z = d3d9_zN / (d3d9_zN - d3d9_zF); -} -void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) { - Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar); -} - - -ReturnCode Gfx_TakeScreenshot(struct Stream* output, int width, int height) { - IDirect3DSurface9* backbuffer = NULL; - IDirect3DSurface9* temp = NULL; - ReturnCode res; - - res = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); - if (res) goto finished; - res = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &temp, NULL); - if (res) goto finished; /* TODO: For DX 8 use IDirect3DDevice8::CreateImageSurface */ - res = IDirect3DDevice9_GetRenderTargetData(device, backbuffer, temp); - if (res) goto finished; - - D3DLOCKED_RECT rect; - res = IDirect3DSurface9_LockRect(temp, &rect, NULL, D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE); - if (res) goto finished; - { - Bitmap bmp; Bitmap_Create(&bmp, width, height, rect.pBits); - res = Bitmap_EncodePng(&bmp, output); - if (res) { IDirect3DSurface9_UnlockRect(temp); goto finished; } - } - res = IDirect3DSurface9_UnlockRect(temp); - if (res) goto finished; - -finished: - D3D9_FreeResource(&backbuffer); - D3D9_FreeResource(&temp); - return res; -} - -bool Gfx_WarnIfNecessary(void) { return false; } - -void Gfx_SetVSync(bool value) { - if (d3d9_vsync == value) return; - d3d9_vsync = value; - - GfxCommon_LoseContext(" (toggling VSync)"); - D3D9_RecreateDevice(); -} - -void Gfx_BeginFrame(void) { - IDirect3DDevice9_BeginScene(device); -} - -void Gfx_EndFrame(void) { - IDirect3DDevice9_EndScene(device); - ReturnCode res = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - if (!res) return; - if (res != D3DERR_DEVICELOST) ErrorHandler_Fail2(res, "D3D9_EndFrame"); - - /* TODO: Make sure this actually works on all graphics cards.*/ - GfxCommon_LoseContext(" (Direct3D9 device lost)"); - D3D9_LoopUntilRetrieved(); - D3D9_RecreateDevice(); -} - -const char* D3D9_StrFlags(void) { - if (createFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) return "Hardware"; - if (createFlags & D3DCREATE_MIXED_VERTEXPROCESSING) return "Mixed"; - if (createFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) return "Software"; - return "(none)"; -} - -const char* D3D9_StrFormat(D3DFORMAT format) { - switch (format) { - case D3DFMT_D32: return "D32"; - case D3DFMT_D24X8: return "D24X8"; - case D3DFMT_D24S8: return "D24S8"; - case D3DFMT_D24X4S4: return "D24X4S4"; - case D3DFMT_D16: return "D16"; - case D3DFMT_D15S1: return "D15S1"; - - case D3DFMT_X8R8G8B8: return "X8R8G8B8"; - case D3DFMT_R8G8B8: return "R8G8B8"; - case D3DFMT_R5G6B5: return "R5G6B5"; - case D3DFMT_X1R5G5B5: return "X1R5G5B5"; - } - return "(unknown)"; -} - -float d3d9_totalMem; -void Gfx_MakeApiInfo(void) { - D3DADAPTER_IDENTIFIER9 adapter = { 0 }; - IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &adapter); - d3d9_totalMem = IDirect3DDevice9_GetAvailableTextureMem(device) / (1024.0f * 1024.0f); - - String_AppendConst(&Gfx_ApiInfo[0],"-- Using Direct3D9 --"); - String_Format1(&Gfx_ApiInfo[1], "Adapter: %c", adapter.Description); - String_Format1(&Gfx_ApiInfo[2], "Processing mode: %c", D3D9_StrFlags()); - Gfx_UpdateApiInfo(); - String_Format2(&Gfx_ApiInfo[4], "Max texture size: (%i, %i)", &Gfx_MaxTexWidth, &Gfx_MaxTexHeight); - String_Format1(&Gfx_ApiInfo[5], "Depth buffer format: %c", D3D9_StrFormat(d3d9_depthFormat)); - String_Format1(&Gfx_ApiInfo[6], "Back buffer format: %c", D3D9_StrFormat(d3d9_viewFormat)); -} - -void Gfx_UpdateApiInfo(void) { - float mem = IDirect3DDevice9_GetAvailableTextureMem(device) / (1024.0f * 1024.0f); - Gfx_ApiInfo[3].length = 0; - String_Format2(&Gfx_ApiInfo[3], "Video memory: %f2 MB total, %f2 free", &d3d9_totalMem, &mem); -} - -void Gfx_OnWindowResize(void) { - GfxCommon_LoseContext(" (resizing window)"); - D3D9_RecreateDevice(); -} - - -static void D3D9_SetDefaultRenderStates(void) { - Gfx_SetFaceCulling(false); - d3d9_batchFormat = -1; - D3D9_SetRenderState(D3DRS_COLORVERTEX, false, "D3D9_ColorVertex"); - D3D9_SetRenderState2(D3DRS_LIGHTING, false, "D3D9_Lighting"); - D3D9_SetRenderState2(D3DRS_SPECULARENABLE, false, "D3D9_SpecularEnable"); - D3D9_SetRenderState2(D3DRS_LOCALVIEWER, false, "D3D9_LocalViewer"); - D3D9_SetRenderState2(D3DRS_DEBUGMONITORTOKEN, false, "D3D9_DebugMonitor"); -} - -static void D3D9_RestoreRenderStates(void) { - union IntAndFloat raw; - D3D9_SetRenderState(D3DRS_ALPHATESTENABLE, d3d9_alphaTest, "D3D9_AlphaTest"); - D3D9_SetRenderState2(D3DRS_ALPHABLENDENABLE, d3d9_alphaBlend, "D3D9_AlphaBlend"); - D3D9_SetRenderState2(D3DRS_ALPHAFUNC, d3d9_alphaTestFunc, "D3D9_AlphaTestFunc"); - D3D9_SetRenderState2(D3DRS_ALPHAREF, d3d9_alphaTestRef, "D3D9_AlphaRefFunc"); - D3D9_SetRenderState2(D3DRS_SRCBLEND, d3d9_srcBlendFunc, "D3D9_AlphaSrcBlend"); - D3D9_SetRenderState2(D3DRS_DESTBLEND, d3d9_dstBlendFunc, "D3D9_AlphaDstBlend"); - D3D9_SetRenderState2(D3DRS_FOGENABLE, d3d9_fogEnable, "D3D9_Fog"); - D3D9_SetRenderState2(D3DRS_FOGCOLOR, d3d9_fogCol, "D3D9_FogColor"); - raw.f = d3d9_fogDensity; - D3D9_SetRenderState2(D3DRS_FOGDENSITY, raw.u, "D3D9_FogDensity"); - raw.f = d3d9_fogEnd; - D3D9_SetRenderState2(D3DRS_FOGEND, raw.u, "D3D9_FogEnd"); - D3D9_SetRenderState2(D3DRS_FOGTABLEMODE, d3d9_fogTableMode, "D3D9_FogMode"); - D3D9_SetRenderState2(D3DRS_ZFUNC, d3d9_depthTestFunc, "D3D9_DepthTestFunc"); - D3D9_SetRenderState2(D3DRS_ZENABLE, d3d9_depthTest, "D3D9_DepthTest"); - D3D9_SetRenderState2(D3DRS_ZWRITEENABLE, d3d9_depthWrite, "D3D9_DepthWrite"); -} -#endif diff --git a/src/Drawer2D.c b/src/Drawer2D.c index 84b042084..f578a1fa4 100644 --- a/src/Drawer2D.c +++ b/src/Drawer2D.c @@ -1,5 +1,5 @@ #include "Drawer2D.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Funcs.h" #include "Platform.h" #include "ExtMath.h" diff --git a/src/Entity.c b/src/Entity.c index c807517ac..9b91aef62 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -8,7 +8,7 @@ #include "Platform.h" #include "Funcs.h" #include "ModelCache.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Lighting.h" #include "Drawer2D.h" #include "Particle.h" diff --git a/src/EntityComponents.c b/src/EntityComponents.c index 10a8d0016..0fe63fd38 100644 --- a/src/EntityComponents.c +++ b/src/EntityComponents.c @@ -9,7 +9,7 @@ #include "Camera.h" #include "Funcs.h" #include "VertexStructs.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "GraphicsCommon.h" #include "ModelCache.h" #include "Physics.h" diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index b2d3bb5cd..c54d2de81 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -2,7 +2,7 @@ #include "ExtMath.h" #include "World.h" #include "Funcs.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Physics.h" #include "Block.h" #include "Platform.h" diff --git a/src/Game.c b/src/Game.c index bf03e43cf..a5b6c89dd 100644 --- a/src/Game.c +++ b/src/Game.c @@ -3,7 +3,7 @@ #include "World.h" #include "Lighting.h" #include "MapRenderer.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Camera.h" #include "Options.h" #include "Funcs.h" diff --git a/src/Graphics.c b/src/Graphics.c new file mode 100644 index 000000000..809f48826 --- /dev/null +++ b/src/Graphics.c @@ -0,0 +1,1315 @@ +#include "Graphics.h" +#include "ErrorHandler.h" +#include "Platform.h" +#include "Window.h" +#include "GraphicsCommon.h" +#include "Funcs.h" +#include "Chat.h" +#include "Game.h" +#include "ExtMath.h" +#include "Bitmap.h" +#include "Event.h" + +int Gfx_strideSizes[2] = { 16, 24 }; +int gfx_batchStride, gfx_batchFormat = -1; + +bool gfx_vsync, gfx_fogEnabled; +bool Gfx_GetFog(void) { return gfx_fogEnabled; } + +/*########################################################################################################################* +*--------------------------------------------------------Direct3D9--------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_BUILD_D3D9 +//#define D3D_DISABLE_9EX causes compile errors +#define WIN32_LEAN_AND_MEAN +#define NOSERVICE +#define NOMCX +#define NOIME +#include +#include +#include + +D3DCMPFUNC d3d9_compareFuncs[8] = { D3DCMP_ALWAYS, D3DCMP_NOTEQUAL, D3DCMP_NEVER, D3DCMP_LESS, D3DCMP_LESSEQUAL, D3DCMP_EQUAL, D3DCMP_GREATEREQUAL, D3DCMP_GREATER }; +DWORD d3d9_formatMappings[2] = { D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2 }; + +IDirect3D9* d3d; +IDirect3DDevice9* device; +D3DTRANSFORMSTATETYPE curMatrix; +DWORD createFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; +D3DFORMAT d3d9_viewFormat, d3d9_depthFormat; + +#define D3D9_SetRenderState(state, value, name) \ +ReturnCode res = IDirect3DDevice9_SetRenderState(device, state, value); if (res) ErrorHandler_Fail2(res, name); +#define D3D9_SetRenderState2(state, value, name) \ +res = IDirect3DDevice9_SetRenderState(device, state, value); if (res) ErrorHandler_Fail2(res, name); + +static void D3D9_SetDefaultRenderStates(void); +static void D3D9_RestoreRenderStates(void); + +static void D3D9_FreeResource(GfxResourceID* resource) { + if (!resource || *resource == GFX_NULL) return; + IUnknown* unk = (IUnknown*)(*resource); + ULONG refCount = unk->lpVtbl->Release(unk); + *resource = GFX_NULL; + if (refCount <= 0) return; + + uintptr_t addr = (uintptr_t)unk; + Platform_Log2("D3D9 resource has %i outstanding references! ID 0x%x", &refCount, &addr); +} + +static void D3D9_LoopUntilRetrieved(void) { + struct ScheduledTask task; + task.Interval = 1.0f / 60.0f; + task.Callback = Gfx_LostContextFunction; + + while (true) { + Thread_Sleep(16); + ReturnCode code = IDirect3DDevice9_TestCooperativeLevel(device); + if (code == D3DERR_DEVICENOTRESET) return; + + task.Callback(&task); + } +} + +static void D3D9_FindCompatibleFormat(void) { + static D3DFORMAT depthFormats[6] = { D3DFMT_D32, D3DFMT_D24X8, D3DFMT_D24S8, D3DFMT_D24X4S4, D3DFMT_D16, D3DFMT_D15S1 }; + static D3DFORMAT viewFormats[4] = { D3DFMT_X8R8G8B8, D3DFMT_R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 }; + ReturnCode res; + int i, count = Array_Elems(viewFormats); + + for (i = 0; i < count; i++) { + d3d9_viewFormat = viewFormats[i]; + res = IDirect3D9_CheckDeviceType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3d9_viewFormat, d3d9_viewFormat, true); + if (!res) break; + } + if (i == count) ErrorHandler_Fail("Unable to create a back buffer with sufficient precision."); + + count = Array_Elems(depthFormats); + for (i = 0; i < count; i++) { + d3d9_depthFormat = depthFormats[i]; + res = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3d9_viewFormat, d3d9_viewFormat, d3d9_depthFormat); + if (!res) break; + } + if (i == count) ErrorHandler_Fail("Unable to create a depth buffer with sufficient precision."); +} + +static void D3D9_FillPresentArgs(int width, int height, D3DPRESENT_PARAMETERS* args) { + args->AutoDepthStencilFormat = d3d9_depthFormat; + args->BackBufferWidth = width; + args->BackBufferHeight = height; + args->BackBufferFormat = d3d9_viewFormat; + args->BackBufferCount = 1; + args->EnableAutoDepthStencil = true; + args->PresentationInterval = gfx_vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + args->SwapEffect = D3DSWAPEFFECT_DISCARD; + args->Windowed = true; +} + +static void D3D9_RecreateDevice(void) { + D3DPRESENT_PARAMETERS args = { 0 }; + D3D9_FillPresentArgs(Game_Width, Game_Height, &args); + + while (IDirect3DDevice9_Reset(device, &args) == D3DERR_DEVICELOST) { + D3D9_LoopUntilRetrieved(); + } + + D3D9_SetDefaultRenderStates(); + D3D9_RestoreRenderStates(); + GfxCommon_RecreateContext(); +} + +void Gfx_Init(void) { + Gfx_MinZNear = 0.05f; + void* winHandle = Window_GetWindowHandle(); + d3d = Direct3DCreate9(D3D_SDK_VERSION); + + D3D9_FindCompatibleFormat(); + D3DPRESENT_PARAMETERS args = { 0 }; + D3D9_FillPresentArgs(640, 480, &args); + ReturnCode res; + + /* Try to create a device with as much hardware usage as possible. */ + res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device); + if (res) { + createFlags = D3DCREATE_MIXED_VERTEXPROCESSING; + res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device); + } + if (res) { + createFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; + res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device); + } + if (res) ErrorHandler_Fail2(res, "Creating Direct3D9 device"); + + D3DCAPS9 caps; + res = IDirect3DDevice9_GetDeviceCaps(device, &caps); + if (res) ErrorHandler_Fail2(res, "Getting Direct3D9 capabilities"); + + Gfx_MaxTexWidth = caps.MaxTextureWidth; + Gfx_MaxTexHeight = caps.MaxTextureHeight; + + Gfx_CustomMipmapsLevels = true; + D3D9_SetDefaultRenderStates(); + GfxCommon_Init(); +} + +void Gfx_Free(void) { + GfxCommon_Free(); + D3D9_FreeResource(&device); + D3D9_FreeResource(&d3d); +} + + +/*########################################################################################################################* +*---------------------------------------------------------Textures--------------------------------------------------------* +*#########################################################################################################################*/ +static void D3D9_SetTextureData(IDirect3DTexture9* texture, Bitmap* bmp, int lvl) { + D3DLOCKED_RECT rect; + ReturnCode res = IDirect3DTexture9_LockRect(texture, lvl, &rect, NULL, 0); + if (res) ErrorHandler_Fail2(res, "D3D9_SetTextureData - Lock"); + + uint32_t size = Bitmap_DataSize(bmp->Width, bmp->Height); + Mem_Copy(rect.pBits, bmp->Scan0, size); + + res = IDirect3DTexture9_UnlockRect(texture, lvl); + if (res) ErrorHandler_Fail2(res, "D3D9_SetTextureData - Unlock"); +} + +static void D3D9_SetTexturePartData(IDirect3DTexture9* texture, int x, int y, Bitmap* bmp, int lvl) { + RECT part; + part.left = x; part.right = x + bmp->Width; + part.top = y; part.bottom = y + bmp->Height; + + D3DLOCKED_RECT rect; + ReturnCode res = IDirect3DTexture9_LockRect(texture, lvl, &rect, &part, 0); + if (res) ErrorHandler_Fail2(res, "D3D9_SetTexturePartData - Lock"); + + /* We need to copy scanline by scanline, as generally rect.stride != data.stride */ + uint8_t* src = (uint8_t*)bmp->Scan0; + uint8_t* dst = (uint8_t*)rect.pBits; + int yy; + uint32_t stride = (uint32_t)(bmp->Width) * BITMAP_SIZEOF_PIXEL; + + for (yy = 0; yy < bmp->Height; yy++) { + Mem_Copy(dst, src, stride); + src += stride; + dst += rect.Pitch; + } + + res = IDirect3DTexture9_UnlockRect(texture, lvl); + if (res) ErrorHandler_Fail2(res, "D3D9_SetTexturePartData - Unlock"); +} + +static void D3D9_DoMipmaps(IDirect3DTexture9* texture, int x, int y, Bitmap* bmp, bool partial) { + uint8_t* prev = bmp->Scan0; + int lvls = GfxCommon_MipmapsLevels(bmp->Width, bmp->Height); + int lvl, width = bmp->Width, height = bmp->Height; + + for (lvl = 1; lvl <= lvls; lvl++) { + x /= 2; y /= 2; + if (width > 1) width /= 2; + if (height > 1) height /= 2; + + uint8_t* cur = Mem_Alloc(width * height, BITMAP_SIZEOF_PIXEL, "mipmaps"); + GfxCommon_GenMipmaps(width, height, cur, prev); + + Bitmap mipmap; + Bitmap_Create(&mipmap, width, height, cur); + if (partial) { + D3D9_SetTexturePartData(texture, x, y, &mipmap, lvl); + } else { + D3D9_SetTextureData(texture, &mipmap, lvl); + } + + if (prev != bmp->Scan0) Mem_Free(prev); + prev = cur; + } + if (prev != bmp->Scan0) Mem_Free(prev); +} + +GfxResourceID Gfx_CreateTexture(Bitmap* bmp, bool managedPool, bool mipmaps) { + IDirect3DTexture9* tex; + ReturnCode res; + int mipmapsLevels = GfxCommon_MipmapsLevels(bmp->Width, bmp->Height); + int levels = 1 + (mipmaps ? mipmapsLevels : 0); + + if (!Math_IsPowOf2(bmp->Width) || !Math_IsPowOf2(bmp->Height)) { + ErrorHandler_Fail("Textures must have power of two dimensions"); + } + + if (managedPool) { + res = IDirect3DDevice9_CreateTexture(device, bmp->Width, bmp->Height, levels, + 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex, NULL); + if (res) ErrorHandler_Fail2(res, "D3D9_CreateTexture"); + + D3D9_SetTextureData(tex, bmp, 0); + if (mipmaps) D3D9_DoMipmaps(tex, 0, 0, bmp, false); + } else { + IDirect3DTexture9* sys; + res = IDirect3DDevice9_CreateTexture(device, bmp->Width, bmp->Height, levels, + 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &sys, NULL); + if (res) ErrorHandler_Fail2(res, "D3D9_CreateTexture - SystemMem"); + + D3D9_SetTextureData(sys, bmp, 0); + if (mipmaps) D3D9_DoMipmaps(sys, 0, 0, bmp, false); + + res = IDirect3DDevice9_CreateTexture(device, bmp->Width, bmp->Height, levels, + 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); + if (res) ErrorHandler_Fail2(res, "D3D9_CreateTexture - GPU"); + + res = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)sys, (IDirect3DBaseTexture9*)tex); + if (res) ErrorHandler_Fail2(res, "D3D9_CreateTexture - Update"); + D3D9_FreeResource(&sys); + } + return tex; +} + +void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, Bitmap* part, bool mipmaps) { + IDirect3DTexture9* texture = (IDirect3DTexture9*)texId; + D3D9_SetTexturePartData(texture, x, y, part, 0); + if (mipmaps) D3D9_DoMipmaps(texture, x, y, part, true); +} + +void Gfx_BindTexture(GfxResourceID texId) { + ReturnCode res = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9*)texId); + if (res) ErrorHandler_Fail2(res, "D3D9_BindTexture"); +} + +void Gfx_DeleteTexture(GfxResourceID* texId) { D3D9_FreeResource(texId); } + +void Gfx_SetTexturing(bool enabled) { + if (enabled) return; + ReturnCode res = IDirect3DDevice9_SetTexture(device, 0, NULL); + if (res) ErrorHandler_Fail2(res, "D3D9_SetTexturing"); +} + +void Gfx_EnableMipmaps(void) { + if (Gfx_Mipmaps) { + ReturnCode res = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + if (res) ErrorHandler_Fail2(res, "D3D9_EnableMipmaps"); + } +} + +void Gfx_DisableMipmaps(void) { + if (Gfx_Mipmaps) { + ReturnCode res = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); + if (res) ErrorHandler_Fail2(res, "D3D9_DisableMipmaps"); + } +} + + +/*########################################################################################################################* +*-----------------------------------------------------State management----------------------------------------------------* +*#########################################################################################################################*/ +uint32_t d3d9_fogCol = 0xFF000000; /* black */ +float d3d9_fogDensity = -1.0f, d3d9_fogEnd = -1.0f; +D3DFOGMODE d3d9_fogMode = D3DFOG_NONE; + +bool d3d9_alphaTesting, d3d9_alphaBlending; +int d3d9_alphaTestRef; +D3DCMPFUNC d3d9_alphaTestFunc = D3DCMP_ALWAYS; +D3DBLEND d3d9_srcBlendFunc = D3DBLEND_ONE, d3d9_dstBlendFunc = D3DBLEND_ZERO; + +uint32_t d3d9_clearCol = 0xFF000000; /* black */ +bool d3d9_depthTesting, d3d9_depthWriting; +D3DCMPFUNC d3d9_depthTestFunc = D3DCMP_LESSEQUAL; + +void Gfx_SetFaceCulling(bool enabled) { + D3DCULL mode = enabled ? D3DCULL_CW : D3DCULL_NONE; + D3D9_SetRenderState(D3DRS_CULLMODE, mode, "D3D9_SetFaceCulling"); +} + +void Gfx_SetFog(bool enabled) { + if (gfx_fogEnabled == enabled) return; + gfx_fogEnabled = enabled; + if (Gfx_LostContext) return; + D3D9_SetRenderState(D3DRS_FOGENABLE, enabled, "D3D9_SetFog"); +} + +void Gfx_SetFogCol(PackedCol col) { + if (col.Packed == d3d9_fogCol) return; + d3d9_fogCol = col.Packed; + if (Gfx_LostContext) return; + D3D9_SetRenderState(D3DRS_FOGCOLOR, col.Packed, "D3D9_SetFogColour"); +} + +void Gfx_SetFogDensity(float value) { + if (value == d3d9_fogDensity) return; + d3d9_fogDensity = value; + if (Gfx_LostContext) return; + union IntAndFloat raw; raw.f = value; + D3D9_SetRenderState(D3DRS_FOGDENSITY, raw.u, "D3D9_SetFogDensity"); +} + +void Gfx_SetFogEnd(float value) { + if (value == d3d9_fogEnd) return; + d3d9_fogEnd = value; + if (Gfx_LostContext) return; + union IntAndFloat raw; raw.f = value; + D3D9_SetRenderState(D3DRS_FOGEND, raw.u, "D3D9_SetFogEnd"); +} + +void Gfx_SetFogMode(int fogMode) { + static D3DFOGMODE modes[3] = { D3DFOG_LINEAR, D3DFOG_EXP, D3DFOG_EXP2 }; + D3DFOGMODE mode = modes[fogMode]; + if (mode == d3d9_fogMode) return; + + d3d9_fogMode = mode; + if (Gfx_LostContext) return; + D3D9_SetRenderState(D3DRS_FOGTABLEMODE, mode, "D3D9_SetFogMode"); +} + +void Gfx_SetAlphaTest(bool enabled) { + if (d3d9_alphaTesting == enabled) return; + d3d9_alphaTesting = enabled; + D3D9_SetRenderState(D3DRS_ALPHATESTENABLE, enabled, "D3D9_SetAlphaTest"); +} + +void Gfx_SetAlphaTestFunc(int compareFunc, float refValue) { + d3d9_alphaTestFunc = d3d9_compareFuncs[compareFunc]; + D3D9_SetRenderState(D3DRS_ALPHAFUNC, d3d9_alphaTestFunc, "D3D9_SetAlphaTest_Func"); + d3d9_alphaTestRef = (int)(refValue * 255); + D3D9_SetRenderState2(D3DRS_ALPHAREF, d3d9_alphaTestRef, "D3D9_SetAlphaTest_Ref"); +} + +void Gfx_SetAlphaBlending(bool enabled) { + if (d3d9_alphaBlending == enabled) return; + d3d9_alphaBlending = enabled; + D3D9_SetRenderState(D3DRS_ALPHABLENDENABLE, enabled, "D3D9_SetAlphaBlending"); +} + +void Gfx_SetAlphaBlendFunc(int srcBlendFunc, int dstBlendFunc) { + static D3DBLEND funcs[6] = { D3DBLEND_ZERO, D3DBLEND_ONE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_DESTALPHA, D3DBLEND_INVDESTALPHA }; + + d3d9_srcBlendFunc = funcs[srcBlendFunc]; + D3D9_SetRenderState(D3DRS_SRCBLEND, d3d9_srcBlendFunc, "D3D9_SetAlphaBlendFunc_Src"); + d3d9_dstBlendFunc = funcs[dstBlendFunc]; + D3D9_SetRenderState2(D3DRS_DESTBLEND, d3d9_dstBlendFunc, "D3D9_SetAlphaBlendFunc_Dst"); +} + +void Gfx_SetAlphaArgBlend(bool enabled) { + D3DTEXTUREOP op = enabled ? D3DTOP_MODULATE : D3DTOP_SELECTARG1; + ReturnCode res = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, op); + if (res) ErrorHandler_Fail2(res, "D3D9_SetAlphaArgBlend"); +} + +void Gfx_ClearCol(PackedCol col) { d3d9_clearCol = col.Packed; } +void Gfx_SetColourWriteMask(bool r, bool g, bool b, bool a) { + DWORD channels = (r ? 1u : 0u) | (g ? 2u : 0u) | (b ? 4u : 0u) | (a ? 8u : 0u); + D3D9_SetRenderState(D3DRS_COLORWRITEENABLE, channels, "D3D9_SetColourWrite"); +} + +void Gfx_SetDepthTest(bool enabled) { + d3d9_depthTesting = enabled; + D3D9_SetRenderState(D3DRS_ZENABLE, enabled, "D3D9_SetDepthTest"); +} + +void Gfx_SetDepthTestFunc(int compareFunc) { + d3d9_depthTestFunc = d3d9_compareFuncs[compareFunc]; + D3D9_SetRenderState(D3DRS_ZFUNC, d3d9_alphaTestFunc, "D3D9_SetDepthTestFunc"); +} + +void Gfx_SetDepthWrite(bool enabled) { + d3d9_depthWriting = enabled; + D3D9_SetRenderState(D3DRS_ZWRITEENABLE, enabled, "D3D9_SetDepthWrite"); +} + +static void D3D9_SetDefaultRenderStates(void) { + Gfx_SetFaceCulling(false); + gfx_batchFormat = -1; + D3D9_SetRenderState(D3DRS_COLORVERTEX, false, "D3D9_ColorVertex"); + D3D9_SetRenderState2(D3DRS_LIGHTING, false, "D3D9_Lighting"); + D3D9_SetRenderState2(D3DRS_SPECULARENABLE, false, "D3D9_SpecularEnable"); + D3D9_SetRenderState2(D3DRS_LOCALVIEWER, false, "D3D9_LocalViewer"); + D3D9_SetRenderState2(D3DRS_DEBUGMONITORTOKEN, false, "D3D9_DebugMonitor"); +} + +static void D3D9_RestoreRenderStates(void) { + union IntAndFloat raw; + D3D9_SetRenderState(D3DRS_ALPHATESTENABLE, d3d9_alphaTesting, "D3D9_AlphaTest"); + D3D9_SetRenderState2(D3DRS_ALPHABLENDENABLE, d3d9_alphaBlending, "D3D9_AlphaBlend"); + D3D9_SetRenderState2(D3DRS_ALPHAFUNC, d3d9_alphaTestFunc, "D3D9_AlphaTestFunc"); + D3D9_SetRenderState2(D3DRS_ALPHAREF, d3d9_alphaTestRef, "D3D9_AlphaRefFunc"); + D3D9_SetRenderState2(D3DRS_SRCBLEND, d3d9_srcBlendFunc, "D3D9_AlphaSrcBlend"); + D3D9_SetRenderState2(D3DRS_DESTBLEND, d3d9_dstBlendFunc, "D3D9_AlphaDstBlend"); + + D3D9_SetRenderState2(D3DRS_FOGENABLE, gfx_fogEnabled, "D3D9_Fog"); + D3D9_SetRenderState2(D3DRS_FOGCOLOR, d3d9_fogCol, "D3D9_FogColor"); + raw.f = d3d9_fogDensity; + D3D9_SetRenderState2(D3DRS_FOGDENSITY, raw.u, "D3D9_FogDensity"); + raw.f = d3d9_fogEnd; + D3D9_SetRenderState2(D3DRS_FOGEND, raw.u, "D3D9_FogEnd"); + D3D9_SetRenderState2(D3DRS_FOGTABLEMODE, d3d9_fogMode, "D3D9_FogMode"); + + D3D9_SetRenderState2(D3DRS_ZFUNC, d3d9_depthTestFunc, "D3D9_DepthTestFunc"); + D3D9_SetRenderState2(D3DRS_ZENABLE, d3d9_depthTesting, "D3D9_DepthTest"); + D3D9_SetRenderState2(D3DRS_ZWRITEENABLE, d3d9_depthWriting, "D3D9_DepthWrite"); +} + + +/*########################################################################################################################* +*---------------------------------------------------Vertex/Index buffers--------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_CreateDynamicVb(int vertexFormat, int maxVertices) { + int size = maxVertices * Gfx_strideSizes[vertexFormat]; + IDirect3DVertexBuffer9* vbuffer; + ReturnCode res = IDirect3DDevice9_CreateVertexBuffer(device, size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, + d3d9_formatMappings[vertexFormat], D3DPOOL_DEFAULT, &vbuffer, NULL); + if (res) ErrorHandler_Fail2(res, "D3D9_CreateDynamicVb"); + + return vbuffer; +} + +static void D3D9_SetVbData(IDirect3DVertexBuffer9* buffer, void* data, int size, const char* lockMsg, const char* unlockMsg, int lockFlags) { + void* dst = NULL; + ReturnCode res = IDirect3DVertexBuffer9_Lock(buffer, 0, size, &dst, lockFlags); + if (res) ErrorHandler_Fail2(res, lockMsg); + + Mem_Copy(dst, data, size); + res = IDirect3DVertexBuffer9_Unlock(buffer); + if (res) ErrorHandler_Fail2(res, unlockMsg); +} + +GfxResourceID Gfx_CreateVb(void* vertices, int vertexFormat, int count) { + int size = count * Gfx_strideSizes[vertexFormat]; + IDirect3DVertexBuffer9* vbuffer; + + for (;;) { + ReturnCode res = IDirect3DDevice9_CreateVertexBuffer(device, size, D3DUSAGE_WRITEONLY, + d3d9_formatMappings[vertexFormat], D3DPOOL_DEFAULT, &vbuffer, NULL); + if (!res) break; + + if (res != D3DERR_OUTOFVIDEOMEMORY) ErrorHandler_Fail2(res, "D3D9_CreateVb"); + Event_RaiseVoid(&GfxEvents_LowVRAMDetected); + } + + D3D9_SetVbData(vbuffer, vertices, size, "D3D9_CreateVb - Lock", "D3D9_CreateVb - Unlock", 0); + return vbuffer; +} + +static void D3D9_SetIbData(IDirect3DIndexBuffer9* buffer, void* data, int size) { + void* dst = NULL; + ReturnCode res = IDirect3DIndexBuffer9_Lock(buffer, 0, size, &dst, 0); + if (res) ErrorHandler_Fail2(res, "D3D9_CreateIb - Lock"); + + Mem_Copy(dst, data, size); + res = IDirect3DIndexBuffer9_Unlock(buffer); + if (res) ErrorHandler_Fail2(res, "D3D9_CreateIb - Unlock"); +} + +GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { + int size = indicesCount * 2; + IDirect3DIndexBuffer9* ibuffer; + ReturnCode res = IDirect3DDevice9_CreateIndexBuffer(device, size, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ibuffer, NULL); + if (res) ErrorHandler_Fail2(res, "D3D9_CreateIb"); + + D3D9_SetIbData(ibuffer, indices, size); + return ibuffer; +} + +void Gfx_BindVb(GfxResourceID vb) { + IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb; + ReturnCode res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, gfx_batchStride); + if (res) ErrorHandler_Fail2(res, "D3D9_BindVb"); +} + +void Gfx_BindIb(GfxResourceID ib) { + IDirect3DIndexBuffer9* ibuffer = (IDirect3DIndexBuffer9*)ib; + ReturnCode res = IDirect3DDevice9_SetIndices(device, ibuffer); + if (res) ErrorHandler_Fail2(res, "D3D9_BindIb"); +} + +void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); } +void Gfx_DeleteIb(GfxResourceID* ib) { D3D9_FreeResource(ib); } + +void Gfx_SetBatchFormat(int format) { + if (format == gfx_batchFormat) return; + gfx_batchFormat = format; + + ReturnCode res = IDirect3DDevice9_SetFVF(device, d3d9_formatMappings[format]); + if (res) ErrorHandler_Fail2(res, "D3D9_SetBatchFormat"); + gfx_batchStride = Gfx_strideSizes[format]; +} + +void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { + int size = vCount * gfx_batchStride; + IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb; + D3D9_SetVbData(vbuffer, vertices, size, "D3D9_SetDynamicVbData - Lock", "D3D9_SetDynamicVbData - Unlock", D3DLOCK_DISCARD); + + ReturnCode res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, gfx_batchStride); + if (res) ErrorHandler_Fail2(res, "D3D9_SetDynamicVbData - Bind"); +} + +void Gfx_DrawVb_Lines(int verticesCount) { + ReturnCode res = IDirect3DDevice9_DrawPrimitive(device, D3DPT_LINELIST, 0, verticesCount >> 1); + if (res) ErrorHandler_Fail2(res, "D3D9_DrawVb_Lines"); +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + ReturnCode res = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, + 0, 0, verticesCount, 0, verticesCount >> 1); + if (res) ErrorHandler_Fail2(res, "D3D9_DrawVb_IndexedTris"); +} + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { + ReturnCode res = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, + startVertex, 0, verticesCount, 0, verticesCount >> 1); + if (res) ErrorHandler_Fail2(res, "D3D9_DrawVb_IndexedTris"); +} + +void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) { + ReturnCode res = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, + startVertex, 0, verticesCount, 0, verticesCount >> 1); + if (res) ErrorHandler_Fail2(res, "D3D9_DrawIndexedVb_TrisT2fC4b"); +} + + +/*########################################################################################################################* +*---------------------------------------------------------Matrices--------------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetMatrixMode(int matrixType) { + if (matrixType == MATRIX_TYPE_PROJECTION) { curMatrix = D3DTS_PROJECTION; } + else if (matrixType == MATRIX_TYPE_VIEW) { curMatrix = D3DTS_VIEW; } + else if (matrixType == MATRIX_TYPE_TEXTURE) { curMatrix = D3DTS_TEXTURE0; } +} + +void Gfx_LoadMatrix(struct Matrix* matrix) { + if (curMatrix == D3DTS_TEXTURE0) { + matrix->Row2.X = matrix->Row3.X; /* NOTE: this hack fixes the texture movements. */ + IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + } + + if (Gfx_LostContext) return; + ReturnCode res = IDirect3DDevice9_SetTransform(device, curMatrix, matrix); + if (res) ErrorHandler_Fail2(res, "D3D9_LoadMatrix"); +} + +void Gfx_LoadIdentityMatrix(void) { + if (curMatrix == D3DTS_TEXTURE0) { + IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + } + + if (Gfx_LostContext) return; + ReturnCode res = IDirect3DDevice9_SetTransform(device, curMatrix, &Matrix_Identity); + if (res) ErrorHandler_Fail2(res, "D3D9_LoadIdentityMatrix"); +} + +#define d3d9_zN -10000.0f +#define d3d9_zF 10000.0f +void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) { + Matrix_OrthographicOffCenter(matrix, 0.0f, width, height, 0.0f, d3d9_zN, d3d9_zF); + matrix->Row2.Z = 1.0f / (d3d9_zN - d3d9_zF); + matrix->Row3.Z = d3d9_zN / (d3d9_zN - d3d9_zF); +} +void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) { + Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar); +} + + +/*########################################################################################################################* +*-----------------------------------------------------------Misc----------------------------------------------------------* +*#########################################################################################################################*/ +ReturnCode Gfx_TakeScreenshot(struct Stream* output, int width, int height) { + IDirect3DSurface9* backbuffer = NULL; + IDirect3DSurface9* temp = NULL; + ReturnCode res; + + res = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + if (res) goto finished; + res = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &temp, NULL); + if (res) goto finished; /* TODO: For DX 8 use IDirect3DDevice8::CreateImageSurface */ + res = IDirect3DDevice9_GetRenderTargetData(device, backbuffer, temp); + if (res) goto finished; + + D3DLOCKED_RECT rect; + res = IDirect3DSurface9_LockRect(temp, &rect, NULL, D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE); + if (res) goto finished; + { + Bitmap bmp; Bitmap_Create(&bmp, width, height, rect.pBits); + res = Bitmap_EncodePng(&bmp, output); + if (res) { IDirect3DSurface9_UnlockRect(temp); goto finished; } + } + res = IDirect3DSurface9_UnlockRect(temp); + if (res) goto finished; + +finished: + D3D9_FreeResource(&backbuffer); + D3D9_FreeResource(&temp); + return res; +} + +void Gfx_SetVSync(bool value) { + if (gfx_vsync == value) return; + gfx_vsync = value; + + GfxCommon_LoseContext(" (toggling VSync)"); + D3D9_RecreateDevice(); +} + +void Gfx_BeginFrame(void) { IDirect3DDevice9_BeginScene(device); } +void Gfx_Clear(void) { + DWORD flags = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER; + ReturnCode res = IDirect3DDevice9_Clear(device, 0, NULL, flags, d3d9_clearCol, 1.0f, 0); + if (res) ErrorHandler_Fail2(res, "D3D9_Clear"); +} + +void Gfx_EndFrame(void) { + IDirect3DDevice9_EndScene(device); + ReturnCode res = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + if (!res) return; + if (res != D3DERR_DEVICELOST) ErrorHandler_Fail2(res, "D3D9_EndFrame"); + + /* TODO: Make sure this actually works on all graphics cards.*/ + GfxCommon_LoseContext(" (Direct3D9 device lost)"); + D3D9_LoopUntilRetrieved(); + D3D9_RecreateDevice(); +} + +bool Gfx_WarnIfNecessary(void) { return false; } +const char* D3D9_StrFlags(void) { + if (createFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) return "Hardware"; + if (createFlags & D3DCREATE_MIXED_VERTEXPROCESSING) return "Mixed"; + if (createFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) return "Software"; + return "(none)"; +} + +const char* D3D9_StrFormat(D3DFORMAT format) { + switch (format) { + case D3DFMT_D32: return "D32"; + case D3DFMT_D24X8: return "D24X8"; + case D3DFMT_D24S8: return "D24S8"; + case D3DFMT_D24X4S4: return "D24X4S4"; + case D3DFMT_D16: return "D16"; + case D3DFMT_D15S1: return "D15S1"; + + case D3DFMT_X8R8G8B8: return "X8R8G8B8"; + case D3DFMT_R8G8B8: return "R8G8B8"; + case D3DFMT_R5G6B5: return "R5G6B5"; + case D3DFMT_X1R5G5B5: return "X1R5G5B5"; + } + return "(unknown)"; +} + +float d3d9_totalMem; +void Gfx_MakeApiInfo(void) { + D3DADAPTER_IDENTIFIER9 adapter = { 0 }; + IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &adapter); + d3d9_totalMem = IDirect3DDevice9_GetAvailableTextureMem(device) / (1024.0f * 1024.0f); + + String_AppendConst(&Gfx_ApiInfo[0],"-- Using Direct3D9 --"); + String_Format1(&Gfx_ApiInfo[1], "Adapter: %c", adapter.Description); + String_Format1(&Gfx_ApiInfo[2], "Processing mode: %c", D3D9_StrFlags()); + Gfx_UpdateApiInfo(); + String_Format2(&Gfx_ApiInfo[4], "Max texture size: (%i, %i)", &Gfx_MaxTexWidth, &Gfx_MaxTexHeight); + String_Format1(&Gfx_ApiInfo[5], "Depth buffer format: %c", D3D9_StrFormat(d3d9_depthFormat)); + String_Format1(&Gfx_ApiInfo[6], "Back buffer format: %c", D3D9_StrFormat(d3d9_viewFormat)); +} + +void Gfx_UpdateApiInfo(void) { + float mem = IDirect3DDevice9_GetAvailableTextureMem(device) / (1024.0f * 1024.0f); + Gfx_ApiInfo[3].length = 0; + String_Format2(&Gfx_ApiInfo[3], "Video memory: %f2 MB total, %f2 free", &d3d9_totalMem, &mem); +} + +void Gfx_OnWindowResize(void) { + GfxCommon_LoseContext(" (resizing window)"); + D3D9_RecreateDevice(); +} +#endif + + +/*########################################################################################################################* +*----------------------------------------------------------OpenGL---------------------------------------------------------* +*#########################################################################################################################*/ +#ifndef CC_BUILD_D3D9 +#ifdef CC_BUILD_WIN +#define WIN32_LEAN_AND_MEAN +#define NOSERVICE +#define NOMCX +#define NOIME +#include +#else +#define APIENETRY +#endif +#include + +/* Extensions from later than OpenGL 1.1 */ +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_BGRA_EXT 0x80E1 + +#ifdef CC_BUILD_GL11 +GfxResourceID gl_activeList; +#define gl_DYNAMICLISTID 1234567891 +void* gl_dynamicListData; +#else +typedef void (APIENTRY *FUNC_GLBINDBUFFER) (GLenum target, GLuint buffer); +typedef void (APIENTRY *FUNC_GLDELETEBUFFERS) (GLsizei n, const GLuint *buffers); +typedef void (APIENTRY *FUNC_GLGENBUFFERS) (GLsizei n, GLuint *buffers); +typedef void (APIENTRY *FUNC_GLBUFFERDATA) (GLenum target, const void* size, const void *data, GLenum usage); +typedef void (APIENTRY *FUNC_GLBUFFERSUBDATA) (GLenum target, const void* offset, const void* size, const void *data); +FUNC_GLBINDBUFFER glBindBuffer; +FUNC_GLDELETEBUFFERS glDeleteBuffers; +FUNC_GLGENBUFFERS glGenBuffers; +FUNC_GLBUFFERDATA glBufferData; +FUNC_GLBUFFERSUBDATA glBufferSubData; +#endif + +int gl_compare[8] = { GL_ALWAYS, GL_NOTEQUAL, GL_NEVER, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER }; +typedef void (*GL_SetupVBFunc)(void); +typedef void (*GL_SetupVBRangeFunc)(int startVertex); +GL_SetupVBFunc gl_setupVBFunc; +GL_SetupVBRangeFunc gl_setupVBRangeFunc; + +#ifndef CC_BUILD_GL11 +static void GL_CheckVboSupport(void) { + String extensions = String_FromReadonly(glGetString(GL_EXTENSIONS)); + String version = String_FromReadonly(glGetString(GL_VERSION)); + String vboExt = String_FromConst("GL_ARB_vertex_buffer_object"); + + int major = (int)(version.buffer[0] - '0'); /* x.y. (and so forth) */ + int minor = (int)(version.buffer[2] - '0'); + + /* Supported in core since 1.5 */ + if ((major > 1) || (major == 1 && minor >= 5)) { + glBindBuffer = (FUNC_GLBINDBUFFER)GLContext_GetAddress("glBindBuffer"); + glDeleteBuffers = (FUNC_GLDELETEBUFFERS)GLContext_GetAddress("glDeleteBuffers"); + glGenBuffers = (FUNC_GLGENBUFFERS)GLContext_GetAddress("glGenBuffers"); + glBufferData = (FUNC_GLBUFFERDATA)GLContext_GetAddress("glBufferData"); + glBufferSubData = (FUNC_GLBUFFERSUBDATA)GLContext_GetAddress("glBufferSubData"); + return; + } else if (String_CaselessContains(&extensions, &vboExt)) { + glBindBuffer = (FUNC_GLBINDBUFFER)GLContext_GetAddress("glBindBufferARB"); + glDeleteBuffers = (FUNC_GLDELETEBUFFERS)GLContext_GetAddress("glDeleteBuffersARB"); + glGenBuffers = (FUNC_GLGENBUFFERS)GLContext_GetAddress("glGenBuffersARB"); + glBufferData = (FUNC_GLBUFFERDATA)GLContext_GetAddress("glBufferDataARB"); + glBufferSubData = (FUNC_GLBUFFERSUBDATA)GLContext_GetAddress("glBufferSubDataARB"); + } else { + ErrorHandler_Fail("Only OpenGL 1.1 supported.\r\n\r\n" \ + "Compile the game with CC_BUILD_GL11, or ask on the classicube forums for it"); + } +} +#endif + +void Gfx_Init(void) { + Gfx_MinZNear = 0.1f; + struct GraphicsMode mode = GraphicsMode_MakeDefault(); + GLContext_Init(mode); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Gfx_MaxTexWidth); + Gfx_MaxTexHeight = Gfx_MaxTexWidth; + +#ifndef CC_BUILD_GL11 + Gfx_CustomMipmapsLevels = true; + GL_CheckVboSupport(); +#else + Gfx_CustomMipmapsLevels = false; +#endif + + GfxCommon_Init(); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); +} + +void Gfx_Free(void) { + GfxCommon_Free(); + GLContext_Free(); +} + +#define gl_Toggle(cap) if (enabled) { glEnable(cap); } else { glDisable(cap); } + + +/*########################################################################################################################* +*---------------------------------------------------------Textures--------------------------------------------------------* +*#########################################################################################################################*/ +static void GL_DoMipmaps(GfxResourceID texId, int x, int y, Bitmap* bmp, bool partial) { + uint8_t* prev = bmp->Scan0; + int lvls = GfxCommon_MipmapsLevels(bmp->Width, bmp->Height); + int lvl, width = bmp->Width, height = bmp->Height; + + for (lvl = 1; lvl <= lvls; lvl++) { + x /= 2; y /= 2; + if (width > 1) width /= 2; + if (height > 1) height /= 2; + + uint8_t* cur = Mem_Alloc(width * height, BITMAP_SIZEOF_PIXEL, "mipmaps"); + GfxCommon_GenMipmaps(width, height, cur, prev); + + if (partial) { + glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, cur); + } else { + glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, cur); + } + + if (prev != bmp->Scan0) Mem_Free(prev); + prev = cur; + } + if (prev != bmp->Scan0) Mem_Free(prev); +} + +GfxResourceID Gfx_CreateTexture(Bitmap* bmp, bool managedPool, bool mipmaps) { + uint32_t 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)) { + ErrorHandler_Fail("Textures must have power of two dimensions"); + } + + if (mipmaps) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); + if (Gfx_CustomMipmapsLevels) { + int lvls = GfxCommon_MipmapsLevels(bmp->Width, bmp->Height); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lvls); + } + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp->Width, bmp->Height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bmp->Scan0); + + if (mipmaps) GL_DoMipmaps(texId, 0, 0, bmp, false); + return texId; +} + +void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, Bitmap* part, bool mipmaps) { + glBindTexture(GL_TEXTURE_2D, texId); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->Width, part->Height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, part->Scan0); + if (mipmaps) GL_DoMipmaps(texId, x, y, part, true); +} + +void Gfx_BindTexture(GfxResourceID texId) { + glBindTexture(GL_TEXTURE_2D, texId); +} + +void Gfx_DeleteTexture(GfxResourceID* texId) { + if (!texId || *texId == GFX_NULL) return; + glDeleteTextures(1, texId); + *texId = GFX_NULL; +} + +void Gfx_SetTexturing(bool enabled) { gl_Toggle(GL_TEXTURE_2D); } +void Gfx_EnableMipmaps(void) { } +void Gfx_DisableMipmaps(void) { } + + +/*########################################################################################################################* +*-----------------------------------------------------State management----------------------------------------------------* +*#########################################################################################################################*/ +PackedCol gl_lastFogCol; +float gl_lastFogEnd = -1, gl_lastFogDensity = -1; +int gl_lastFogMode = -1; + +PackedCol gl_lastClearCol; + +void Gfx_SetFog(bool enabled) { + gfx_fogEnabled = enabled; + gl_Toggle(GL_FOG); +} + +void Gfx_SetFogCol(PackedCol col) { + if (PackedCol_Equals(col, gl_lastFogCol)) return; + float colRGBA[4] = { col.R / 255.0f, col.G / 255.0f, col.B / 255.0f, col.A / 255.0f }; + glFogfv(GL_FOG_COLOR, colRGBA); + gl_lastFogCol = col; +} + +void Gfx_SetFogDensity(float value) { + if (value == gl_lastFogDensity) return; + glFogf(GL_FOG_DENSITY, value); + gl_lastFogDensity = value; +} + +void Gfx_SetFogEnd(float value) { + if (value == gl_lastFogEnd) return; + glFogf(GL_FOG_END, value); + gl_lastFogEnd = value; +} + +void Gfx_SetFogMode(int mode) { + static GLint modes[3] = { GL_LINEAR, GL_EXP, GL_EXP2 }; + if (mode == gl_lastFogMode) return; + glFogi(GL_FOG_MODE, modes[mode]); + gl_lastFogMode = mode; +} + +void Gfx_SetFaceCulling(bool enabled) { gl_Toggle(GL_CULL_FACE); } +void Gfx_SetAlphaTest(bool enabled) { gl_Toggle(GL_ALPHA_TEST); } +void Gfx_SetAlphaTestFunc(int func, float value) { + glAlphaFunc(gl_compare[func], value); +} + +void Gfx_SetAlphaBlending(bool enabled) { gl_Toggle(GL_BLEND); } +void Gfx_SetAlphaBlendFunc(int srcFunc, int dstFunc) { + static GLenum funcs[6] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; + glBlendFunc(funcs[srcFunc], funcs[dstFunc]); +} +void Gfx_SetAlphaArgBlend(bool enabled) { } + +void Gfx_ClearCol(PackedCol col) { + if (PackedCol_Equals(col, gl_lastClearCol)) return; + glClearColor(col.R / 255.0f, col.G / 255.0f, col.B / 255.0f, col.A / 255.0f); + gl_lastClearCol = col; +} + +void Gfx_SetColourWriteMask(bool r, bool g, bool b, bool a) { + glColorMask(r, g, b, a); +} + +void Gfx_SetDepthWrite(bool enabled) { + glDepthMask(enabled); +} + +void Gfx_SetDepthTest(bool enabled) { gl_Toggle(GL_DEPTH_TEST); } +void Gfx_SetDepthTestFunc(int compareFunc) { + glDepthFunc(gl_compare[compareFunc]); +} + + +/*########################################################################################################################* +*---------------------------------------------------Vertex/Index buffers--------------------------------------------------* +*#########################################################################################################################*/ +#ifndef CC_BUILD_GL11 +static GfxResourceID GL_GenAndBind(GLenum target) { + GfxResourceID id; + glGenBuffers(1, &id); + glBindBuffer(target, id); + return id; +} + +GfxResourceID Gfx_CreateDynamicVb(int vertexFormat, int maxVertices) { + GfxResourceID id = GL_GenAndBind(GL_ARRAY_BUFFER); + uint32_t sizeInBytes = maxVertices * Gfx_strideSizes[vertexFormat]; + glBufferData(GL_ARRAY_BUFFER, (void*)sizeInBytes, NULL, GL_DYNAMIC_DRAW); + return id; +} + +GfxResourceID Gfx_CreateVb(void* vertices, int vertexFormat, int count) { + GfxResourceID id = GL_GenAndBind(GL_ARRAY_BUFFER); + uint32_t sizeInBytes = count * Gfx_strideSizes[vertexFormat]; + glBufferData(GL_ARRAY_BUFFER, (void*)sizeInBytes, vertices, GL_STATIC_DRAW); + return id; +} + +GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { + GfxResourceID id = GL_GenAndBind(GL_ELEMENT_ARRAY_BUFFER); + uint32_t sizeInBytes = indicesCount * 2; + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (void*)sizeInBytes, indices, GL_STATIC_DRAW); + return id; +} + +void Gfx_BindVb(GfxResourceID vb) { glBindBuffer(GL_ARRAY_BUFFER, vb); } +void Gfx_BindIb(GfxResourceID ib) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib); } + +void Gfx_DeleteVb(GfxResourceID* vb) { + if (!vb || *vb == GFX_NULL) return; + glDeleteBuffers(1, vb); + *vb = GFX_NULL; +} + +void Gfx_DeleteIb(GfxResourceID* ib) { + if (!ib || *ib == GFX_NULL) return; + glDeleteBuffers(1, ib); + *ib = GFX_NULL; +} +#else +GfxResourceID Gfx_CreateDynamicVb(int vertexFormat, int maxVertices) { return gl_DYNAMICLISTID; } +GfxResourceID Gfx_CreateVb(void* vertices, int vertexFormat, int count) { + /* We need to setup client state properly when building the list */ + int curFormat = gfx_batchFormat; + Gfx_SetBatchFormat(vertexFormat); + GfxResourceID list = glGenLists(1); + glNewList(list, GL_COMPILE); + count &= ~0x01; /* Need to get rid of the 1 extra element, see comment in chunk mesh builder for why */ + + uint16_t indices[GFX_MAX_INDICES]; + GfxCommon_MakeIndices(indices, ICOUNT(count)); + + int stride = vertexFormat == VERTEX_FORMAT_P3FT2FC4B ? sizeof(VertexP3fT2fC4b) : sizeof(VertexP3fC4b); + glVertexPointer(3, GL_FLOAT, stride, vertices); + glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)((uint8_t*)vertices + 12)); + if (vertexFormat == VERTEX_FORMAT_P3FT2FC4B) { + glTexCoordPointer(2, GL_FLOAT, stride, (void*)((uint8_t*)vertices + 16)); + } + + glDrawElements(GL_TRIANGLES, ICOUNT(count), GL_UNSIGNED_SHORT, indices); + glEndList(); + Gfx_SetBatchFormat(curFormat); + return list; +} + +GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { return GFX_NULL; } +void Gfx_BindVb(GfxResourceID vb) { gl_activeList = vb; } +void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_DeleteIb(GfxResourceID* ib) { } + +void Gfx_DeleteVb(GfxResourceID* vb) { + if (!vb || *vb == GFX_NULL) return; + if (*vb != gl_DYNAMICLISTID) glDeleteLists(*vb, 1); + *vb = GFX_NULL; +} +#endif + +void GL_SetupVbPos3fCol4b(void) { + glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fC4b), (void*)0); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fC4b), (void*)12); +} + +void GL_SetupVbPos3fTex2fCol4b(void) { + glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)0); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)12); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)16); +} + +void GL_SetupVbPos3fCol4b_Range(int startVertex) { + uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fC4b); + glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fC4b), (void*)(offset)); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fC4b), (void*)(offset + 12)); +} + +void GL_SetupVbPos3fTex2fCol4b_Range(int startVertex) { + uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b); + glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset)); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)(offset + 12)); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset + 16)); +} + +void Gfx_SetBatchFormat(int vertexFormat) { + if (vertexFormat == gfx_batchFormat) return; + + if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + gfx_batchFormat = vertexFormat; + gfx_batchStride = Gfx_strideSizes[vertexFormat]; + + if (vertexFormat == VERTEX_FORMAT_P3FT2FC4B) { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + gl_setupVBFunc = GL_SetupVbPos3fTex2fCol4b; + gl_setupVBRangeFunc = GL_SetupVbPos3fTex2fCol4b_Range; + } else { + gl_setupVBFunc = GL_SetupVbPos3fCol4b; + gl_setupVBRangeFunc = GL_SetupVbPos3fCol4b_Range; + } +} + +#ifndef CC_BUILD_GL11 +void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { + glBindBuffer(GL_ARRAY_BUFFER, vb); + uint32_t sizeInBytes = vCount * gfx_batchStride; + glBufferSubData(GL_ARRAY_BUFFER, NULL, (void*)sizeInBytes, vertices); +} + +void Gfx_DrawVb_Lines(int verticesCount) { + gl_setupVBFunc(); + glDrawArrays(GL_LINES, 0, verticesCount); +} + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { + gl_setupVBRangeFunc(startVertex); + glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL); +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + gl_setupVBFunc(); + glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL); +} + +void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) { + uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b); + glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset)); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)(offset + 12)); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset + 16)); + glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL); +} +#else +void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { + gl_activeList = gl_DYNAMICLISTID; + gl_dynamicListData = vertices; +} + +static void GL_V16(VertexP3fC4b v) { + glColor4ub(v.Col.R, v.Col.G, v.Col.B, v.Col.A); + glVertex3f(v.X, v.Y, v.Z); +} + +static void GL_V24(VertexP3fT2fC4b v) { + glColor4ub(v.Col.R, v.Col.G, v.Col.B, v.Col.A); + glTexCoord2f(v.U, v.V); + glVertex3f(v.X, v.Y, v.Z); +} + +static void GL_DrawDynamicTriangles(int verticesCount, int startVertex) { + glBegin(GL_TRIANGLES); + int i; + if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) { + VertexP3fT2fC4b* ptr = (VertexP3fT2fC4b*)gl_dynamicListData; + for (i = startVertex; i < startVertex + verticesCount; i += 4) { + GL_V24(ptr[i + 0]); GL_V24(ptr[i + 1]); GL_V24(ptr[i + 2]); + GL_V24(ptr[i + 2]); GL_V24(ptr[i + 3]); GL_V24(ptr[i + 0]); + } + } else { + VertexP3fC4b* ptr = (VertexP3fC4b*)gl_dynamicListData; + for (i = startVertex; i < startVertex + verticesCount; i += 4) { + GL_V16(ptr[i + 0]); GL_V16(ptr[i + 1]); GL_V16(ptr[i + 2]); + GL_V16(ptr[i + 2]); GL_V16(ptr[i + 3]); GL_V16(ptr[i + 0]); + } + } + glEnd(); +} + +void Gfx_DrawVb_Lines(int verticesCount) { + glBegin(GL_LINES); + int i; + if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) { + VertexP3fT2fC4b* ptr = (VertexP3fT2fC4b*)gl_dynamicListData; + for (i = 0; i < verticesCount; i += 2) { GL_V24(ptr[i + 0]); GL_V24(ptr[i + 1]); } + } else { + VertexP3fC4b* ptr = (VertexP3fC4b*)gl_dynamicListData; + for (i = 0; i < verticesCount; i += 2) { GL_V16(ptr[i + 0]); GL_V16(ptr[i + 1]); } + } + glEnd(); +} + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { + if (gl_activeList != gl_DYNAMICLISTID) { glCallList(gl_activeList); } + else { GL_DrawDynamicTriangles(verticesCount, startVertex); } +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + if (gl_activeList != gl_DYNAMICLISTID) { glCallList(gl_activeList); } + else { GL_DrawDynamicTriangles(verticesCount, 0); } +} + +GfxResourceID gl_lastPartialList; +void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) { + /* TODO: This renders the whole map, bad performance!! FIX FIX */ + if (gl_activeList == gl_lastPartialList) return; + glCallList(gl_activeList); + gl_lastPartialList = gl_activeList; +} +#endif + + +/*########################################################################################################################* +*---------------------------------------------------------Matrices--------------------------------------------------------* +*#########################################################################################################################*/ +int gl_lastMatrixType; + +void Gfx_SetMatrixMode(int matrixType) { + if (matrixType == gl_lastMatrixType) return; + gl_lastMatrixType = matrixType; + static GLenum matrixModes[3] = { GL_PROJECTION, GL_MODELVIEW, GL_TEXTURE }; + glMatrixMode(matrixModes[matrixType]); +} + +void Gfx_LoadMatrix(struct Matrix* matrix) { glLoadMatrixf((float*)matrix); } +void Gfx_LoadIdentityMatrix(void) { glLoadIdentity(); } + +void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) { + Matrix_OrthographicOffCenter(matrix, 0.0f, width, height, 0.0f, -10000.0f, 10000.0f); +} +void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) { + Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar); +} + + +/*########################################################################################################################* +*-----------------------------------------------------------Misc----------------------------------------------------------* +*#########################################################################################################################*/ +ReturnCode Gfx_TakeScreenshot(struct Stream* output, int width, int height) { + Bitmap bmp; Bitmap_Allocate(&bmp, width, height); + glReadPixels(0, 0, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bmp.Scan0); + uint8_t tmp[PNG_MAX_DIMS * BITMAP_SIZEOF_PIXEL]; + + /* flip vertically around y */ + int x, y; + uint32_t stride = (uint32_t)(bmp.Width) * BITMAP_SIZEOF_PIXEL; + for (y = 0; y < height / 2; y++) { + uint32_t* src = Bitmap_GetRow(&bmp, y); + uint32_t* dst = Bitmap_GetRow(&bmp, (height - 1) - y); + + Mem_Copy(tmp, src, stride); + Mem_Copy(src, dst, stride); + Mem_Copy(dst, tmp, stride); + /*for (x = 0; x < bmp.Width; x++) { + uint32_t temp = dst[x]; dst[x] = src[x]; src[x] = temp; + }*/ + } + + ReturnCode res = Bitmap_EncodePng(&bmp, output); + Mem_Free(bmp.Scan0); + return res; +} + +bool nv_mem; +void Gfx_MakeApiInfo(void) { + int depthBits = 0; + glGetIntegerv(GL_DEPTH_BITS, &depthBits); + + String_AppendConst(&Gfx_ApiInfo[0],"-- Using OpenGL --"); + String_Format1(&Gfx_ApiInfo[1], "Vendor: %c", glGetString(GL_VENDOR)); + String_Format1(&Gfx_ApiInfo[2], "Renderer: %c", glGetString(GL_RENDERER)); + String_Format1(&Gfx_ApiInfo[3], "GL version: %c", glGetString(GL_VERSION)); + /* Memory usage goes here */ + String_Format2(&Gfx_ApiInfo[5], "Max texture size: (%i, %i)", &Gfx_MaxTexWidth, &Gfx_MaxTexHeight); + String_Format1(&Gfx_ApiInfo[6], "Depth buffer bits: %i", &depthBits); + + String extensions = String_FromReadonly(glGetString(GL_EXTENSIONS)); + String memExt = String_FromConst("GL_NVX_gpu_memory_info"); + nv_mem = String_CaselessContains(&extensions, &memExt); +} + +void Gfx_UpdateApiInfo(void) { + if (!nv_mem) return; + int totalKb = 0, curKb = 0; + glGetIntegerv(0x9048, &totalKb); + glGetIntegerv(0x9049, &curKb); + + if (totalKb <= 0 || curKb <= 0) return; + Gfx_ApiInfo[4].length = 0; + float total = totalKb / 1024.0f, cur = curKb / 1024.0f; + String_Format2(&Gfx_ApiInfo[4], "Video memory: %f2 MB total, %f2 free", &total, &cur); +} + +bool Gfx_WarnIfNecessary(void) { +#ifdef CC_BUILD_GL11 + Chat_AddRaw("&cYou are using the very outdated OpenGL backend."); + Chat_AddRaw("&cAs such you may experience poor performance."); + Chat_AddRaw("&cIt is likely you need to install video card drivers."); +#endif + + String renderer = String_FromReadonly(glGetString(GL_RENDERER)); + String intel = String_FromConst("Intel"); + if (!String_ContainsString(&renderer, &intel)) return false; + + Chat_AddRaw("&cIntel graphics cards are known to have issues with the OpenGL build."); + Chat_AddRaw("&cVSync may not work, and you may see disappearing clouds and map edges."); + Chat_AddRaw("&cFor Windows, try downloading the Direct3D 9 build instead."); + return true; +} + +void Gfx_SetVSync(bool value) { + if (gfx_vsync == value) return; + gfx_vsync = value; + GLContext_SetVSync(value); +} + +void Gfx_BeginFrame(void) { } +void Gfx_Clear(void) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void Gfx_EndFrame(void) { + GLContext_SwapBuffers(); +#ifdef CC_BUILD_GL11 + gl_activeList = NULL; +#endif +} + +void Gfx_OnWindowResize(void) { + glViewport(0, 0, Game_Width, Game_Height); +} +#endif diff --git a/src/GraphicsAPI.h b/src/Graphics.h similarity index 96% rename from src/GraphicsAPI.h rename to src/Graphics.h index 46d25b412..099ff7a5a 100644 --- a/src/GraphicsAPI.h +++ b/src/Graphics.h @@ -38,7 +38,6 @@ struct Matrix Gfx_View, Gfx_Projection; #define GFX_MAX_INDICES (65536 / 4 * 6) #define GFX_MAX_VERTICES 65536 -#define GFX_STRIDE_SIZES { 16, 24 } /* Callback invoked when the current context is lost, and is repeatedly invoked until the context can be retrieved. */ ScheduledTaskCallback Gfx_LostContextFunction; diff --git a/src/GraphicsCommon.c b/src/GraphicsCommon.c index e794ecc52..1ced64ece 100644 --- a/src/GraphicsCommon.c +++ b/src/GraphicsCommon.c @@ -1,5 +1,5 @@ #include "GraphicsCommon.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Platform.h" #include "Block.h" #include "Event.h" diff --git a/src/Gui.c b/src/Gui.c index c9a918a01..065e711a6 100644 --- a/src/Gui.c +++ b/src/Gui.c @@ -2,7 +2,7 @@ #include "Window.h" #include "Game.h" #include "GraphicsCommon.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Event.h" #include "Drawer2D.h" #include "ExtMath.h" diff --git a/src/HeldBlockRenderer.c b/src/HeldBlockRenderer.c index bed805cca..95c58720b 100644 --- a/src/HeldBlockRenderer.c +++ b/src/HeldBlockRenderer.c @@ -2,7 +2,7 @@ #include "Block.h" #include "Game.h" #include "Inventory.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "GraphicsCommon.h" #include "Camera.h" #include "ModelCache.h" diff --git a/src/Input.c b/src/Input.c index 9b981b206..2e53f5a41 100644 --- a/src/Input.c +++ b/src/Input.c @@ -7,6 +7,10 @@ #include "Platform.h" #include "Chat.h" + +/*########################################################################################################################* +*--------------------------------------------------------Key/Mouse--------------------------------------------------------* +*#########################################################################################################################*/ #define Key_Function_Names \ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",\ "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20",\ @@ -60,41 +64,32 @@ const char* Key_Names[Key_Count] = { "XBUTTON1", "XBUTTON2", };*/ -bool Key_States[Key_Count]; -bool Key_IsPressed(Key key) { return Key_States[key]; } - void Key_SetPressed(Key key, bool pressed) { - if (Key_States[key] != pressed || Key_KeyRepeat) { - Key_States[key] = pressed; + if (Key_Pressed[key] == pressed && !Key_KeyRepeat) return; + Key_Pressed[key] = pressed; - if (pressed) { - Event_RaiseInt(&KeyEvents_Down, key); - } else { - Event_RaiseInt(&KeyEvents_Up, key); - } + if (pressed) { + Event_RaiseInt(&KeyEvents_Down, key); + } else { + Event_RaiseInt(&KeyEvents_Up, key); } } void Key_Clear(void) { int i; for (i = 0; i < Key_Count; i++) { - if (Key_States[i]) Key_SetPressed((Key)i, false); + if (Key_Pressed[i]) Key_SetPressed((Key)i, false); } } - -bool MouseButton_States[MouseButton_Count]; -bool Mouse_IsPressed(MouseButton btn) { return MouseButton_States[btn]; } - void Mouse_SetPressed(MouseButton btn, bool pressed) { - if (MouseButton_States[btn] != pressed) { - MouseButton_States[btn] = pressed; + if (Mouse_Pressed[btn] == pressed) return; + Mouse_Pressed[btn] = pressed; - if (pressed) { - Event_RaiseInt(&MouseEvents_Down, btn); - } else { - Event_RaiseInt(&MouseEvents_Up, btn); - } + if (pressed) { + Event_RaiseInt(&MouseEvents_Down, btn); + } else { + Event_RaiseInt(&MouseEvents_Up, btn); } } @@ -110,6 +105,10 @@ void Mouse_SetPosition(int x, int y) { Event_RaiseMouseMove(&MouseEvents_Moved, deltaX, deltaY); } + +/*########################################################################################################################* +*---------------------------------------------------------Keybinds--------------------------------------------------------* +*#########################################################################################################################*/ Key KeyBind_Keys[KeyBind_Count]; uint8_t KeyBind_Defaults[KeyBind_Count] = { Key_W, Key_S, Key_A, Key_D, @@ -136,7 +135,7 @@ const char* KeyBind_Names[KeyBind_Count] = { Key KeyBind_Get(KeyBind binding) { return KeyBind_Keys[binding]; } Key KeyBind_GetDefault(KeyBind binding) { return KeyBind_Defaults[binding]; } -bool KeyBind_IsPressed(KeyBind binding) { return Key_States[KeyBind_Keys[binding]]; } +bool KeyBind_IsPressed(KeyBind binding) { return Key_Pressed[KeyBind_Keys[binding]]; } void KeyBind_Load(void) { int i; @@ -181,6 +180,9 @@ void KeyBind_Init(void) { } +/*########################################################################################################################* +*---------------------------------------------------------Hotkeys---------------------------------------------------------* +*#########################################################################################################################*/ uint8_t Hotkeys_LWJGL[256] = { 0, Key_Escape, Key_1, Key_2, Key_3, Key_4, Key_5, Key_6, Key_7, Key_8, Key_9, Key_0, Key_Minus, Key_Plus, Key_BackSpace, Key_Tab, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_BracketLeft, Key_BracketRight, Key_Enter, Key_ControlLeft, Key_A, Key_S, diff --git a/src/Input.h b/src/Input.h index f86c50aa2..3c56e30fc 100644 --- a/src/Input.h +++ b/src/Input.h @@ -71,12 +71,12 @@ are generated for the same key when it is held down for a period of time. Should bool Key_KeyRepeat; extern const char* Key_Names[Key_Count]; -#define Key_IsWinPressed() (Key_IsPressed(Key_WinLeft) || Key_IsPressed(Key_WinRight)) -#define Key_IsAltPressed() (Key_IsPressed(Key_AltLeft) || Key_IsPressed(Key_AltRight)) -#define Key_IsControlPressed() (Key_IsPressed(Key_ControlLeft) || Key_IsPressed(Key_ControlRight)) -#define Key_IsShiftPressed() (Key_IsPressed(Key_ShiftLeft) || Key_IsPressed(Key_ShiftRight)) +#define Key_IsWinPressed() (Key_Pressed[Key_WinLeft] || Key_Pressed[Key_WinRight]) +#define Key_IsAltPressed() (Key_Pressed[Key_AltLeft] || Key_Pressed[Key_AltRight]) +#define Key_IsControlPressed() (Key_Pressed[Key_ControlLeft] || Key_Pressed[Key_ControlRight]) +#define Key_IsShiftPressed() (Key_Pressed[Key_ShiftLeft] || Key_Pressed[Key_ShiftRight]) -bool Key_IsPressed(Key key); +bool Key_Pressed[Key_Count]; void Key_SetPressed(Key key, bool pressed); void Key_Clear(void); @@ -89,7 +89,7 @@ typedef enum MouseButton_ { float Mouse_Wheel; int Mouse_X, Mouse_Y; -bool Mouse_IsPressed(MouseButton btn); +bool Mouse_Pressed[MouseButton_Count]; void Mouse_SetPressed(MouseButton btn, bool pressed); void Mouse_SetWheel(float wheel); void Mouse_SetPosition(int x, int y); diff --git a/src/InputHandler.c b/src/InputHandler.c index 05abbb1ee..44223328b 100644 --- a/src/InputHandler.c +++ b/src/InputHandler.c @@ -26,7 +26,7 @@ TimeMS input_lastClick; float input_fovIndex = -1.0f; bool InputHandler_IsMousePressed(MouseButton button) { - if (Mouse_IsPressed(button)) return true; + if (Mouse_Pressed[button]) return true; /* Key --> mouse mappings */ if (button == MouseButton_Left && KeyBind_IsPressed(KeyBind_MouseLeft)) return true; diff --git a/src/IsometricDrawer.c b/src/IsometricDrawer.c index 1ef2663de..fc567b845 100644 --- a/src/IsometricDrawer.c +++ b/src/IsometricDrawer.c @@ -1,7 +1,7 @@ #include "IsometricDrawer.h" #include "Drawer.h" #include "GraphicsCommon.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "PackedCol.h" #include "ExtMath.h" #include "Block.h" diff --git a/src/MapRenderer.c b/src/MapRenderer.c index 6c39880a5..022b1d6da 100644 --- a/src/MapRenderer.c +++ b/src/MapRenderer.c @@ -1,7 +1,7 @@ #include "MapRenderer.h" #include "Block.h" #include "Game.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "EnvRenderer.h" #include "World.h" #include "Vectors.h" diff --git a/src/Menus.c b/src/Menus.c index c69c1967d..972c7b4cc 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -6,7 +6,7 @@ #include "Platform.h" #include "Inventory.h" #include "Drawer2D.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Funcs.h" #include "TerrainAtlas.h" #include "ModelCache.h" diff --git a/src/Model.c b/src/Model.c index 47f0c7183..6d6f49057 100644 --- a/src/Model.c +++ b/src/Model.c @@ -4,7 +4,7 @@ #include "Game.h" #include "ModelCache.h" #include "GraphicsCommon.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Entity.h" #define UV_POS_MASK ((uint16_t)0x7FFF) diff --git a/src/ModelCache.c b/src/ModelCache.c index 98975780a..6c9c83e5c 100644 --- a/src/ModelCache.c +++ b/src/ModelCache.c @@ -1,5 +1,5 @@ #include "ModelCache.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Game.h" #include "Event.h" #include "ExtMath.h" diff --git a/src/OpenGLApi.c b/src/OpenGLApi.c deleted file mode 100644 index 4dadc4492..000000000 --- a/src/OpenGLApi.c +++ /dev/null @@ -1,616 +0,0 @@ -#include "GraphicsAPI.h" -#ifndef CC_BUILD_D3D9 -#include "ErrorHandler.h" -#include "Platform.h" -#include "Window.h" -#include "GraphicsCommon.h" -#include "Funcs.h" -#include "Chat.h" -#include "Game.h" -#include "ExtMath.h" -#include "Bitmap.h" - -#ifdef CC_BUILD_WIN -#define WIN32_LEAN_AND_MEAN -#define NOSERVICE -#define NOMCX -#define NOIME -#include -#else -#define APIENETRY -#endif -#include - -/* Extensions from later than OpenGL 1.1 */ -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_STATIC_DRAW 0x88E4 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_BGRA_EXT 0x80E1 - -#ifdef CC_BUILD_GL11 -GfxResourceID gl_activeList; -#define gl_DYNAMICLISTID 1234567891 -void* gl_dynamicListData; -#else -typedef void (APIENTRY *FUNC_GLBINDBUFFER) (GLenum target, GLuint buffer); -typedef void (APIENTRY *FUNC_GLDELETEBUFFERS) (GLsizei n, const GLuint *buffers); -typedef void (APIENTRY *FUNC_GLGENBUFFERS) (GLsizei n, GLuint *buffers); -typedef void (APIENTRY *FUNC_GLBUFFERDATA) (GLenum target, const void* size, const void *data, GLenum usage); -typedef void (APIENTRY *FUNC_GLBUFFERSUBDATA) (GLenum target, const void* offset, const void* size, const void *data); -FUNC_GLBINDBUFFER glBindBuffer; -FUNC_GLDELETEBUFFERS glDeleteBuffers; -FUNC_GLGENBUFFERS glGenBuffers; -FUNC_GLBUFFERDATA glBufferData; -FUNC_GLBUFFERSUBDATA glBufferSubData; -#endif - -int Gfx_strideSizes[2] = GFX_STRIDE_SIZES; -bool gl_vsync; - -int gl_blend[6] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; -int gl_compare[8] = { GL_ALWAYS, GL_NOTEQUAL, GL_NEVER, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER }; -int gl_fogModes[3] = { GL_LINEAR, GL_EXP, GL_EXP2 }; -int gl_matrixModes[3] = { GL_PROJECTION, GL_MODELVIEW, GL_TEXTURE }; - -typedef void (*GL_SetupVBFunc)(void); -typedef void (*GL_SetupVBRangeFunc)(int startVertex); -GL_SetupVBFunc gl_setupVBFunc; -GL_SetupVBRangeFunc gl_setupVBRangeFunc; -int gl_batchStride, gl_batchFormat = -1; - -#ifndef CC_BUILD_GL11 -static void GL_CheckVboSupport(void) { - String extensions = String_FromReadonly(glGetString(GL_EXTENSIONS)); - String version = String_FromReadonly(glGetString(GL_VERSION)); - String vboExt = String_FromConst("GL_ARB_vertex_buffer_object"); - - int major = (int)(version.buffer[0] - '0'); /* x.y. (and so forth) */ - int minor = (int)(version.buffer[2] - '0'); - - /* Supported in core since 1.5 */ - if ((major > 1) || (major == 1 && minor >= 5)) { - glBindBuffer = (FUNC_GLBINDBUFFER)GLContext_GetAddress("glBindBuffer"); - glDeleteBuffers = (FUNC_GLDELETEBUFFERS)GLContext_GetAddress("glDeleteBuffers"); - glGenBuffers = (FUNC_GLGENBUFFERS)GLContext_GetAddress("glGenBuffers"); - glBufferData = (FUNC_GLBUFFERDATA)GLContext_GetAddress("glBufferData"); - glBufferSubData = (FUNC_GLBUFFERSUBDATA)GLContext_GetAddress("glBufferSubData"); - return; - } else if (String_CaselessContains(&extensions, &vboExt)) { - glBindBuffer = (FUNC_GLBINDBUFFER)GLContext_GetAddress("glBindBufferARB"); - glDeleteBuffers = (FUNC_GLDELETEBUFFERS)GLContext_GetAddress("glDeleteBuffersARB"); - glGenBuffers = (FUNC_GLGENBUFFERS)GLContext_GetAddress("glGenBuffersARB"); - glBufferData = (FUNC_GLBUFFERDATA)GLContext_GetAddress("glBufferDataARB"); - glBufferSubData = (FUNC_GLBUFFERSUBDATA)GLContext_GetAddress("glBufferSubDataARB"); - } else { - ErrorHandler_Fail("Only OpenGL 1.1 supported.\r\n\r\n" \ - "Compile the game with CC_BUILD_GL11, or ask on the classicube forums for it"); - } -} -#endif - -void Gfx_Init(void) { - Gfx_MinZNear = 0.1f; - struct GraphicsMode mode = GraphicsMode_MakeDefault(); - GLContext_Init(mode); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Gfx_MaxTexWidth); - Gfx_MaxTexHeight = Gfx_MaxTexWidth; - -#ifndef CC_BUILD_GL11 - Gfx_CustomMipmapsLevels = true; - GL_CheckVboSupport(); -#else - Gfx_CustomMipmapsLevels = false; -#endif - - GfxCommon_Init(); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); -} - -void Gfx_Free(void) { - GfxCommon_Free(); - GLContext_Free(); -} - -#define gl_Toggle(cap) if (enabled) { glEnable(cap); } else { glDisable(cap); } - -static void GL_DoMipmaps(GfxResourceID texId, int x, int y, Bitmap* bmp, bool partial) { - uint8_t* prev = bmp->Scan0; - int lvls = GfxCommon_MipmapsLevels(bmp->Width, bmp->Height); - int lvl, width = bmp->Width, height = bmp->Height; - - for (lvl = 1; lvl <= lvls; lvl++) { - x /= 2; y /= 2; - if (width > 1) width /= 2; - if (height > 1) height /= 2; - - uint8_t* cur = Mem_Alloc(width * height, BITMAP_SIZEOF_PIXEL, "mipmaps"); - GfxCommon_GenMipmaps(width, height, cur, prev); - - if (partial) { - glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, cur); - } else { - glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, cur); - } - - if (prev != bmp->Scan0) Mem_Free(prev); - prev = cur; - } - if (prev != bmp->Scan0) Mem_Free(prev); -} - -GfxResourceID Gfx_CreateTexture(Bitmap* bmp, bool managedPool, bool mipmaps) { - uint32_t 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)) { - ErrorHandler_Fail("Textures must have power of two dimensions"); - } - - if (mipmaps) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); - if (Gfx_CustomMipmapsLevels) { - int lvls = GfxCommon_MipmapsLevels(bmp->Width, bmp->Height); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lvls); - } - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp->Width, bmp->Height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bmp->Scan0); - - if (mipmaps) GL_DoMipmaps(texId, 0, 0, bmp, false); - return texId; -} - -void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, Bitmap* part, bool mipmaps) { - glBindTexture(GL_TEXTURE_2D, texId); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->Width, part->Height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, part->Scan0); - if (mipmaps) GL_DoMipmaps(texId, x, y, part, true); -} - -void Gfx_BindTexture(GfxResourceID texId) { - glBindTexture(GL_TEXTURE_2D, texId); -} - -void Gfx_DeleteTexture(GfxResourceID* texId) { - if (!texId || *texId == GFX_NULL) return; - glDeleteTextures(1, texId); - *texId = GFX_NULL; -} - -void Gfx_SetTexturing(bool enabled) { gl_Toggle(GL_TEXTURE_2D); } -void Gfx_EnableMipmaps(void) { } -void Gfx_DisableMipmaps(void) { } - - -bool gl_fogEnable; -bool Gfx_GetFog(void) { return gl_fogEnable; } -void Gfx_SetFog(bool enabled) { - gl_fogEnable = enabled; - gl_Toggle(GL_FOG); -} - -PackedCol gl_lastFogCol; -void Gfx_SetFogCol(PackedCol col) { - if (PackedCol_Equals(col, gl_lastFogCol)) return; - float colRGBA[4] = { col.R / 255.0f, col.G / 255.0f, col.B / 255.0f, col.A / 255.0f }; - glFogfv(GL_FOG_COLOR, colRGBA); - gl_lastFogCol = col; -} - -float gl_lastFogEnd = -1, gl_lastFogDensity = -1; -void Gfx_SetFogDensity(float value) { - if (value == gl_lastFogDensity) return; - glFogf(GL_FOG_DENSITY, value); - gl_lastFogDensity = value; -} - -void Gfx_SetFogEnd(float value) { - if (value == gl_lastFogEnd) return; - glFogf(GL_FOG_END, value); - gl_lastFogEnd = value; -} - -int gl_lastFogMode = -1; -void Gfx_SetFogMode(int mode) { - if (mode == gl_lastFogMode) return; - glFogi(GL_FOG_MODE, gl_fogModes[mode]); - gl_lastFogMode = mode; -} - - -void Gfx_SetFaceCulling(bool enabled) { gl_Toggle(GL_CULL_FACE); } -void Gfx_SetAlphaTest(bool enabled) { gl_Toggle(GL_ALPHA_TEST); } -void Gfx_SetAlphaTestFunc(int func, float value) { - glAlphaFunc(gl_compare[func], value); -} - -void Gfx_SetAlphaBlending(bool enabled) { gl_Toggle(GL_BLEND); } -void Gfx_SetAlphaBlendFunc(int srcFunc, int dstFunc) { - glBlendFunc(gl_blend[srcFunc], gl_blend[dstFunc]); -} -void Gfx_SetAlphaArgBlend(bool enabled) { } - - -void Gfx_Clear(void) { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -} - -PackedCol gl_lastClearCol; -void Gfx_ClearCol(PackedCol col) { - if (PackedCol_Equals(col, gl_lastClearCol)) return; - glClearColor(col.R / 255.0f, col.G / 255.0f, col.B / 255.0f, col.A / 255.0f); - gl_lastClearCol = col; -} - -void Gfx_SetColourWriteMask(bool r, bool g, bool b, bool a) { - glColorMask(r, g, b, a); -} - -void Gfx_SetDepthWrite(bool enabled) { - glDepthMask(enabled); -} - -void Gfx_SetDepthTest(bool enabled) { gl_Toggle(GL_DEPTH_TEST); } -void Gfx_SetDepthTestFunc(int compareFunc) { - glDepthFunc(gl_compare[compareFunc]); -} - - -#ifndef CC_BUILD_GL11 -GfxResourceID GL_GenAndBind(GLenum target) { - GfxResourceID id; - glGenBuffers(1, &id); - glBindBuffer(target, id); - return id; -} -#endif - -GfxResourceID Gfx_CreateDynamicVb(int vertexFormat, int maxVertices) { -#ifndef CC_BUILD_GL11 - GfxResourceID id = GL_GenAndBind(GL_ARRAY_BUFFER); - uint32_t sizeInBytes = maxVertices * Gfx_strideSizes[vertexFormat]; - glBufferData(GL_ARRAY_BUFFER, (void*)sizeInBytes, NULL, GL_DYNAMIC_DRAW); - return id; -#else - return gl_DYNAMICLISTID; -#endif -} - -#define gl_MAXINDICES ICOUNT(65536) -GfxResourceID Gfx_CreateVb(void* vertices, int vertexFormat, int count) { -#ifndef CC_BUILD_GL11 - GfxResourceID id = GL_GenAndBind(GL_ARRAY_BUFFER); - uint32_t sizeInBytes = count * Gfx_strideSizes[vertexFormat]; - glBufferData(GL_ARRAY_BUFFER, (void*)sizeInBytes, vertices, GL_STATIC_DRAW); - return id; -#else - /* We need to setup client state properly when building the list */ - int curFormat = gl_batchFormat; - Gfx_SetBatchFormat(vertexFormat); - GfxResourceID list = glGenLists(1); - glNewList(list, GL_COMPILE); - count &= ~0x01; /* Need to get rid of the 1 extra element, see comment in chunk mesh builder for why */ - - uint16_t indices[GFX_MAX_INDICES]; - GfxCommon_MakeIndices(indices, ICOUNT(count)); - - int stride = vertexFormat == VERTEX_FORMAT_P3FT2FC4B ? sizeof(VertexP3fT2fC4b) : sizeof(VertexP3fC4b); - glVertexPointer(3, GL_FLOAT, stride, vertices); - glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)((uint8_t*)vertices + 12)); - if (vertexFormat == VERTEX_FORMAT_P3FT2FC4B) { - glTexCoordPointer(2, GL_FLOAT, stride, (void*)((uint8_t*)vertices + 16)); - } - - glDrawElements(GL_TRIANGLES, ICOUNT(count), GL_UNSIGNED_SHORT, indices); - glEndList(); - Gfx_SetBatchFormat(curFormat); - return list; -#endif -} - -GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { -#ifndef CC_BUILD_GL11 - GfxResourceID id = GL_GenAndBind(GL_ELEMENT_ARRAY_BUFFER); - uint32_t sizeInBytes = indicesCount * 2; - glBufferData(GL_ELEMENT_ARRAY_BUFFER, (void*)sizeInBytes, indices, GL_STATIC_DRAW); - return id; -#else - return NULL; -#endif -} - -void Gfx_BindVb(GfxResourceID vb) { -#ifndef CC_BUILD_GL11 - glBindBuffer(GL_ARRAY_BUFFER, vb); -#else - gl_activeList = vb; -#endif -} - -void Gfx_BindIb(GfxResourceID ib) { -#ifndef CC_BUILD_GL11 - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib); -#else - return; -#endif -} - -void Gfx_DeleteVb(GfxResourceID* vb) { - if (!vb || *vb == GFX_NULL) return; -#ifndef CC_BUILD_GL11 - glDeleteBuffers(1, vb); -#else - if (*vb != gl_DYNAMICLISTID) glDeleteLists(*vb, 1); -#endif - *vb = GFX_NULL; -} - -void Gfx_DeleteIb(GfxResourceID* ib) { -#ifndef CC_BUILD_GL11 - if (!ib || *ib == GFX_NULL) return; - glDeleteBuffers(1, ib); - *ib = GFX_NULL; -#else - return; -#endif -} - - -void GL_SetupVbPos3fCol4b(void) { - glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fC4b), (void*)0); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fC4b), (void*)12); -} - -void GL_SetupVbPos3fTex2fCol4b(void) { - glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)0); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)12); - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)16); -} - -void GL_SetupVbPos3fCol4b_Range(int startVertex) { - uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fC4b); - glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fC4b), (void*)(offset)); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fC4b), (void*)(offset + 12)); -} - -void GL_SetupVbPos3fTex2fCol4b_Range(int startVertex) { - uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b); - glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset)); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)(offset + 12)); - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset + 16)); -} - -void Gfx_SetBatchFormat(int vertexFormat) { - if (vertexFormat == gl_batchFormat) return; - - if (gl_batchFormat == VERTEX_FORMAT_P3FT2FC4B) { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - gl_batchFormat = vertexFormat; - gl_batchStride = Gfx_strideSizes[vertexFormat]; - - if (vertexFormat == VERTEX_FORMAT_P3FT2FC4B) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - gl_setupVBFunc = GL_SetupVbPos3fTex2fCol4b; - gl_setupVBRangeFunc = GL_SetupVbPos3fTex2fCol4b_Range; - } else { - gl_setupVBFunc = GL_SetupVbPos3fCol4b; - gl_setupVBRangeFunc = GL_SetupVbPos3fCol4b_Range; - } -} - -void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { -#ifndef CC_BUILD_GL11 - glBindBuffer(GL_ARRAY_BUFFER, vb); - uint32_t sizeInBytes = vCount * gl_batchStride; - glBufferSubData(GL_ARRAY_BUFFER, NULL, (void*)sizeInBytes, vertices); -#else - gl_activeList = gl_DYNAMICLISTID; - gl_dynamicListData = vertices; -#endif -} - -#ifdef CC_BUILD_GL11 -static void GL_V16(VertexP3fC4b v) { - glColor4ub(v.Col.R, v.Col.G, v.Col.B, v.Col.A); - glVertex3f(v.X, v.Y, v.Z); -} - -static void GL_V24(VertexP3fT2fC4b v) { - glColor4ub(v.Col.R, v.Col.G, v.Col.B, v.Col.A); - glTexCoord2f(v.U, v.V); - glVertex3f(v.X, v.Y, v.Z); -} - -static void GL_DrawDynamicTriangles(int verticesCount, int startVertex) { - glBegin(GL_TRIANGLES); - int i; - if (gl_batchFormat == VERTEX_FORMAT_P3FT2FC4B) { - VertexP3fT2fC4b* ptr = (VertexP3fT2fC4b*)gl_dynamicListData; - for (i = startVertex; i < startVertex + verticesCount; i += 4) { - GL_V24(ptr[i + 0]); GL_V24(ptr[i + 1]); GL_V24(ptr[i + 2]); - GL_V24(ptr[i + 2]); GL_V24(ptr[i + 3]); GL_V24(ptr[i + 0]); - } - } else { - VertexP3fC4b* ptr = (VertexP3fC4b*)gl_dynamicListData; - for (i = startVertex; i < startVertex + verticesCount; i += 4) { - GL_V16(ptr[i + 0]); GL_V16(ptr[i + 1]); GL_V16(ptr[i + 2]); - GL_V16(ptr[i + 2]); GL_V16(ptr[i + 3]); GL_V16(ptr[i + 0]); - } - } - glEnd(); -} -#endif - -void Gfx_DrawVb_Lines(int verticesCount) { -#ifndef CC_BUILD_GL11 - gl_setupVBFunc(); - glDrawArrays(GL_LINES, 0, verticesCount); -#else - glBegin(GL_LINES); - int i; - if (gl_batchFormat == VERTEX_FORMAT_P3FT2FC4B) { - VertexP3fT2fC4b* ptr = (VertexP3fT2fC4b*)gl_dynamicListData; - for (i = 0; i < verticesCount; i += 2) { GL_V24(ptr[i + 0]); GL_V24(ptr[i + 1]); } - } else { - VertexP3fC4b* ptr = (VertexP3fC4b*)gl_dynamicListData; - for (i = 0; i < verticesCount; i += 2) { GL_V16(ptr[i + 0]); GL_V16(ptr[i + 1]); } - } - glEnd(); -#endif -} - -void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { -#ifndef CC_BUILD_GL11 - gl_setupVBRangeFunc(startVertex); - glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL); -#else - if (gl_activeList != gl_DYNAMICLISTID) { glCallList(gl_activeList); } - else { GL_DrawDynamicTriangles(verticesCount, startVertex); } -#endif -} - -void Gfx_DrawVb_IndexedTris(int verticesCount) { -#ifndef CC_BUILD_GL11 - gl_setupVBFunc(); - glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL); -#else - if (gl_activeList != gl_DYNAMICLISTID) { glCallList(gl_activeList); } - else { GL_DrawDynamicTriangles(verticesCount, 0); } -#endif -} - -GfxResourceID gl_lastPartialList; -void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) { - -#ifndef CC_BUILD_GL11 - uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b); - glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset)); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)(offset + 12)); - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset + 16)); - glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL); -#else - /* TODO: This renders the whole map, bad performance!! FIX FIX */ - if (gl_activeList != gl_lastPartialList) { - glCallList(gl_activeList); - gl_lastPartialList = gl_activeList; - } -#endif -} - - -int gl_lastMatrixType; -void Gfx_SetMatrixMode(int matrixType) { - if (matrixType == gl_lastMatrixType) return; - glMatrixMode(gl_matrixModes[matrixType]); - gl_lastMatrixType = matrixType; -} - -void Gfx_LoadMatrix(struct Matrix* matrix) { glLoadMatrixf((float*)matrix); } -void Gfx_LoadIdentityMatrix(void) { glLoadIdentity(); } - -void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) { - Matrix_OrthographicOffCenter(matrix, 0.0f, width, height, 0.0f, -10000.0f, 10000.0f); -} -void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) { - Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar); -} - - -ReturnCode Gfx_TakeScreenshot(struct Stream* output, int width, int height) { - Bitmap bmp; Bitmap_Allocate(&bmp, width, height); - glReadPixels(0, 0, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bmp.Scan0); - uint8_t tmp[PNG_MAX_DIMS * BITMAP_SIZEOF_PIXEL]; - - /* flip vertically around y */ - int x, y; - uint32_t stride = (uint32_t)(bmp.Width) * BITMAP_SIZEOF_PIXEL; - for (y = 0; y < height / 2; y++) { - uint32_t* src = Bitmap_GetRow(&bmp, y); - uint32_t* dst = Bitmap_GetRow(&bmp, (height - 1) - y); - - Mem_Copy(tmp, src, stride); - Mem_Copy(src, dst, stride); - Mem_Copy(dst, tmp, stride); - /*for (x = 0; x < bmp.Width; x++) { - uint32_t temp = dst[x]; dst[x] = src[x]; src[x] = temp; - }*/ - } - - ReturnCode res = Bitmap_EncodePng(&bmp, output); - Mem_Free(bmp.Scan0); - return res; -} - -bool nv_mem; -void Gfx_MakeApiInfo(void) { - int depthBits = 0; - glGetIntegerv(GL_DEPTH_BITS, &depthBits); - - String_AppendConst(&Gfx_ApiInfo[0],"-- Using OpenGL --"); - String_Format1(&Gfx_ApiInfo[1], "Vendor: %c", glGetString(GL_VENDOR)); - String_Format1(&Gfx_ApiInfo[2], "Renderer: %c", glGetString(GL_RENDERER)); - String_Format1(&Gfx_ApiInfo[3], "GL version: %c", glGetString(GL_VERSION)); - /* Memory usage goes here */ - String_Format2(&Gfx_ApiInfo[5], "Max texture size: (%i, %i)", &Gfx_MaxTexWidth, &Gfx_MaxTexHeight); - String_Format1(&Gfx_ApiInfo[6], "Depth buffer bits: %i", &depthBits); - - String extensions = String_FromReadonly(glGetString(GL_EXTENSIONS)); - String memExt = String_FromConst("GL_NVX_gpu_memory_info"); - nv_mem = String_CaselessContains(&extensions, &memExt); -} - -void Gfx_UpdateApiInfo(void) { - if (!nv_mem) return; - int totalKb = 0, curKb = 0; - glGetIntegerv(0x9048, &totalKb); - glGetIntegerv(0x9049, &curKb); - - if (totalKb <= 0 || curKb <= 0) return; - Gfx_ApiInfo[4].length = 0; - float total = totalKb / 1024.0f, cur = curKb / 1024.0f; - String_Format2(&Gfx_ApiInfo[4], "Video memory: %f2 MB total, %f2 free", &total, &cur); -} - -bool Gfx_WarnIfNecessary(void) { -#ifdef CC_BUILD_GL11 - Chat_AddRaw("&cYou are using the very outdated OpenGL backend."); - Chat_AddRaw("&cAs such you may experience poor performance."); - Chat_AddRaw("&cIt is likely you need to install video card drivers."); -#endif - - String renderer = String_FromReadonly(glGetString(GL_RENDERER)); - String intel = String_FromConst("Intel"); - if (!String_ContainsString(&renderer, &intel)) return false; - - Chat_AddRaw("&cIntel graphics cards are known to have issues with the OpenGL build."); - Chat_AddRaw("&cVSync may not work, and you may see disappearing clouds and map edges."); - Chat_AddRaw("&cFor Windows, try downloading the Direct3D 9 build instead."); - return true; -} - - -void Gfx_SetVSync(bool value) { - if (gl_vsync == value) return; - gl_vsync = value; - GLContext_SetVSync(value); -} - -void Gfx_BeginFrame(void) { } -void Gfx_EndFrame(void) { - GLContext_SwapBuffers(); -#ifdef CC_BUILD_GL11 - gl_activeList = NULL; -#endif -} - -void Gfx_OnWindowResize(void) { - glViewport(0, 0, Game_Width, Game_Height); -} -#endif diff --git a/src/Particle.c b/src/Particle.c index c1d80970c..bfbde6ba7 100644 --- a/src/Particle.c +++ b/src/Particle.c @@ -5,7 +5,7 @@ #include "Lighting.h" #include "Entity.h" #include "TerrainAtlas.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "GraphicsCommon.h" #include "Funcs.h" #include "Game.h" diff --git a/src/PickedPosRenderer.c b/src/PickedPosRenderer.c index e8e60b910..757accf88 100644 --- a/src/PickedPosRenderer.c +++ b/src/PickedPosRenderer.c @@ -1,7 +1,7 @@ #include "PickedPosRenderer.h" #include "PackedCol.h" #include "VertexStructs.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "GraphicsCommon.h" #include "Game.h" #include "Event.h" diff --git a/src/Screens.c b/src/Screens.c index e12f70d09..61122a430 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -6,7 +6,7 @@ #include "Platform.h" #include "Inventory.h" #include "Drawer2D.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Funcs.h" #include "TerrainAtlas.h" #include "ModelCache.h" diff --git a/src/SelectionBox.c b/src/SelectionBox.c index 0bafb5099..a44486401 100644 --- a/src/SelectionBox.c +++ b/src/SelectionBox.c @@ -1,6 +1,6 @@ #include "SelectionBox.h" #include "ExtMath.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "GraphicsCommon.h" #include "Event.h" #include "Funcs.h" diff --git a/src/String.c b/src/String.c index 4c2ea7c30..5b13bedb1 100644 --- a/src/String.c +++ b/src/String.c @@ -135,7 +135,7 @@ bool String_Append(String* str, char c) { } bool String_AppendBool(String* str, bool value) { - char* text = value ? "True" : "False"; + const char* text = value ? "True" : "False"; return String_AppendConst(str, text); } diff --git a/src/TerrainAtlas.c b/src/TerrainAtlas.c index 0e24ac61e..6ec8d51da 100644 --- a/src/TerrainAtlas.c +++ b/src/TerrainAtlas.c @@ -3,7 +3,7 @@ #include "Block.h" #include "ExtMath.h" #include "Funcs.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Platform.h" void Atlas2D_UpdateState(Bitmap* bmp) { diff --git a/src/TexturePack.c b/src/TexturePack.c index 32c15a8b9..2ef288a34 100644 --- a/src/TexturePack.c +++ b/src/TexturePack.c @@ -5,7 +5,7 @@ #include "Stream.h" #include "Bitmap.h" #include "World.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Event.h" #include "Game.h" #include "AsyncDownloader.h" diff --git a/src/Widgets.c b/src/Widgets.c index 8a2241a8f..8582e6f6f 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -1,5 +1,5 @@ #include "Widgets.h" -#include "GraphicsAPI.h" +#include "Graphics.h" #include "Drawer2D.h" #include "GraphicsCommon.h" #include "ExtMath.h"