[dx75] GetDeviceCaps

Jason Edmeades us at the-edmeades.demon.co.uk
Sat Aug 30 11:42:06 CDT 2003


A number of games call Directx8 GetDeviceCaps prior to creating the 
device, and more worryingly prior to creating any windows. Hence there 
is no GL context yet. Currently the code queries GL which can either 
trap or return erroneous values (in which case it returns guessed 
values), but the 'proper' way to do it is to create a dummy GL context, 
use it to query the values, and then destroy the context - ddraw and 
opengl dlls do it already,

One note: On my machine, this works UNLESS certain dlls are loaded 
beforehand in which case it traps. However, this patch doesnt cause the 
problem - I have pinned it down to linking with -lpthreads. If I 
manually remove these from the Makefile in d3d8 and d3d9, I have no 
problems, but if it is there, a simple program which 
loadlibrary(user32.dll ), freelibrary(), loadlibrary(d3d8.dll) causes a 
trap deep inside GL. (FYI : I did not put --with-nptl on the ./configure 
anymore, so I am unsure where it has come from... to be investigated).

Changelog

Use a dummy GL context if one is not available when GetDeviceCaps is called
Remove the compiler warnings introduced in the last DXTn patch

Jason
-------------- next part --------------
Index: dlls/d3d8/d3d8_main.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/d3d8_main.c,v
retrieving revision 1.12
diff -u -r1.12 d3d8_main.c
--- dlls/d3d8/d3d8_main.c	15 Aug 2003 03:50:09 -0000	1.12
+++ dlls/d3d8/d3d8_main.c	30 Aug 2003 16:29:28 -0000
@@ -61,7 +61,7 @@
 /* At process attach */
 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
 {
-    TRACE("fdwReason=%ld\n", fdwReason);
+    TRACE("D3D8 DLLMain Reason=%ld\n", fdwReason);
        if (fdwReason == DLL_PROCESS_ATTACH)
        {
            HMODULE mod;
@@ -77,3 +77,4 @@
        }
     return TRUE;
 }
+
Index: dlls/d3d8/directx.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/directx.c,v
retrieving revision 1.47
diff -u -r1.47 directx.c
--- dlls/d3d8/directx.c	15 Aug 2003 03:50:08 -0000	1.47
+++ dlls/d3d8/directx.c	30 Aug 2003 16:29:30 -0000
@@ -326,6 +326,8 @@
         case D3DFMT_DXT3:
         case D3DFMT_DXT5:
             return D3D_OK;
+        default:
+            break; /* Avoid compiler warnings */
         }
     }
 
@@ -397,9 +399,91 @@
 }
 
 HRESULT  WINAPI  IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS8* pCaps) {
+
+    BOOL        gotContext  = FALSE;
+    BOOL        created     = FALSE;
+    GLint       gl_tex_size = 0;    
+    GLXContext  gl_context  = 0;
+    Display    *display     = NULL;
     ICOM_THIS(IDirect3D8Impl,iface);
+
     TRACE("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
 
+    /* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
+        ie there is no GL Context - Get a default rendering context to enable the 
+        function query some info from GL                                           */    
+    if (glXGetCurrentContext() == NULL) {
+
+        XVisualInfo  template;
+        XVisualInfo *vis;
+        HDC          device_context;
+        Visual      *visual;
+        Drawable     drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
+        XWindowAttributes win_attr;
+        BOOL         failed = FALSE;
+        int          num;
+
+        /* Get the display */
+        device_context = GetDC(0);
+        display = get_display(device_context);
+        ReleaseDC(0, device_context);
+
+        /* Get the X visual */
+        ENTER_GL();
+        if (XGetWindowAttributes(display, drawable, &win_attr)) {
+            visual = win_attr.visual;
+        } else {
+            visual = DefaultVisual(display, DefaultScreen(display));
+        }
+        template.visualid = XVisualIDFromVisual(visual);
+        vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
+        if (vis == NULL) {
+            LEAVE_GL();
+            WARN("Error creating visual info for capabilities initialization\n");
+            failed = TRUE;
+        }
+
+        /* Create a GL context */
+        if (!failed) {
+           gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
+
+           if (gl_context == NULL) {
+              LEAVE_GL();
+              WARN("Error creating default context for capabilities initialization\n");
+              failed = TRUE;
+           }
+        }
+
+        /* Make it the current GL context */
+        if (!failed && glXMakeCurrent(display, drawable, gl_context) == False) {
+            glXDestroyContext(display, gl_context);
+            LEAVE_GL();
+            WARN("Error setting default context as current for capabilities initialization\n");
+            failed = TRUE;	
+        }
+
+        /* It worked! Wow... */
+        if (!failed) {
+           gotContext = TRUE;
+           created = TRUE;
+        }
+    }
+
+    if (gotContext == FALSE) {
+
+        FIXME("GetDeviceCaps called but no GL Context - Returning dummy values\n");
+        gl_tex_size=65535;
+        pCaps->MaxTextureBlendStages = 2;
+        pCaps->MaxSimultaneousTextures = 2;
+        pCaps->MaxUserClipPlanes = 8;
+        pCaps->MaxActiveLights = 8;
+        pCaps->MaxVertexBlendMatrices = 0;
+        pCaps->MaxVertexBlendMatrixIndex = 1;
+        pCaps->MaxAnisotropy = 0;
+        pCaps->MaxPointSize = 255.0;
+    } else {
+        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_tex_size);
+    }
     pCaps->DeviceType = (DeviceType == D3DDEVTYPE_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;  /* Not quite true, but use h/w supported by opengl I suppose */
     pCaps->AdapterOrdinal = Adapter;
 
@@ -495,12 +579,8 @@
 			 D3DLINECAPS_ALPHACMP
 			 D3DLINECAPS_FOG */
 
-    {
-      GLint gl_tex_size;    
-      glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_tex_size);
-      pCaps->MaxTextureWidth = gl_tex_size;
-      pCaps->MaxTextureHeight = gl_tex_size;
-    }
+    pCaps->MaxTextureWidth = gl_tex_size;
+    pCaps->MaxTextureHeight = gl_tex_size;
 
     pCaps->MaxVolumeExtent = 0;
 
@@ -558,10 +638,9 @@
 			      D3DTEXOPCAPS_MULTIPLYADD 
 			      D3DTEXOPCAPS_PREMODULATE */
 
-    {
+    if (gotContext) {
         GLint gl_max;
 	GLfloat gl_float;
-
 #if defined(GL_VERSION_1_3)
         glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max);
 #else
@@ -628,6 +707,12 @@
     pCaps->MaxPixelShaderValue = 0.0;
 #endif
 
+    /* If we created a dummy context, throw it away */
+    if (created) {
+        glXMakeCurrent(display, None, NULL);
+        glXDestroyContext(display, gl_context);
+        LEAVE_GL();
+    }
     return D3D_OK;
 }
 


More information about the wine-patches mailing list