Use D3D9Ex when available
authorSam Lantinga <slouken@libsdl.org>
Sat, 31 May 2014 11:37:12 -0700
changeset 8792 333216331863
parent 8791 44dc9af6b7c2
child 8793 357193514f2f
Use D3D9Ex when available This hopefully works around crashes in Intel D3D9 support in Windows 8.1.
src/render/direct3d/SDL_render_d3d.c
src/video/windows/SDL_windowsvideo.c
--- a/src/render/direct3d/SDL_render_d3d.c	Sat May 31 11:33:25 2014 -0700
+++ b/src/render/direct3d/SDL_render_d3d.c	Sat May 31 11:37:12 2014 -0700
@@ -124,6 +124,7 @@
 static void D3D_WindowEvent(SDL_Renderer * renderer,
                             const SDL_WindowEvent *event);
 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                              const SDL_Rect * rect, const void *pixels,
                              int pitch);
@@ -190,12 +191,18 @@
 typedef struct
 {
     IDirect3DTexture9 *texture;
+    IDirect3DTexture9 *staging;
+} D3D_TextureRep;
+
+typedef struct
+{
+    D3D_TextureRep texture;
     D3DTEXTUREFILTERTYPE scaleMode;
 
     /* YV12 texture support */
     SDL_bool yuv;
-    IDirect3DTexture9 *utexture;
-    IDirect3DTexture9 *vtexture;
+    D3D_TextureRep utexture;
+    D3D_TextureRep vtexture;
     Uint8 *pixels;
     int pitch;
     SDL_Rect locked_rect;
@@ -408,6 +415,8 @@
     for (texture = renderer->textures; texture; texture = texture->next) {
         if (texture->access == SDL_TEXTUREACCESS_TARGET) {
             D3D_DestroyTexture(renderer, texture);
+        } else {
+            D3D_RecreateTexture(renderer, texture);
         }
     }
 
@@ -805,74 +814,58 @@
 }
 
 static int
-D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, int w, int h)
 {
-    D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
-    D3D_TextureData *data;
-    D3DPOOL pool;
-    DWORD usage;
     HRESULT result;
 
-    data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
-    if (!data) {
-        return SDL_OutOfMemory();
-    }
-    data->scaleMode = GetScaleQuality();
-
-    texture->driverdata = data;
-
-#ifdef USE_DYNAMIC_TEXTURE
-    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
-        pool = D3DPOOL_DEFAULT;
-        usage = D3DUSAGE_DYNAMIC;
-    } else
-#endif
-    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
-        /* D3DPOOL_MANAGED does not work with D3DUSAGE_RENDERTARGET */
-        pool = D3DPOOL_DEFAULT;
-        usage = D3DUSAGE_RENDERTARGET;
-    } else {
-        pool = D3DPOOL_MANAGED;
-        usage = 0;
+    result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
+        PixelFormatToD3DFMT(format),
+        D3DPOOL_DEFAULT, &texture->texture, NULL);
+    if (FAILED(result)) {
+        return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
     }
 
-    result =
-        IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
-                                       texture->h, 1, usage,
-                                       PixelFormatToD3DFMT(texture->format),
-                                       pool, &data->texture, NULL);
-    if (FAILED(result)) {
-        return D3D_SetError("CreateTexture()", result);
-    }
-
-    if (texture->format == SDL_PIXELFORMAT_YV12 ||
-        texture->format == SDL_PIXELFORMAT_IYUV) {
-        data->yuv = SDL_TRUE;
-
-        result =
-            IDirect3DDevice9_CreateTexture(renderdata->device, texture->w / 2,
-                                           texture->h / 2, 1, usage,
-                                           PixelFormatToD3DFMT(texture->format),
-                                           pool, &data->utexture, NULL);
+    if (usage != D3DUSAGE_RENDERTARGET) {
+        result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
+            PixelFormatToD3DFMT(format),
+            D3DPOOL_SYSTEMMEM, &texture->staging, NULL);
         if (FAILED(result)) {
-            return D3D_SetError("CreateTexture()", result);
-        }
-
-        result =
-            IDirect3DDevice9_CreateTexture(renderdata->device, texture->w / 2,
-                                           texture->h / 2, 1, usage,
-                                           PixelFormatToD3DFMT(texture->format),
-                                           pool, &data->vtexture, NULL);
-        if (FAILED(result)) {
-            return D3D_SetError("CreateTexture()", result);
+            return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result);
         }
     }
-
     return 0;
 }
 
 static int
-D3D_UpdateTextureInternal(IDirect3DTexture9 *texture, Uint32 format, SDL_bool full_texture, int x, int y, int w, int h, const void *pixels, int pitch)
+D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int w, int h)
+{
+    HRESULT result;
+
+    if (!texture->texture) {
+        return 0;
+    }
+
+    IDirect3DTexture9_Release(texture->texture);
+    result = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
+        PixelFormatToD3DFMT(format),
+        D3DPOOL_DEFAULT, &texture->texture, NULL);
+    if (FAILED(result)) {
+        return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
+    }
+
+    result = IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
+    if (FAILED(result)) {
+        return D3D_SetError("AddDirtyRect()", result);
+    }
+    result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
+    if (FAILED(result)) {
+        return D3D_SetError("UpdateTexture()", result);
+    }
+    return 0;
+}
+
+static int
+D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int x, int y, int w, int h, const void *pixels, int pitch)
 {
     RECT d3drect;
     D3DLOCKED_RECT locked;
@@ -881,16 +874,11 @@
     int row, length;
     HRESULT result;
 
-    if (full_texture) {
-        result = IDirect3DTexture9_LockRect(texture, 0, &locked, NULL, D3DLOCK_DISCARD);
-    } else {
-        d3drect.left = x;
-        d3drect.right = x + w;
-        d3drect.top = y;
-        d3drect.bottom = y + h;
-        result = IDirect3DTexture9_LockRect(texture, 0, &locked, &d3drect, 0);
-    }
-
+    d3drect.left = x;
+    d3drect.right = x + w;
+    d3drect.top = y;
+    d3drect.bottom = y + h;
+    result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0);
     if (FAILED(result)) {
         return D3D_SetError("LockRect()", result);
     }
@@ -913,8 +901,84 @@
             dst += locked.Pitch;
         }
     }
-    IDirect3DTexture9_UnlockRect(texture, 0);
+    IDirect3DTexture9_UnlockRect(texture->staging, 0);
+    IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
+
+    return 0;
+}
+
+static void
+D3D_DestroyTextureRep(D3D_TextureRep *texture)
+{
+    if (texture->texture) {
+        IDirect3DTexture9_Release(texture->texture);
+        texture->texture = NULL;
+    }
+    if (texture->staging) {
+        IDirect3DTexture9_Release(texture->staging);
+        texture->staging = NULL;
+    }
+}
+
+static int
+D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+    D3D_TextureData *texturedata;
+    DWORD usage;
+
+    texturedata = (D3D_TextureData *) SDL_calloc(1, sizeof(*texturedata));
+    if (!texturedata) {
+        return SDL_OutOfMemory();
+    }
+    texturedata->scaleMode = GetScaleQuality();
+
+    texture->driverdata = texturedata;
 
+    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
+        usage = D3DUSAGE_RENDERTARGET;
+    } else {
+        usage = 0;
+    }
+
+    if (D3D_CreateTextureRep(data->device, &texturedata->texture, usage, texture->format, texture->w, texture->h) < 0) {
+        return -1;
+    }
+
+    if (texture->format == SDL_PIXELFORMAT_YV12 ||
+        texture->format == SDL_PIXELFORMAT_IYUV) {
+        texturedata->yuv = SDL_TRUE;
+
+        if (D3D_CreateTextureRep(data->device, &texturedata->utexture, usage, texture->format, texture->w / 2, texture->h / 2) < 0) {
+            return -1;
+        }
+
+        if (D3D_CreateTextureRep(data->device, &texturedata->vtexture, usage, texture->format, texture->w / 2, texture->h / 2) < 0) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int
+D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+    D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
+    D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
+
+    if (D3D_RecreateTextureRep(data->device, &texturedata->texture, texture->format, texture->w, texture->h) < 0) {
+        return -1;
+    }
+
+    if (texturedata->yuv) {
+        if (D3D_RecreateTextureRep(data->device, &texturedata->utexture, texture->format, texture->w / 2, texture->h / 2) < 0) {
+            return -1;
+        }
+
+        if (D3D_RecreateTextureRep(data->device, &texturedata->vtexture, texture->format, texture->w / 2, texture->h / 2) < 0) {
+            return -1;
+        }
+    }
     return 0;
 }
 
@@ -922,37 +986,29 @@
 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                   const SDL_Rect * rect, const void *pixels, int pitch)
 {
-    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
-    SDL_bool full_texture = SDL_FALSE;
+    D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
+    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
 
-#ifdef USE_DYNAMIC_TEXTURE
-    if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
-        rect->x == 0 && rect->y == 0 &&
-        rect->w == texture->w && rect->h == texture->h) {
-        full_texture = SDL_TRUE;
-    }
-#endif
-
-    if (!data) {
+    if (!texturedata) {
         SDL_SetError("Texture is not currently available");
         return -1;
     }
 
-    if (D3D_UpdateTextureInternal(data->texture, texture->format, full_texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
+    if (D3D_UpdateTextureRep(data->device, &texturedata->texture, texture->format, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
         return -1;
     }
 
-    if (data->yuv) {
+    if (texturedata->yuv) {
         /* Skip to the correct offset into the next texture */
         pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
 
-        if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->vtexture : data->utexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
+        if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
             return -1;
         }
 
         /* Skip to the correct offset into the next texture */
         pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);
-        if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->utexture : data->vtexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
+        if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
             return -1;
         }
     }
@@ -966,29 +1022,21 @@
                      const Uint8 *Uplane, int Upitch,
                      const Uint8 *Vplane, int Vpitch)
 {
-    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
-    SDL_bool full_texture = SDL_FALSE;
+    D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
+    D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
 
-#ifdef USE_DYNAMIC_TEXTURE
-    if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
-        rect->x == 0 && rect->y == 0 &&
-        rect->w == texture->w && rect->h == texture->h) {
-            full_texture = SDL_TRUE;
-    }
-#endif
-
-    if (!data) {
+    if (!texturedata) {
         SDL_SetError("Texture is not currently available");
         return -1;
     }
 
-    if (D3D_UpdateTextureInternal(data->texture, texture->format, full_texture, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
+    if (D3D_UpdateTextureRep(data->device, &texturedata->texture, texture->format, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
         return -1;
     }
-    if (D3D_UpdateTextureInternal(data->utexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch) < 0) {
+    if (D3D_UpdateTextureRep(data->device, &texturedata->utexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch) < 0) {
         return -1;
     }
-    if (D3D_UpdateTextureInternal(data->vtexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch) < 0) {
+    if (D3D_UpdateTextureRep(data->device, &texturedata->vtexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch) < 0) {
         return -1;
     }
     return 0;
@@ -998,37 +1046,39 @@
 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                 const SDL_Rect * rect, void **pixels, int *pitch)
 {
-    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
-    RECT d3drect;
-    D3DLOCKED_RECT locked;
-    HRESULT result;
+    D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
 
-    if (!data) {
+    if (!texturedata) {
         SDL_SetError("Texture is not currently available");
         return -1;
     }
 
-    if (data->yuv) {
+    texturedata->locked_rect = *rect;
+
+    if (texturedata->yuv) {
         /* It's more efficient to upload directly... */
-        if (!data->pixels) {
-            data->pitch = texture->w;
-            data->pixels = (Uint8 *)SDL_malloc((texture->h * data->pitch * 3) / 2);
-            if (!data->pixels) {
+        if (!texturedata->pixels) {
+            texturedata->pitch = texture->w;
+            texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2);
+            if (!texturedata->pixels) {
                 return SDL_OutOfMemory();
             }
         }
-        data->locked_rect = *rect;
         *pixels =
-            (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
+            (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
                       rect->x * SDL_BYTESPERPIXEL(texture->format));
-        *pitch = data->pitch;
+        *pitch = texturedata->pitch;
     } else {
+        RECT d3drect;
+        D3DLOCKED_RECT locked;
+        HRESULT result;
+
         d3drect.left = rect->x;
         d3drect.right = rect->x + rect->w;
         d3drect.top = rect->y;
         d3drect.bottom = rect->y + rect->h;
 
-        result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
+        result = IDirect3DTexture9_LockRect(texturedata->texture.staging, 0, &locked, &d3drect, 0);
         if (FAILED(result)) {
             return D3D_SetError("LockRect()", result);
         }
@@ -1041,20 +1091,22 @@
 static void
 D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
-    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
+    D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
+    D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
 
-    if (!data) {
+    if (!texturedata) {
         return;
     }
 
-    if (data->yuv) {
-        const SDL_Rect *rect = &data->locked_rect;
+    if (texturedata->yuv) {
+        const SDL_Rect *rect = &texturedata->locked_rect;
         void *pixels =
-            (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
+            (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
                       rect->x * SDL_BYTESPERPIXEL(texture->format));
-        D3D_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
+        D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch);
     } else {
-        IDirect3DTexture9_UnlockRect(data->texture, 0);
+        IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0);
+        IDirect3DDevice9_UpdateTexture(data->device, (IDirect3DBaseTexture9 *)texturedata->texture.staging, (IDirect3DBaseTexture9 *)texturedata->texture.texture);
     }
 }
 
@@ -1082,7 +1134,7 @@
         return -1;
     }
 
-    result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture, 0, &data->currentRenderTarget);
+    result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture.texture, 0, &data->currentRenderTarget);
     if(FAILED(result)) {
         return D3D_SetError("GetSurfaceLevel()", result);
     }
@@ -1530,7 +1582,7 @@
 
     result =
         IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
-                                    texturedata->texture);
+                                    texturedata->texture.texture);
     if (FAILED(result)) {
         return D3D_SetError("SetTexture()", result);
     }
@@ -1543,14 +1595,14 @@
 
         result =
             IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)
-                                        texturedata->utexture);
+                                        texturedata->utexture.texture);
         if (FAILED(result)) {
             return D3D_SetError("SetTexture()", result);
         }
 
         result =
             IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
-                                        texturedata->vtexture);
+                                        texturedata->vtexture.texture);
         if (FAILED(result)) {
             return D3D_SetError("SetTexture()", result);
         }
@@ -1673,7 +1725,7 @@
 
     result =
         IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
-                                    texturedata->texture);
+                                    texturedata->texture.texture);
     if (FAILED(result)) {
         return D3D_SetError("SetTexture()", result);
     }
@@ -1686,14 +1738,14 @@
 
         result =
             IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)
-                                        texturedata->utexture);
+                                        texturedata->utexture.texture);
         if (FAILED(result)) {
             return D3D_SetError("SetTexture()", result);
         }
 
         result =
             IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
-                                        texturedata->vtexture);
+                                        texturedata->vtexture.texture);
         if (FAILED(result)) {
             return D3D_SetError("SetTexture()", result);
         }
@@ -1816,15 +1868,9 @@
     if (!data) {
         return;
     }
-    if (data->texture) {
-        IDirect3DTexture9_Release(data->texture);
-    }
-    if (data->utexture) {
-        IDirect3DTexture9_Release(data->utexture);
-    }
-    if (data->vtexture) {
-        IDirect3DTexture9_Release(data->vtexture);
-    }
+    D3D_DestroyTextureRep(&data->texture);
+    D3D_DestroyTextureRep(&data->utexture);
+    D3D_DestroyTextureRep(&data->vtexture);
     SDL_free(data->pixels);
     SDL_free(data);
     texture->driverdata = NULL;
--- a/src/video/windows/SDL_windowsvideo.c	Sat May 31 11:33:25 2014 -0700
+++ b/src/video/windows/SDL_windowsvideo.c	Sat May 31 11:37:12 2014 -0700
@@ -184,25 +184,38 @@
 {
     *pD3DDLL = SDL_LoadObject("D3D9.DLL");
     if (*pD3DDLL) {
-        IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
+        typedef IDirect3D9 *(WINAPI *Direct3DCreate9_t) (UINT SDKVersion);
+        typedef HRESULT *(WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D);
+        Direct3DCreate9_t Direct3DCreate9Func;
+        Direct3DCreate9Ex_t Direct3DCreate9ExFunc;
 
-        D3DCreate =
-            (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(*pD3DDLL,
-            "Direct3DCreate9");
-        if (D3DCreate) {
-            *pDirect3D9Interface = D3DCreate(D3D_SDK_VERSION);
-        }
-        if (!*pDirect3D9Interface) {
-            SDL_UnloadObject(*pD3DDLL);
-            *pD3DDLL = NULL;
-            return SDL_FALSE;
+        Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9Ex");
+        if (Direct3DCreate9ExFunc) {
+            IDirect3D9Ex *pDirect3D9ExInterface;
+            HRESULT hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);
+            if (SUCCEEDED(hr)) {
+                const GUID IDirect3D9_GUID = { 0x81bdcbca, 0x64d4, 0x426d, { 0xae, 0x8d, 0xad, 0x1, 0x47, 0xf4, 0x27, 0x5c } };
+                hr = IDirect3D9Ex_QueryInterface(pDirect3D9ExInterface, &IDirect3D9_GUID, (LPVOID)pDirect3D9Interface);
+                IDirect3D9Ex_Release(pDirect3D9ExInterface);
+                if (SUCCEEDED(hr)) {
+                    return SDL_TRUE;
+                }
+            }
         }
 
-        return SDL_TRUE;
-    } else {
-        *pDirect3D9Interface = NULL;
-        return SDL_FALSE;
+        Direct3DCreate9Func = (Direct3DCreate9_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9");
+        if (Direct3DCreate9Func) {
+            *pDirect3D9Interface = Direct3DCreate9Func(D3D_SDK_VERSION);
+            if (*pDirect3D9Interface) {
+                return SDL_TRUE;
+            }
+        }
+
+        SDL_UnloadObject(*pD3DDLL);
+        *pD3DDLL = NULL;
     }
+    *pDirect3D9Interface = NULL;
+    return SDL_FALSE;
 }