diff --git a/src/Graphics.h b/src/Graphics.h index d5a4c6a35..5b43ccde6 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -56,13 +56,14 @@ extern GfxResourceID Gfx_quadVb, Gfx_texVb; #define GFX_MAX_VERTICES 65536 #define TEXTURE_FLAG_MANAGED 0x01 /* Texture should persist across gfx context loss */ +#define TEXTURE_FLAG_DYNAMIC 0x02 /* Texture should allow updating via Gfx_UpdateTexture */ void Gfx_RecreateDynamicVb(GfxResourceID* vb, VertexFormat fmt, int maxVertices); void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps); void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count); /* Creates a new texture. (and also generates mipmaps if mipmaps) */ -/* Supported flags: TEXTURE_FLAG_MANAGED */ +/* Supported flags: TEXTURE_FLAG_MANAGED, TEXTURE_FLAG_DYNAMIC */ /* NOTE: Only set mipmaps to true if Gfx_Mipmaps is also true, because whether textures use mipmapping may be either a per-texture or global state depending on the backend. */ CC_API GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps); diff --git a/src/Graphics_D3D9.c b/src/Graphics_D3D9.c index c0953cddb..0fc9b3377 100644 --- a/src/Graphics_D3D9.c +++ b/src/Graphics_D3D9.c @@ -49,19 +49,35 @@ static void D3D9_FreeResource(GfxResourceID* resource) { Platform_Log2("D3D9 resource has %i outstanding references! ID 0x%x", &refCount, &addr); } -typedef IDirect3D9* (WINAPI *FP_Direct3DCreate9)(UINT SDKVersion); -static void CreateD3D9(void) { +static IDirect3D9* (WINAPI *_Direct3DCreate9)(UINT SDKVersion); +static HRESULT (WINAPI *_Direct3DCreate9Ex)(UINT SDKVersion, IDirect3D9** __d3d9); + +static void LoadD3D9Library(void) { + static const struct DynamicLibSym funcs[] = { + DynamicLib_Sym(Direct3DCreate9), + DynamicLib_Sym(Direct3DCreate9Ex) + }; static const cc_string path = String_FromConst("d3d9.dll"); - FP_Direct3DCreate9 _direct3DCreate9; void* lib = DynamicLib_Load2(&path); if (!lib) { Logger_DynamicLibWarn("loading", &path); Logger_Abort("Failed to load d3d9.dll. You may need to install Direct3D9."); } + DynamicLib_GetAll(lib, funcs, Array_Elems(funcs)); +} - _direct3DCreate9 = DynamicLib_Get2(lib, "Direct3DCreate9"); - d3d = _direct3DCreate9(D3D_SDK_VERSION); +static void CreateD3D9Instance(void) { + cc_result res; + if (false) { + res = _Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d); + if (res) Logger_Abort2(res, "Direct3D9Create9Ex failed"); + /* Extended Direct3D9 does not support managed textures */ + } else { + d3d = _Direct3DCreate9(D3D_SDK_VERSION); + /* Normal Direct3D9 supports POOL_MANAGED textures */ + Gfx.ManagedTextures = true; + } if (!d3d) Logger_Abort("Direct3DCreate9 returned NULL"); } @@ -159,13 +175,13 @@ static void TryCreateDevice(void) { } void Gfx_Create(void) { - CreateD3D9(); + LoadD3D9Library(); + CreateD3D9Instance(); FindCompatibleViewFormat(); FindCompatibleDepthFormat(); depthBits = D3D9_DepthBufferBits(); customMipmapsLevels = true; - Gfx.ManagedTextures = true; Gfx.Created = true; TryCreateDevice(); } @@ -299,7 +315,9 @@ static void D3D9_DoMipmaps(IDirect3DTexture9* texture, int x, int y, struct Bitm GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { IDirect3DTexture9* tex; IDirect3DTexture9* sys; + DWORD usage = 0; cc_result res; + int mipmapsLevels = CalcMipmapsLevels(bmp->width, bmp->height); int levels = 1 + (mipmaps ? mipmapsLevels : 0); @@ -307,8 +325,8 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm Logger_Abort("Textures must have power of two dimensions"); } if (Gfx.LostContext) return 0; - - if (flags & TEXTURE_FLAG_MANAGED) { + + if ((flags & TEXTURE_FLAG_MANAGED) && Gfx.ManagedTextures) { for (;;) { res = IDirect3DDevice9_CreateTexture(device, bmp->width, bmp->height, levels, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex, NULL); @@ -318,6 +336,9 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm D3D9_SetTextureData(tex, bmp, 0); if (mipmaps) D3D9_DoMipmaps(tex, 0, 0, bmp, bmp->width, false); } else { + /* Direct3D9ex doesn't support dynamic textures */ + if ((flags & TEXTURE_FLAG_DYNAMIC) && !Gfx.ManagedTextures) usage = D3DUSAGE_DYNAMIC; + for (;;) { res = IDirect3DDevice9_CreateTexture(device, bmp->width, bmp->height, levels, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &sys, NULL); @@ -329,7 +350,7 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm for (;;) { res = IDirect3DDevice9_CreateTexture(device, bmp->width, bmp->height, levels, - 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); + usage, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); if (D3D9_CheckResult(res, "D3D9_CreateGPUTexture failed")) break; } @@ -756,7 +777,8 @@ void Gfx_EndFrame(void) { IDirect3DDevice9_EndScene(device); cc_result res = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - if (res) { + /* Direct3D9Ex returns S_PRESENT_OCCLUDED when e.g. window is minimised */ + if (res && res != S_PRESENT_OCCLUDED) { if (res != D3DERR_DEVICELOST) Logger_Abort2(res, "D3D9_EndFrame"); /* TODO: Make sure this actually works on all graphics cards. */ Gfx_LoseContext(" (Direct3D9 device lost)"); diff --git a/src/TexturePack.c b/src/TexturePack.c index b07e0b6f7..f1863e67f 100644 --- a/src/TexturePack.c +++ b/src/TexturePack.c @@ -55,7 +55,7 @@ static void Atlas_Convert2DTo1D(void) { Bitmap_UNSAFE_CopyBlock(atlasX, atlasY, 0, y * tileSize, &Atlas2D.Bmp, &atlas1D, tileSize); } - Gfx_RecreateTexture(&Atlas1D.TexIds[i], &atlas1D, TEXTURE_FLAG_MANAGED, Gfx.Mipmaps); + Gfx_RecreateTexture(&Atlas1D.TexIds[i], &atlas1D, TEXTURE_FLAG_MANAGED | TEXTURE_FLAG_DYNAMIC, Gfx.Mipmaps); } Mem_Free(atlas1D.scan0); }