wined3d: Fix CreateFakeGLContext to work with a foreign context.
[wine] / dlls / wined3d / directx.c
1 /*
2  * IWineD3D implementation
3  *
4  * Copyright 2002-2004 Jason Edmeades
5  * Copyright 2003-2004 Raphael Junqueira
6  * Copyright 2004 Christian Costa
7  * Copyright 2005 Oliver Stieber
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 /* Compile time diagnostics: */
25
26 /* Uncomment this to force only a single display mode to be exposed: */
27 /*#define DEBUG_SINGLE_MODE*/
28
29
30 #include "config.h"
31 #include <assert.h>
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
36 #define GLINFO_LOCATION This->gl_info
37
38 /**********************************************************
39  * Utility functions follow
40  **********************************************************/
41
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
45 {
46     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
47     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
48     X11DRV_GET_FONT,      /* get current X font for a DC */
49 };
50
51 /* retrieve the X display to use on a given DC */
52 inline static Display *get_display( HDC hdc )
53 {
54     Display *display;
55     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
56
57     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
58                     sizeof(display), (LPSTR)&display )) display = NULL;
59     return display;
60 }
61
62 /* lookup tables */
63 int minLookup[MAX_LOOKUPS];
64 int maxLookup[MAX_LOOKUPS];
65 DWORD *stateLookup[MAX_LOOKUPS];
66
67 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
68
69
70 /**
71  * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
72  * ie there is no GL Context - Get a default rendering context to enable the
73  * function query some info from GL
74  */
75
76 static int             wined3d_fake_gl_context_ref = 0;
77 static BOOL            wined3d_fake_gl_context_foreign;
78 static BOOL            wined3d_fake_gl_context_available = FALSE;
79 static Display*        wined3d_fake_gl_context_display = NULL;
80
81 static void WineD3D_ReleaseFakeGLContext(void) {
82     GLXContext glCtx;
83
84     if(!wined3d_fake_gl_context_available) {
85         TRACE_(d3d_caps)("context not available\n");
86         return;
87     }
88
89     glCtx = glXGetCurrentContext();
90
91     TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
92     if (0 == (--wined3d_fake_gl_context_ref) ) {
93         if(!wined3d_fake_gl_context_foreign && glCtx) {
94             TRACE_(d3d_caps)("destroying fake GL context\n");
95             glXMakeCurrent(wined3d_fake_gl_context_display, None, NULL);
96             glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
97         }
98         LEAVE_GL();
99         wined3d_fake_gl_context_available = FALSE;
100     }
101     assert(wined3d_fake_gl_context_ref >= 0);
102
103 }
104
105 static BOOL WineD3D_CreateFakeGLContext(void) {
106     XVisualInfo* visInfo;
107     GLXContext   glCtx;
108
109     TRACE_(d3d_caps)("getting context...\n");
110     if(wined3d_fake_gl_context_ref > 0) goto ret;
111     assert(0 == wined3d_fake_gl_context_ref);
112
113     wined3d_fake_gl_context_foreign = TRUE;
114
115     if(!wined3d_fake_gl_context_display) {
116         HDC        device_context = GetDC(0);
117
118         wined3d_fake_gl_context_display = get_display(device_context);
119         ReleaseDC(0, device_context);
120     }
121
122     ENTER_GL();
123
124     visInfo = NULL;
125     glCtx = glXGetCurrentContext();
126
127     if (!glCtx) {
128         Drawable     drawable;
129         XVisualInfo  template;
130         Visual*      visual;
131         int          num;
132         XWindowAttributes win_attr;
133
134         wined3d_fake_gl_context_foreign = FALSE;
135         drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
136
137         TRACE_(d3d_caps)("Creating Fake GL Context\n");
138
139         /* Get the X visual */
140         if (XGetWindowAttributes(wined3d_fake_gl_context_display, drawable, &win_attr)) {
141             visual = win_attr.visual;
142         } else {
143             visual = DefaultVisual(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display));
144         }
145         template.visualid = XVisualIDFromVisual(visual);
146         visInfo = XGetVisualInfo(wined3d_fake_gl_context_display, VisualIDMask, &template, &num);
147         if (!visInfo) {
148             WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
149             goto fail;
150         }
151
152         /* Create a GL context */
153         glCtx = glXCreateContext(wined3d_fake_gl_context_display, visInfo, NULL, GL_TRUE);
154         if (!glCtx) {
155             WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
156             goto fail;
157         }
158
159         /* Make it the current GL context */
160         if (!glXMakeCurrent(wined3d_fake_gl_context_display, drawable, glCtx)) {
161             WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
162             goto fail;
163         }
164
165         XFree(visInfo);
166
167     }
168
169   ret:
170     TRACE_(d3d_caps)("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
171     wined3d_fake_gl_context_ref++;
172     wined3d_fake_gl_context_available = TRUE;
173     return TRUE;
174   fail:
175     if(visInfo) XFree(visInfo);
176     if(glCtx) glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
177     LEAVE_GL();
178     return FALSE;
179 }
180
181 /**********************************************************
182  * IUnknown parts follows
183  **********************************************************/
184
185 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
186 {
187     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
188
189     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
190     if (IsEqualGUID(riid, &IID_IUnknown)
191         || IsEqualGUID(riid, &IID_IWineD3DBase)
192         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
193         IUnknown_AddRef(iface);
194         *ppobj = This;
195         return S_OK;
196     }
197     *ppobj = NULL;
198     return E_NOINTERFACE;
199 }
200
201 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
202     IWineD3DImpl *This = (IWineD3DImpl *)iface;
203     ULONG refCount = InterlockedIncrement(&This->ref);
204
205     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
206     return refCount;
207 }
208
209 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
210     IWineD3DImpl *This = (IWineD3DImpl *)iface;
211     ULONG ref;
212     TRACE("(%p) : Releasing from %d\n", This, This->ref);
213     ref = InterlockedDecrement(&This->ref);
214     if (ref == 0) {
215         HeapFree(GetProcessHeap(), 0, This);
216     }
217
218     return ref;
219 }
220
221 /* Set the shader type for this device, depending on the given capabilities,
222  * the device type, and the user preferences in wined3d_settings */
223
224 static void select_shader_mode(
225     WineD3D_GL_Info *gl_info,
226     WINED3DDEVTYPE DeviceType,
227     int* ps_selected,
228     int* vs_selected) {
229
230     /* Give priority to user disable/emulation request.
231      * Then respect REF device for software.
232      * Then check capabilities for hardware, and fallback to software */
233
234     if (wined3d_settings.vs_mode == VS_NONE) {
235         *vs_selected = SHADER_NONE;
236     } else if (DeviceType == WINED3DDEVTYPE_REF || wined3d_settings.vs_mode == VS_SW) {
237         *vs_selected = SHADER_SW;
238     } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
239         *vs_selected = SHADER_GLSL;
240     } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
241         *vs_selected = SHADER_ARB;
242     } else {
243         *vs_selected = SHADER_SW;
244     }
245
246     /* Fallback to SHADER_NONE where software pixel shaders should be used */
247     if (wined3d_settings.ps_mode == PS_NONE) {
248         *ps_selected = SHADER_NONE;
249     } else if (DeviceType == WINED3DDEVTYPE_REF) {
250         *ps_selected = SHADER_NONE;
251     } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
252         *ps_selected = SHADER_GLSL;
253     } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
254         *ps_selected = SHADER_ARB;
255     } else {
256         *ps_selected = SHADER_NONE;
257     }
258 }
259
260 /** Select the number of report maximum shader constants based on the selected shader modes */
261 void select_shader_max_constants(
262     int ps_selected_mode,
263     int vs_selected_mode,
264     WineD3D_GL_Info *gl_info) {
265
266     switch (vs_selected_mode) {
267         case SHADER_GLSL:
268             /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
269             gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I - 1;
270             break;
271         case SHADER_ARB:
272             /* We have to subtract any other PARAMs that we might use in our shader programs.
273              * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
274              * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
275             gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
276             break;
277         case SHADER_SW:
278             gl_info->max_vshader_constantsF = 96;  /* TODO: Fixup software shaders */
279             break;
280         default:
281             gl_info->max_vshader_constantsF = 0;
282             break;
283     }
284
285     switch (ps_selected_mode) {
286         case SHADER_GLSL:
287             /* Subtract the other potential uniforms from the max available (bools & ints) */
288             gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
289             break;
290         case SHADER_ARB:
291             gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
292             break;
293         case SHADER_SW:
294             gl_info->max_pshader_constantsF = 96;  /* TODO: Fixup software shaders */
295             break;
296         default:
297             gl_info->max_pshader_constantsF = 0;
298             break;
299     }
300 }
301
302 /**********************************************************
303  * IWineD3D parts follows
304  **********************************************************/
305
306 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
307     IWineD3DImpl *This = (IWineD3DImpl *)iface;
308     WineD3D_GL_Info *gl_info = &This->gl_info;
309
310     const char *GL_Extensions    = NULL;
311     const char *GLX_Extensions   = NULL;
312     const char *gl_string        = NULL;
313     const char *gl_string_cursor = NULL;
314     GLint       gl_max;
315     GLfloat     gl_floatv[2];
316     Bool        test = 0;
317     int         major, minor;
318     BOOL        return_value = TRUE;
319     int         i;
320
321     /* Make sure that we've got a context */
322     /* TODO: CreateFakeGLContext should really take a display as a parameter  */
323     /* Only save the values obtained when a display is provided */
324     if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
325         return_value = FALSE;
326
327     TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
328
329     gl_string = (const char *) glGetString(GL_RENDERER);
330     if (NULL == gl_string)
331         gl_string = "None";
332     strcpy(gl_info->gl_renderer, gl_string);
333
334     /* Fill in the GL info retrievable depending on the display */
335     if (NULL != display) {
336         test = glXQueryVersion(display, &major, &minor);
337         gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
338     } else {
339         FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
340     }
341     gl_string = (const char *) glGetString(GL_VENDOR);
342
343     TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
344     if (gl_string != NULL) {
345         /* Fill in the GL vendor */
346         if (strstr(gl_string, "NVIDIA")) {
347             gl_info->gl_vendor = VENDOR_NVIDIA;
348         } else if (strstr(gl_string, "ATI")) {
349             gl_info->gl_vendor = VENDOR_ATI;
350         } else if (strstr(gl_string, "Intel(R)") || 
351                    strstr(gl_info->gl_renderer, "Intel(R)")) {
352             gl_info->gl_vendor = VENDOR_INTEL;
353         } else if (strstr(gl_string, "Mesa")) {
354             gl_info->gl_vendor = VENDOR_MESA;
355         } else {
356             gl_info->gl_vendor = VENDOR_WINE;
357         }
358     } else {
359         gl_info->gl_vendor = VENDOR_WINE;
360     }
361
362
363     TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
364
365     /* Parse the GL_VERSION field into major and minor information */
366     gl_string = (const char *) glGetString(GL_VERSION);
367     if (gl_string != NULL) {
368
369         switch (gl_info->gl_vendor) {
370         case VENDOR_NVIDIA:
371             gl_string_cursor = strstr(gl_string, "NVIDIA");
372             if (!gl_string_cursor) {
373                 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
374                 break;
375             }
376
377             gl_string_cursor = strstr(gl_string_cursor, " ");
378             if (!gl_string_cursor) {
379                 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
380                 break;
381             }
382
383             while (*gl_string_cursor == ' ') {
384                 ++gl_string_cursor;
385             }
386
387             if (!*gl_string_cursor) {
388                 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
389                 break;
390             }
391
392             major = atoi(gl_string_cursor);
393             while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
394                 ++gl_string_cursor;
395             }
396
397             if (*gl_string_cursor++ != '.') {
398                 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
399                 break;
400             }
401
402             minor = atoi(gl_string_cursor);
403             minor = major*100+minor;
404             major = 10;
405
406             break;
407
408         case VENDOR_ATI:
409             major = minor = 0;
410             gl_string_cursor = strchr(gl_string, '-');
411             if (gl_string_cursor) {
412                 int error = 0;
413                 gl_string_cursor++;
414
415                 /* Check if version number is of the form x.y.z */
416                 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
417                     error = 1;
418                 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
419                     error = 1;
420                 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
421                     error = 1;
422                 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
423                     error = 1;
424
425                 /* Mark version number as malformed */
426                 if (error)
427                     gl_string_cursor = 0;
428             }
429
430             if (!gl_string_cursor)
431                 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
432             else {
433                 major = *gl_string_cursor - '0';
434                 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
435             }
436             break;
437
438         case VENDOR_INTEL:
439         case VENDOR_MESA:
440             gl_string_cursor = strstr(gl_string, "Mesa");
441             gl_string_cursor = strstr(gl_string_cursor, " ");
442             while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
443             if (*gl_string_cursor) {
444                 char tmp[16];
445                 int cursor = 0;
446
447                 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
448                     tmp[cursor++] = *gl_string_cursor;
449                     ++gl_string_cursor;
450                 }
451                 tmp[cursor] = 0;
452                 major = atoi(tmp);
453
454                 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
455                 ++gl_string_cursor;
456
457                 cursor = 0;
458                 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
459                     tmp[cursor++] = *gl_string_cursor;
460                     ++gl_string_cursor;
461                 }
462                 tmp[cursor] = 0;
463                 minor = atoi(tmp);
464             }
465             break;
466
467         default:
468             major = 0;
469             minor = 9;
470         }
471         gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
472         TRACE_(d3d_caps)("found GL_VERSION  (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
473     }
474
475     TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
476
477     /*
478      * Initialize openGL extension related variables
479      *  with Default values
480      */
481     memset(&gl_info->supported, 0, sizeof(gl_info->supported));
482     gl_info->max_buffers        = 1;
483     gl_info->max_textures       = 1;
484     gl_info->max_texture_stages = 1;
485     gl_info->max_samplers       = 1;
486     gl_info->max_sampler_stages = 1;
487     gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
488     gl_info->ps_arb_max_temps = 0;
489     gl_info->ps_arb_max_instructions = 0;
490     gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
491     gl_info->vs_arb_max_temps = 0;
492     gl_info->vs_arb_max_instructions = 0;
493     gl_info->vs_nv_version  = VS_VERSION_NOT_SUPPORTED;
494     gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
495     gl_info->vs_glsl_constantsF = 0;
496     gl_info->ps_glsl_constantsF = 0;
497     gl_info->vs_arb_constantsF = 0;
498     gl_info->ps_arb_constantsF = 0;
499
500     /* Now work out what GL support this card really has */
501 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
502     GL_EXT_FUNCS_GEN;
503     GLX_EXT_FUNCS_GEN;
504 #undef USE_GL_FUNC
505
506     /* Retrieve opengl defaults */
507     glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
508     gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
509     TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
510
511     glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
512     gl_info->max_lights = gl_max;
513     TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
514
515     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
516     gl_info->max_texture_size = gl_max;
517     TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
518
519     glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
520     gl_info->max_pointsize = gl_floatv[1];
521     TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
522
523     /* Parse the gl supported features, in theory enabling parts of our code appropriately */
524     GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
525     TRACE_(d3d_caps)("GL_Extensions reported:\n");
526
527     if (NULL == GL_Extensions) {
528         ERR("   GL_Extensions returns NULL\n");
529     } else {
530         while (*GL_Extensions != 0x00) {
531             const char *Start = GL_Extensions;
532             char        ThisExtn[256];
533
534             memset(ThisExtn, 0x00, sizeof(ThisExtn));
535             while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
536                 GL_Extensions++;
537             }
538             memcpy(ThisExtn, Start, (GL_Extensions - Start));
539             TRACE_(d3d_caps)("- %s\n", ThisExtn);
540
541             /**
542              * ARB
543              */
544             if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
545                 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
546                 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);            
547                 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
548                 gl_info->max_buffers = gl_max;
549             } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
550                 gl_info->ps_arb_version = PS_VERSION_11;
551                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
552                 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
553                 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
554                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
555                 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
556                 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
557                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
558                 gl_info->ps_arb_constantsF = gl_max;
559                 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
560                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
561                 gl_info->ps_arb_max_temps = gl_max;
562                 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
563                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
564                 gl_info->ps_arb_max_instructions = gl_max;                
565             } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
566                 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
567                 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
568                 gl_max /= 4;
569                 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
570                 gl_info->ps_glsl_constantsF = gl_max;
571             } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
572                 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
573                 gl_info->supported[ARB_IMAGING] = TRUE;
574             } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
575                 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
576                 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
577             } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
578                 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
579                 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
580                 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
581                 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
582                 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
583                 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
584             } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
585                 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
586                 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
587                 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
588                 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
589             } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
590                 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
591                 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
592             } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
593                 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
594                 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
595             } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
596                 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
597                 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
598             } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
599                 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
600                 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
601             } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
602                 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
603                 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
604             } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
605                 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
606                 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
607             } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
608                 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
609                 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
610             } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
611                 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
612                 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
613             } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
614                 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
615                 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
616             } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
617                 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
618                 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
619             } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
620                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
621                 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
622             } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
623                 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
624                 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
625             } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
626                 gl_info->vs_arb_version = VS_VERSION_11;
627                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
628                 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
629                 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
630                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
631                 gl_info->vs_arb_constantsF = gl_max;
632                 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
633                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
634                 gl_info->vs_arb_max_temps = gl_max;
635                 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
636                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
637                 gl_info->vs_arb_max_instructions = gl_max;
638             } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
639                 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
640                 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
641                 gl_max /= 4;
642                 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
643                 gl_info->vs_glsl_constantsF = gl_max;
644             } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
645                 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
646                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
647                 gl_info->max_blends = gl_max;
648                 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
649             } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
650                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
651                 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
652             } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
653                 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
654                 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
655             } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
656                 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
657                 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
658             /**
659              * EXT
660              */
661             } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
662                 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
663                 gl_info->supported[EXT_FOG_COORD] = TRUE;
664             } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
665                 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
666                 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
667             } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
668                 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
669                 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
670             } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
671                 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
672                 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
673             } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
674                 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
675                 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
676             } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
677                 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
678                 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
679             } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
680                 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
681                 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
682             } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
683                 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
684                 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
685             } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
686                 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
687                 gl_info->supported[EXT_TEXTURE3D] = TRUE;
688                 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
689                 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
690                 gl_info->max_texture3d_size = gl_max;
691             } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
692                 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
693                 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
694             } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
695                 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
696                 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
697             } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
698                 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
699                 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
700             } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
701                 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
702                 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
703             } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
704                 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
705                 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
706                 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
707                 gl_info->max_anisotropy = gl_max;
708             } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
709                 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
710                 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
711             } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
712                 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
713                 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
714             } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
715                 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
716                 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
717
718             /**
719              * NVIDIA
720              */
721             } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
722                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
723                 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
724             } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
725                 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
726                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
727             } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
728                 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
729                 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
730                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
731                 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
732             } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
733                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
734                 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
735             } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
736                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
737                 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
738             } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
739                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
740                 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
741             } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
742                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
743                 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
744             } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
745                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
746                 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
747             } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
748                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
749                 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
750             } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
751                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
752                 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
753             } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
754                 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
755                     gl_info->vs_nv_version = VS_VERSION_30;
756                 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
757                     gl_info->vs_nv_version = VS_VERSION_20;
758                 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
759                     gl_info->vs_nv_version = VS_VERSION_11;
760                 else
761                     gl_info->vs_nv_version = VS_VERSION_10;
762                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
763                 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
764
765             /**
766              * ATI
767              */
768             /** TODO */
769             } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
770                 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
771                 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
772             } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
773                 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
774                 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
775             } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
776                 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
777                 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
778             } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
779                 gl_info->vs_ati_version = VS_VERSION_11;
780                 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
781                 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
782             }
783
784
785             if (*GL_Extensions == ' ') GL_Extensions++;
786         }
787     }
788     checkGLcall("extension detection\n");
789
790     /* In some cases the number of texture stages can be larger than the number
791      * of samplers. The GF4 for example can use only 2 samplers (no fragment
792      * shaders), but 8 texture stages (register combiners). */
793     gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
794
795     /* We can only use NP2_NATIVE when the hardware supports it. */
796     if (wined3d_settings.nonpower2_mode == NP2_NATIVE && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
797         WARN_(d3d_caps)("GL_ARB_texture_non_power_of_two not supported, falling back to NP2_NONE NPOT mode.\n");
798         wined3d_settings.nonpower2_mode = NP2_NONE;
799     }
800
801     /* We can only use ORM_FBO when the hardware supports it. */
802     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
803         WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
804         wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
805     }
806
807     /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
808      * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
809      * in case of the latest videocards in the number of pixel/vertex pipelines.
810      *
811      * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
812      * rendering. Various games use this information to get a rough estimation of the features of the card
813      * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
814      * games might even use it to work around bugs which happen on certain videocards/driver combinations.
815      * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
816      * not the PCI id.
817      *
818      * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
819      * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
820      * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
821      * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
822      * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
823      * is used for rendering which is not always the case). This would work but it is not very portable. Second
824      * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
825      * is limited.
826      *
827      * As said most games only use the PCI id to get an indication of the capabilities of the card.
828      * It doesn't really matter if the given id is the correct one if we return the id of a card with
829      * similar 3d features.
830      *
831      * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
832      * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
833      * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
834      * won't pass we return a default card. This way is better than maintaining a full card database as even
835      * without a full database we can return a card with similar features. Second the size of the database
836      * can be made quite small because when you know what type of 3d functionality a card has, you know to which
837      * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
838      * to distinguishes between different models from that family. 
839      */
840     switch (gl_info->gl_vendor) {
841         case VENDOR_NVIDIA:
842             /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
843              * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
844              */
845             if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
846                 if (strstr(gl_info->gl_renderer, "7800") ||
847                     strstr(gl_info->gl_renderer, "7900") ||
848                     strstr(gl_info->gl_renderer, "7950") ||
849                     strstr(gl_info->gl_renderer, "Quadro FX 4") ||
850                     strstr(gl_info->gl_renderer, "Quadro FX 5"))
851                         gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
852                 else if(strstr(gl_info->gl_renderer, "6800") ||
853                         strstr(gl_info->gl_renderer, "7600"))
854                             gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
855                 else if(strstr(gl_info->gl_renderer, "6600") ||
856                         strstr(gl_info->gl_renderer, "6610") ||
857                         strstr(gl_info->gl_renderer, "6700"))
858                             gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
859                 else
860                     gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
861             } else if(WINE_D3D9_CAPABLE(gl_info)) {
862                 if (strstr(gl_info->gl_renderer, "5800") ||
863                     strstr(gl_info->gl_renderer, "5900") ||
864                     strstr(gl_info->gl_renderer, "5950") ||
865                     strstr(gl_info->gl_renderer, "Quadro FX"))
866                         gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
867                 else if(strstr(gl_info->gl_renderer, "5600") ||
868                         strstr(gl_info->gl_renderer, "5650") ||
869                         strstr(gl_info->gl_renderer, "5700") ||
870                         strstr(gl_info->gl_renderer, "5750"))
871                             gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
872                 else
873                     gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
874             } else if(WINE_D3D8_CAPABLE(gl_info)) {
875                 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
876                     gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
877                 else
878                     gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
879             } else if(WINE_D3D7_CAPABLE(gl_info)) {
880                 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
881                     gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
882                 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
883                     gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
884                 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
885                     gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
886                 else
887                     gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
888             } else {
889                 if (strstr(gl_info->gl_renderer, "TNT2"))
890                     gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
891                 else
892                     gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
893             }
894             break;
895         case VENDOR_ATI:
896             if(WINE_D3D9_CAPABLE(gl_info)) {
897                 /* Radeon R5xx */
898                 if (strstr(gl_info->gl_renderer, "X1600") ||
899                     strstr(gl_info->gl_renderer, "X1800") ||
900                     strstr(gl_info->gl_renderer, "X1900") ||
901                     strstr(gl_info->gl_renderer, "X1950"))
902                         gl_info->gl_card = CARD_ATI_RADEON_X1600;
903                 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
904                 else if(strstr(gl_info->gl_renderer, "X700") ||
905                         strstr(gl_info->gl_renderer, "X800") ||
906                         strstr(gl_info->gl_renderer, "X850") ||
907                         strstr(gl_info->gl_renderer, "X1300") ||
908                         strstr(gl_info->gl_renderer, "X1400"))
909                             gl_info->gl_card = CARD_ATI_RADEON_X700;
910                 /* Radeon R3xx */ 
911                 else
912                     gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
913             } else if(WINE_D3D8_CAPABLE(gl_info)) {
914                     gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
915             } else if(WINE_D3D7_CAPABLE(gl_info)) {
916                     gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
917             } else
918                 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
919             break;
920         case VENDOR_INTEL:
921             if (strstr(gl_info->gl_renderer, "915GM")) {
922                 gl_info->gl_card = CARD_INTEL_I915GM;
923             } else if (strstr(gl_info->gl_renderer, "915G")) {
924                 gl_info->gl_card = CARD_INTEL_I915G;
925             } else if (strstr(gl_info->gl_renderer, "865G")) {
926                 gl_info->gl_card = CARD_INTEL_I865G;
927             } else if (strstr(gl_info->gl_renderer, "855G")) {
928                 gl_info->gl_card = CARD_INTEL_I855G;
929             } else if (strstr(gl_info->gl_renderer, "830G")) {
930                 gl_info->gl_card = CARD_INTEL_I830G;
931             } else {
932                 gl_info->gl_card = CARD_INTEL_I915G;
933             }
934             break;
935         case VENDOR_MESA:
936         case VENDOR_WINE:
937         default:
938             /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice 
939              * for Nvidia was because the hardware and drivers they make are of good quality. This makes
940              * them a good generic choice.
941              */
942             gl_info->gl_vendor = VENDOR_NVIDIA;
943             if(WINE_D3D9_CAPABLE(gl_info))
944                 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
945             else if(WINE_D3D8_CAPABLE(gl_info))
946                 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;            
947             else if(WINE_D3D7_CAPABLE(gl_info))
948                 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
949             else if(WINE_D3D6_CAPABLE(gl_info))
950                 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
951             else
952                 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
953     }
954     TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
955
956     /* Load all the lookup tables
957     TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
958     minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
959     maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
960
961     minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
962     maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
963
964
965     for (i = 0; i < MAX_LOOKUPS; i++) {
966         stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
967     }
968
969     stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP   - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
970     stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP  - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
971     stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
972              gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
973     stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
974              gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
975     stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
976              gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
977     stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
978              gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
979
980     stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE        - minLookup[WINELOOKUP_MAGFILTER]]  = GL_NEAREST;
981     stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT       - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
982     stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR      - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
983     stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
984              gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
985
986
987     minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE]     = GL_LINEAR;
988     minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT]    = GL_LINEAR;
989     minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR]   = GL_LINEAR;
990     minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE]    = GL_NEAREST;
991     minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT]   = GL_NEAREST_MIPMAP_NEAREST;
992     minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR]  = GL_NEAREST_MIPMAP_LINEAR;
993     minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE]   = GL_LINEAR;
994     minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT]  = GL_LINEAR_MIPMAP_NEAREST;
995     minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
996     minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE]   = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
997     GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
998     minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT]  = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
999     minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1000
1001 /* TODO: config lookups */
1002
1003     if (display != NULL) {
1004         GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1005         TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1006
1007         if (NULL == GLX_Extensions) {
1008             ERR("   GLX_Extensions returns NULL\n");
1009         } else {
1010             while (*GLX_Extensions != 0x00) {
1011                 const char *Start = GLX_Extensions;
1012                 char ThisExtn[256];
1013
1014                 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1015                 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1016                     GLX_Extensions++;
1017                 }
1018                 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1019                 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1020                 if (*GLX_Extensions == ' ') GLX_Extensions++;
1021             }
1022         }
1023     }
1024
1025
1026     WineD3D_ReleaseFakeGLContext();
1027     return return_value;
1028 }
1029
1030 /**********************************************************
1031  * IWineD3D implementation follows
1032  **********************************************************/
1033
1034 static UINT     WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1035     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1036
1037     /* FIXME: Set to one for now to imply the display */
1038     TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1039     return 1;
1040 }
1041
1042 static HRESULT  WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1043     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1044     FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1045     return WINED3D_OK;
1046 }
1047
1048 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1049     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1050     POINT pt = { -1, -1 };
1051
1052     if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1053         return NULL;
1054     }
1055
1056     FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1057     return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1058 }
1059
1060 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1061      of the same bpp but different resolutions                                  */
1062
1063 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1064 static UINT     WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1065     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1066     TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1067
1068     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1069         return 0;
1070     }
1071
1072     if (Adapter == 0) { /* Display */
1073         int i = 0;
1074         int j = 0;
1075 #if !defined( DEBUG_SINGLE_MODE )
1076         DEVMODEW DevModeW;
1077
1078         /* Work out the current screen bpp */
1079         HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1080         int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1081         DeleteDC(hdc);
1082
1083         while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1084             j++;
1085             switch (Format)
1086             {
1087             case WINED3DFMT_UNKNOWN:
1088                    i++;
1089                    break;
1090             case WINED3DFMT_X8R8G8B8:
1091             case WINED3DFMT_A8R8G8B8:
1092                    if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
1093                    if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
1094                    break;
1095             case WINED3DFMT_X1R5G5B5:
1096             case WINED3DFMT_A1R5G5B5:
1097             case WINED3DFMT_R5G6B5:
1098                    if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
1099                    break;
1100             default:
1101                    /* Skip other modes as they do not match the requested format */
1102                    break;
1103             }
1104         }
1105 #else
1106         i = 1;
1107         j = 1;
1108 #endif
1109         TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1110         return i;
1111     } else {
1112         FIXME_(d3d_caps)("Adapter not primary display\n");
1113     }
1114     return 0;
1115 }
1116
1117 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1118 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1119     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1120     TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1121
1122     /* Validate the parameters as much as possible */
1123     if (NULL == pMode ||
1124         Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1125         Mode    >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1126         return WINED3DERR_INVALIDCALL;
1127     }
1128
1129     if (Adapter == 0) { /* Display */
1130         int bpp;
1131 #if !defined( DEBUG_SINGLE_MODE )
1132         DEVMODEW DevModeW;
1133         int ModeIdx = 0;
1134
1135         /* Work out the current screen bpp */
1136         HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1137         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1138         DeleteDC(hdc);
1139
1140         /* If we are filtering to a specific format, then need to skip all unrelated
1141            modes, but if mode is irrelevant, then we can use the index directly      */
1142         if (Format == WINED3DFMT_UNKNOWN)
1143         {
1144             ModeIdx = Mode;
1145         } else {
1146             int i = 0;
1147             int j = 0;
1148             DEVMODEW DevModeWtmp;
1149
1150
1151             while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
1152                 j++;
1153                 switch (Format)
1154                 {
1155                 case WINED3DFMT_UNKNOWN:
1156                        i++;
1157                        break;
1158                 case WINED3DFMT_X8R8G8B8:
1159                 case WINED3DFMT_A8R8G8B8:
1160                        if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
1161                        if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
1162                        break;
1163                 case WINED3DFMT_X1R5G5B5:
1164                 case WINED3DFMT_A1R5G5B5:
1165                 case WINED3DFMT_R5G6B5:
1166                        if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
1167                        break;
1168                 default:
1169                        /* Skip other modes as they do not match requested format */
1170                        break;
1171                 }
1172             }
1173             ModeIdx = j;
1174         }
1175
1176         /* Now get the display mode via the calculated index */
1177         if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
1178         {
1179             pMode->Width        = DevModeW.dmPelsWidth;
1180             pMode->Height       = DevModeW.dmPelsHeight;
1181             bpp                 = min(DevModeW.dmBitsPerPel, bpp);
1182             pMode->RefreshRate  = D3DADAPTER_DEFAULT;
1183             if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1184             {
1185                 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1186             }
1187
1188             if (Format == WINED3DFMT_UNKNOWN)
1189             {
1190                 switch (bpp) {
1191                 case  8: pMode->Format = WINED3DFMT_R3G3B2;   break;
1192                 case 16: pMode->Format = WINED3DFMT_R5G6B5;   break;
1193                 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
1194                 case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break;
1195                 default: pMode->Format = WINED3DFMT_UNKNOWN;
1196                 }
1197             } else {
1198                 pMode->Format = Format;
1199             }
1200         }
1201         else
1202         {
1203             TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1204             return WINED3DERR_INVALIDCALL;
1205         }
1206
1207 #else
1208         /* Return one setting of the format requested */
1209         if (Mode > 0) return WINED3DERR_INVALIDCALL;
1210         pMode->Width        = 800;
1211         pMode->Height       = 600;
1212         pMode->RefreshRate  = D3DADAPTER_DEFAULT;
1213         pMode->Format       = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_A8R8G8B8 : Format;
1214         bpp = 32;
1215 #endif
1216         TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1217                  pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
1218
1219     } else {
1220         FIXME_(d3d_caps)("Adapter not primary display\n");
1221     }
1222
1223     return WINED3D_OK;
1224 }
1225
1226 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1227     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1228     TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1229
1230     if (NULL == pMode ||
1231         Adapter >= IWineD3D_GetAdapterCount(iface)) {
1232         return WINED3DERR_INVALIDCALL;
1233     }
1234
1235     if (Adapter == 0) { /* Display */
1236         int bpp = 0;
1237         DEVMODEW DevModeW;
1238
1239         EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1240         pMode->Width        = DevModeW.dmPelsWidth;
1241         pMode->Height       = DevModeW.dmPelsHeight;
1242         bpp                 = DevModeW.dmBitsPerPel;
1243         pMode->RefreshRate  = D3DADAPTER_DEFAULT;
1244         if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1245         {
1246             pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1247         }
1248
1249         switch (bpp) {
1250         case  8: pMode->Format       = WINED3DFMT_R3G3B2;   break;
1251         case 16: pMode->Format       = WINED3DFMT_R5G6B5;   break;
1252         case 24: pMode->Format       = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1253         case 32: pMode->Format       = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1254         default: pMode->Format       = WINED3DFMT_UNKNOWN;
1255         }
1256
1257     } else {
1258         FIXME_(d3d_caps)("Adapter not primary display\n");
1259     }
1260
1261     TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1262           pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1263     return WINED3D_OK;
1264 }
1265
1266 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1267     Display *display;
1268     HDC     device_context;
1269     /* only works with one adapter at the moment... */
1270
1271     /* Get the display */
1272     device_context = GetDC(0);
1273     display = get_display(device_context);
1274     ReleaseDC(0, device_context);
1275     return display;
1276 }
1277
1278 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1279    and fields being inserted in the middle, a new structure is used in place    */
1280 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1281                                                    WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1282     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1283
1284     TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1285
1286     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1287         return WINED3DERR_INVALIDCALL;
1288     }
1289
1290     if (Adapter == 0) { /* Display - only device supported for now */
1291
1292         BOOL isGLInfoValid = This->isGLInfoValid;
1293
1294         /* FillGLCaps updates gl_info, but we only want to store and
1295            reuse the values once we have a context which is valid. Values from
1296            a temporary context may differ from the final ones                 */
1297         if (!isGLInfoValid) {
1298             /* If we don't know the device settings, go query them now */
1299             isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1300         }
1301
1302         /* If it worked, return the information requested */
1303         if (isGLInfoValid) {
1304           TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1305           strcpy(pIdentifier->Driver, "Display");
1306           strcpy(pIdentifier->Description, "Direct3D HAL");
1307
1308           /* Note dx8 doesn't supply a DeviceName */
1309           if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1310           /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1311           pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1312           pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1313           *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1314           *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1315           *(pIdentifier->SubSysId) = 0;
1316           *(pIdentifier->Revision) = 0;
1317
1318         } else {
1319
1320           /* If it failed, return dummy values from an NVidia driver */
1321           WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1322           strcpy(pIdentifier->Driver, "Display");
1323           strcpy(pIdentifier->Description, "Direct3D HAL");
1324           if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1325           /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1326           pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1327           /* 71.74 is a current Linux Nvidia driver version */
1328           pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1329           *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1330           *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1331           *(pIdentifier->SubSysId) = 0;
1332           *(pIdentifier->Revision) = 0;
1333         }
1334
1335         /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1336         if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1337             *(pIdentifier->WHQLLevel) = 0;
1338         } else {
1339             *(pIdentifier->WHQLLevel) = 1;
1340         }
1341
1342     } else {
1343         FIXME_(d3d_caps)("Adapter not primary display\n");
1344     }
1345
1346     return WINED3D_OK;
1347 }
1348
1349 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1350 #if 0 /* This code performs a strict test between the format and the current X11  buffer depth, which may give the best performance */
1351   int gl_test;
1352   int rb, gb, bb, ab, type, buf_sz;
1353
1354   gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE,   &rb);
1355   gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1356   gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE,  &bb);
1357   gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1358   gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1359   gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1360
1361   switch (Format) {
1362   case WINED3DFMT_X8R8G8B8:
1363   case WINED3DFMT_R8G8B8:
1364     if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1365     break;
1366   case WINED3DFMT_A8R8G8B8:
1367     if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1368     break;
1369   case WINED3DFMT_A2R10G10B10:
1370     if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1371     break;
1372   case WINED3DFMT_X1R5G5B5:
1373     if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1374     break;
1375   case WINED3DFMT_A1R5G5B5:
1376     if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1377     break;
1378   case WINED3DFMT_X4R4G4B4:
1379     if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1380     break;
1381   case WINED3DFMT_R5G6B5:
1382     if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1383     break;
1384   case WINED3DFMT_R3G3B2:
1385     if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1386     break;
1387   case WINED3DFMT_A8P8:
1388     if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1389     break;
1390   case WINED3DFMT_P8:
1391     if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1392     break;
1393   default:
1394     ERR("unsupported format %s\n", debug_d3dformat(Format));
1395     break;
1396   }
1397   return FALSE;
1398 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1399 switch (Format) {
1400   case WINED3DFMT_X8R8G8B8:
1401   case WINED3DFMT_R8G8B8:
1402   case WINED3DFMT_A8R8G8B8:
1403   case WINED3DFMT_A2R10G10B10:
1404   case WINED3DFMT_X1R5G5B5:
1405   case WINED3DFMT_A1R5G5B5:
1406   case WINED3DFMT_R5G6B5:
1407   case WINED3DFMT_R3G3B2:
1408   case WINED3DFMT_A8P8:
1409   case WINED3DFMT_P8:
1410 return TRUE;
1411   default:
1412     ERR("unsupported format %s\n", debug_d3dformat(Format));
1413     break;
1414   }
1415 return FALSE;
1416 #endif
1417 }
1418
1419 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1420 #if 0/* This code performs a strict test between the format and the current X11  buffer depth, which may give the best performance */
1421   int gl_test;
1422   int db, sb;
1423
1424   gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1425   gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1426
1427   switch (Format) {
1428   case WINED3DFMT_D16:
1429   case WINED3DFMT_D16_LOCKABLE:
1430     if (16 == db) return TRUE;
1431     break;
1432   case WINED3DFMT_D32:
1433     if (32 == db) return TRUE;
1434     break;
1435   case WINED3DFMT_D15S1:
1436     if (15 == db) return TRUE;
1437     break;
1438   case WINED3DFMT_D24S8:
1439     if (24 == db && 8 == sb) return TRUE;
1440     break;
1441   case WINED3DFMT_D24FS8:
1442     if (24 == db && 8 == sb) return TRUE;
1443     break;
1444   case WINED3DFMT_D24X8:
1445     if (24 == db) return TRUE;
1446     break;
1447   case WINED3DFMT_D24X4S4:
1448     if (24 == db && 4 == sb) return TRUE;
1449     break;
1450   case WINED3DFMT_D32F_LOCKABLE:
1451     if (32 == db) return TRUE;
1452     break;
1453   default:
1454     ERR("unsupported format %s\n", debug_d3dformat(Format));
1455     break;
1456   }
1457   return FALSE;
1458 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1459   switch (Format) {
1460   case WINED3DFMT_D16:
1461   case WINED3DFMT_D16_LOCKABLE:
1462   case WINED3DFMT_D32:
1463   case WINED3DFMT_D15S1:
1464   case WINED3DFMT_D24S8:
1465   case WINED3DFMT_D24FS8:
1466   case WINED3DFMT_D24X8:
1467   case WINED3DFMT_D24X4S4:
1468   case WINED3DFMT_D32F_LOCKABLE:
1469     return TRUE;
1470   default:
1471     ERR("unsupported format %s\n", debug_d3dformat(Format));
1472     break;
1473   }
1474   return FALSE;
1475 #endif
1476 }
1477
1478 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1479                                                    WINED3DFORMAT AdapterFormat,
1480                                                    WINED3DFORMAT RenderTargetFormat,
1481                                                    WINED3DFORMAT DepthStencilFormat) {
1482     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1483     HRESULT hr = WINED3DERR_NOTAVAILABLE;
1484     GLXFBConfig* cfgs = NULL;
1485     int nCfgs = 0;
1486     int it;
1487
1488     WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1489            This, Adapter,
1490            DeviceType, debug_d3ddevicetype(DeviceType),
1491            AdapterFormat, debug_d3dformat(AdapterFormat),
1492            RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1493            DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1494
1495     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1496         TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1497         return WINED3DERR_INVALIDCALL;
1498     }
1499
1500     if(WineD3D_CreateFakeGLContext())
1501         cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1502
1503     if (cfgs) {
1504         for (it = 0; it < nCfgs; ++it) {
1505             if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1506                 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1507                     hr = WINED3D_OK;
1508                     break ;
1509                 }
1510             }
1511         }
1512         XFree(cfgs);
1513         cfgs = NULL;
1514     } else {
1515         /* If there's a current context then we cannot create a fake one so pass everything */
1516         hr = WINED3D_OK;
1517     }
1518
1519     WineD3D_ReleaseFakeGLContext();
1520
1521     if (hr != WINED3D_OK)
1522         TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1523
1524     TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1525     return hr;
1526 }
1527
1528 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, 
1529                                                        WINED3DFORMAT SurfaceFormat,
1530                                                        BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD*   pQualityLevels) {
1531
1532     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1533     TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1534           This,
1535           Adapter,
1536           DeviceType, debug_d3ddevicetype(DeviceType),
1537           SurfaceFormat, debug_d3dformat(SurfaceFormat),
1538           Windowed,
1539           MultiSampleType,
1540           pQualityLevels);
1541
1542     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1543         return WINED3DERR_INVALIDCALL;
1544     }
1545
1546     if (pQualityLevels != NULL) {
1547         static int s_single_shot = 0;
1548         if (!s_single_shot) {
1549             FIXME("Quality levels unsupported at present\n");
1550             s_single_shot = 1;
1551         }
1552         *pQualityLevels = 1; /* Guess at a value! */
1553     }
1554
1555     if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1556     return WINED3DERR_NOTAVAILABLE;
1557 }
1558
1559 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1560                                             WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1561
1562     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1563     GLXFBConfig* cfgs = NULL;
1564     int nCfgs = 0;
1565     int it;
1566     HRESULT hr = WINED3DERR_NOTAVAILABLE;
1567
1568     TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1569           This,
1570           Adapter,
1571           CheckType, debug_d3ddevicetype(CheckType),
1572           DisplayFormat, debug_d3dformat(DisplayFormat),
1573           BackBufferFormat, debug_d3dformat(BackBufferFormat),
1574           Windowed);
1575
1576     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1577         WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1578         return WINED3DERR_INVALIDCALL;
1579     }
1580
1581     if (WineD3D_CreateFakeGLContext()) {
1582       cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1583       for (it = 0; it < nCfgs; ++it) {
1584           if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1585               hr = WINED3D_OK;
1586               TRACE_(d3d_caps)("OK\n");
1587               break ;
1588           }
1589       }
1590       if(cfgs) XFree(cfgs);
1591       WineD3D_ReleaseFakeGLContext();
1592     }
1593
1594     if(hr != WINED3D_OK)
1595         TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1596
1597     return hr;
1598 }
1599
1600 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, 
1601                                               WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1602     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1603     TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1604           This,
1605           Adapter,
1606           DeviceType, debug_d3ddevicetype(DeviceType),
1607           AdapterFormat, debug_d3dformat(AdapterFormat),
1608           Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1609           RType, debug_d3dresourcetype(RType),
1610           CheckFormat, debug_d3dformat(CheckFormat));
1611
1612     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1613         return WINED3DERR_INVALIDCALL;
1614     }
1615
1616     /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1617      * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1618      * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1619     if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1620         TRACE_(d3d_caps)("[FAILED]\n");
1621         return WINED3DERR_NOTAVAILABLE;     /* Enable when fully supported */
1622     }
1623     
1624     if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1625         switch (CheckFormat) {
1626             case WINED3DFMT_D16_LOCKABLE:
1627             case WINED3DFMT_D32:
1628             case WINED3DFMT_D15S1:
1629             case WINED3DFMT_D24S8:
1630             case WINED3DFMT_D24X8:
1631             case WINED3DFMT_D24X4S4:
1632             case WINED3DFMT_D16:
1633             case WINED3DFMT_L16:
1634             case WINED3DFMT_D32F_LOCKABLE:
1635             case WINED3DFMT_D24FS8:
1636                 TRACE_(d3d_caps)("[OK]\n");
1637                 return WINED3D_OK;
1638             default:
1639                 TRACE_(d3d_caps)("[FAILED]\n");
1640                 return WINED3DERR_NOTAVAILABLE;
1641         }
1642     } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1643         switch (CheckFormat) {
1644             case WINED3DFMT_R8G8B8:
1645             case WINED3DFMT_A8R8G8B8:
1646             case WINED3DFMT_X8R8G8B8:
1647             case WINED3DFMT_R5G6B5:
1648             case WINED3DFMT_X1R5G5B5:
1649             case WINED3DFMT_A1R5G5B5:
1650             case WINED3DFMT_A4R4G4B4:
1651             case WINED3DFMT_R3G3B2:
1652             case WINED3DFMT_X4R4G4B4:
1653             case WINED3DFMT_A8B8G8R8:
1654             case WINED3DFMT_X8B8G8R8:
1655             case WINED3DFMT_P8:
1656                 TRACE_(d3d_caps)("[OK]\n");
1657                 return WINED3D_OK;
1658             default:
1659                 TRACE_(d3d_caps)("[FAILED]\n");
1660                 return WINED3DERR_NOTAVAILABLE;
1661         }
1662     }
1663
1664     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1665         switch (CheckFormat) {
1666         case WINED3DFMT_DXT1:
1667         case WINED3DFMT_DXT2:
1668         case WINED3DFMT_DXT3:
1669         case WINED3DFMT_DXT4:
1670         case WINED3DFMT_DXT5:
1671           TRACE_(d3d_caps)("[OK]\n");
1672           return WINED3D_OK;
1673         default:
1674             break; /* Avoid compiler warnings */
1675         }
1676     }
1677
1678     if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1679
1680         BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1681
1682         switch (CheckFormat) {
1683             case WINED3DFMT_R16F:
1684             case WINED3DFMT_A16B16G16R16F:
1685                 if (!half_pixel_support) break;
1686             case WINED3DFMT_R32F:
1687             case WINED3DFMT_A32B32G32R32F:
1688                 TRACE_(d3d_caps)("[OK]\n");
1689                 return WINED3D_OK;
1690             default:
1691                 break; /* Avoid compiler warnings */
1692         }
1693     }
1694
1695     /* This format is nothing special and it is supported perfectly.
1696      * However, ati and nvidia driver on windows do not mark this format as
1697      * supported (tested with the dxCapsViewer) and pretending to
1698      * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1699      * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1700      * Enable it on dx7. It will need additional checking on dx10 when we support it.
1701      */
1702     if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1703         TRACE_(d3d_caps)("[FAILED]\n");
1704         return WINED3DERR_NOTAVAILABLE;
1705     }
1706
1707     switch (CheckFormat) {
1708
1709         /*****
1710          *  supported: RGB(A) formats
1711          */
1712         case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1713         case WINED3DFMT_A8R8G8B8:
1714         case WINED3DFMT_X8R8G8B8:
1715         case WINED3DFMT_R5G6B5:
1716         case WINED3DFMT_X1R5G5B5:
1717         case WINED3DFMT_A1R5G5B5:
1718         case WINED3DFMT_A4R4G4B4:
1719         case WINED3DFMT_R3G3B2:
1720         case WINED3DFMT_A8:
1721         case WINED3DFMT_A8R3G3B2:
1722         case WINED3DFMT_X4R4G4B4:
1723         case WINED3DFMT_A8B8G8R8:
1724         case WINED3DFMT_X8B8G8R8:
1725         case WINED3DFMT_A2R10G10B10:
1726         case WINED3DFMT_A2B10G10R10:
1727             TRACE_(d3d_caps)("[OK]\n");
1728             return WINED3D_OK;
1729
1730         /*****
1731          *  supported: Palettized
1732          */
1733         case WINED3DFMT_P8:
1734             TRACE_(d3d_caps)("[OK]\n");
1735             return WINED3D_OK;
1736
1737         /*****
1738          *  Supported: (Alpha)-Luminance
1739          */
1740         case WINED3DFMT_L8:
1741         case WINED3DFMT_A8L8:
1742         case WINED3DFMT_A4L4:
1743             TRACE_(d3d_caps)("[OK]\n");
1744             return WINED3D_OK;
1745
1746         /*****
1747          *  Not supported for now: Bump mapping formats
1748          *  Enable some because games often fail when they are not available
1749          *  and are still playable even without bump mapping
1750          */
1751         case WINED3DFMT_V8U8:
1752         case WINED3DFMT_V16U16:
1753         case WINED3DFMT_L6V5U5:
1754         case WINED3DFMT_X8L8V8U8:
1755         case WINED3DFMT_Q8W8V8U8:
1756         case WINED3DFMT_W11V11U10:
1757         case WINED3DFMT_A2W10V10U10:
1758             WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1759             return WINED3D_OK;
1760
1761         /*****
1762          *  DXTN Formats: Handled above
1763          * WINED3DFMT_DXT1
1764          * WINED3DFMT_DXT2
1765          * WINED3DFMT_DXT3
1766          * WINED3DFMT_DXT4
1767          * WINED3DFMT_DXT5
1768          */
1769
1770         /*****
1771          *  Odd formats - not supported
1772          */
1773         case WINED3DFMT_VERTEXDATA:
1774         case WINED3DFMT_INDEX16:
1775         case WINED3DFMT_INDEX32:
1776         case WINED3DFMT_Q16W16V16U16:
1777             TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1778             return WINED3DERR_NOTAVAILABLE;
1779
1780         /*****
1781          *  Float formats: Not supported right now
1782          */
1783         case WINED3DFMT_G16R16F:
1784         case WINED3DFMT_G32R32F:
1785         case WINED3DFMT_CxV8U8:
1786             TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1787             return WINED3DERR_NOTAVAILABLE;
1788
1789             /* Not supported */
1790         case WINED3DFMT_G16R16:
1791         case WINED3DFMT_A16B16G16R16:
1792             TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1793             return WINED3DERR_NOTAVAILABLE;
1794
1795         default:
1796             break;
1797     }
1798
1799     TRACE_(d3d_caps)("[FAILED]\n");
1800     return WINED3DERR_NOTAVAILABLE;
1801 }
1802
1803 static HRESULT  WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1804                                                           WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1805     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1806
1807     FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1808           This,
1809           Adapter,
1810           DeviceType, debug_d3ddevicetype(DeviceType),
1811           SourceFormat, debug_d3dformat(SourceFormat),
1812           TargetFormat, debug_d3dformat(TargetFormat));
1813     return WINED3D_OK;
1814 }
1815
1816 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1817       subset of a D3DCAPS9 structure. However, it has to come via a void *
1818       as the d3d8 interface cannot import the d3d9 header                  */
1819 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1820
1821     IWineD3DImpl    *This = (IWineD3DImpl *)iface;
1822     int vs_selected_mode;
1823     int ps_selected_mode;
1824
1825     TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1826
1827     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1828         return WINED3DERR_INVALIDCALL;
1829     }
1830
1831     /* FIXME: GL info should be per adapter */
1832
1833     /* If we don't know the device settings, go query them now */
1834     if (!This->isGLInfoValid) {
1835         /* use the desktop window to fill gl caps */
1836         BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1837
1838         /* We are running off a real context, save the values */
1839         if (rc) This->isGLInfoValid = TRUE;
1840     }
1841     select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1842
1843     /* This function should *not* be modifying GL caps
1844      * TODO: move the functionality where it belongs */
1845     select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1846
1847     /* ------------------------------------------------
1848        The following fields apply to both d3d8 and d3d9
1849        ------------------------------------------------ */
1850     *pCaps->DeviceType              = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF;  /* Not quite true, but use h/w supported by opengl I suppose */
1851     *pCaps->AdapterOrdinal          = Adapter;
1852
1853     *pCaps->Caps                    = 0;
1854     *pCaps->Caps2                   = WINED3DCAPS2_CANRENDERWINDOWED |
1855                                       WINED3DCAPS2_FULLSCREENGAMMA;
1856     *pCaps->Caps3                   = 0;
1857     *pCaps->PresentationIntervals   = D3DPRESENT_INTERVAL_IMMEDIATE;
1858
1859     *pCaps->CursorCaps              = 0;
1860
1861
1862     *pCaps->DevCaps                 = WINED3DDEVCAPS_FLOATTLVERTEX       |
1863                                       WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1864                                       WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1865                                       WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1866                                       WINED3DDEVCAPS_DRAWPRIMTLVERTEX    |
1867                                       WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1868                                       WINED3DDEVCAPS_EXECUTEVIDEOMEMORY  |
1869                                       WINED3DDEVCAPS_PUREDEVICE          |
1870                                       WINED3DDEVCAPS_HWRASTERIZATION     |
1871                                       WINED3DDEVCAPS_TEXTUREVIDEOMEMORY  |
1872                                       WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1873                                       WINED3DDEVCAPS_CANRENDERAFTERFLIP  |
1874                                       WINED3DDEVCAPS_DRAWPRIMITIVES2     |
1875                                       WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1876
1877     *pCaps->PrimitiveMiscCaps       = D3DPMISCCAPS_CULLNONE              |
1878                                       D3DPMISCCAPS_CULLCCW               |
1879                                       D3DPMISCCAPS_CULLCW                |
1880                                       D3DPMISCCAPS_COLORWRITEENABLE      |
1881                                       D3DPMISCCAPS_CLIPTLVERTS           |
1882                                       D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1883                                       D3DPMISCCAPS_MASKZ                 |
1884                                       D3DPMISCCAPS_BLENDOP;
1885                                     /* TODO:
1886                                         D3DPMISCCAPS_NULLREFERENCE
1887                                         D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1888                                         D3DPMISCCAPS_FOGANDSPECULARALPHA
1889                                         D3DPMISCCAPS_SEPARATEALPHABLEND
1890                                         D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1891                                         D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1892                                         D3DPMISCCAPS_FOGVERTEXCLAMPED */
1893
1894 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1895 #if 0
1896     if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1897         *pCaps->PrimitiveMiscCaps |=  D3DPMISCCAPS_TSSARGTEMP;
1898     if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1899         *pCaps->PrimitiveMiscCaps |=  D3DPMISCCAPS_PERSTAGECONSTANT;
1900 #endif
1901
1902     *pCaps->RasterCaps              = WINED3DPRASTERCAPS_DITHER    |
1903                                       WINED3DPRASTERCAPS_PAT       |
1904                                       WINED3DPRASTERCAPS_WFOG      |
1905                                       WINED3DPRASTERCAPS_ZFOG      |
1906                                       WINED3DPRASTERCAPS_FOGVERTEX |
1907                                       WINED3DPRASTERCAPS_FOGTABLE  |
1908                                       WINED3DPRASTERCAPS_FOGRANGE  |
1909                                       WINED3DPRASTERCAPS_STIPPLE   |
1910                                       WINED3DPRASTERCAPS_SUBPIXEL  |
1911                                       WINED3DPRASTERCAPS_ZTEST     |
1912                                       WINED3DPRASTERCAPS_SCISSORTEST   |
1913                                       WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1914                                       WINED3DPRASTERCAPS_DEPTHBIAS;
1915
1916     if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1917       *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY    |
1918                             WINED3DPRASTERCAPS_ZBIAS         |
1919                             WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1920     }
1921                         /* FIXME Add:
1922                            WINED3DPRASTERCAPS_COLORPERSPECTIVE
1923                            WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1924                            WINED3DPRASTERCAPS_ANTIALIASEDGES
1925                            WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1926                            WINED3DPRASTERCAPS_WBUFFER */
1927
1928     *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS       |
1929                        D3DPCMPCAPS_EQUAL        |
1930                        D3DPCMPCAPS_GREATER      |
1931                        D3DPCMPCAPS_GREATEREQUAL |
1932                        D3DPCMPCAPS_LESS         |
1933                        D3DPCMPCAPS_LESSEQUAL    |
1934                        D3DPCMPCAPS_NEVER        |
1935                        D3DPCMPCAPS_NOTEQUAL;
1936
1937     *pCaps->SrcBlendCaps  = D3DPBLENDCAPS_BLENDFACTOR     |
1938                             D3DPBLENDCAPS_BOTHINVSRCALPHA |
1939                             D3DPBLENDCAPS_BOTHSRCALPHA    |
1940                             D3DPBLENDCAPS_DESTALPHA       |
1941                             D3DPBLENDCAPS_DESTCOLOR       |
1942                             D3DPBLENDCAPS_INVDESTALPHA    |
1943                             D3DPBLENDCAPS_INVDESTCOLOR    |
1944                             D3DPBLENDCAPS_INVSRCALPHA     |
1945                             D3DPBLENDCAPS_INVSRCCOLOR     |
1946                             D3DPBLENDCAPS_ONE             |
1947                             D3DPBLENDCAPS_SRCALPHA        |
1948                             D3DPBLENDCAPS_SRCALPHASAT     |
1949                             D3DPBLENDCAPS_SRCCOLOR        |
1950                             D3DPBLENDCAPS_ZERO;
1951                             
1952     *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR     |
1953                             D3DPBLENDCAPS_BOTHINVSRCALPHA |
1954                             D3DPBLENDCAPS_BOTHSRCALPHA    |
1955                             D3DPBLENDCAPS_DESTALPHA       |
1956                             D3DPBLENDCAPS_DESTCOLOR       |
1957                             D3DPBLENDCAPS_INVDESTALPHA    |
1958                             D3DPBLENDCAPS_INVDESTCOLOR    |
1959                             D3DPBLENDCAPS_INVSRCALPHA     |
1960                             D3DPBLENDCAPS_INVSRCCOLOR     |
1961                             D3DPBLENDCAPS_ONE             |
1962                             D3DPBLENDCAPS_SRCALPHA        |
1963                             D3DPBLENDCAPS_SRCALPHASAT     |
1964                             D3DPBLENDCAPS_SRCCOLOR        |
1965                             D3DPBLENDCAPS_ZERO;
1966
1967     *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS       |
1968                            D3DPCMPCAPS_EQUAL        |
1969                            D3DPCMPCAPS_GREATER      |
1970                            D3DPCMPCAPS_GREATEREQUAL |
1971                            D3DPCMPCAPS_LESS         |
1972                            D3DPCMPCAPS_LESSEQUAL    |
1973                            D3DPCMPCAPS_NEVER        |
1974                            D3DPCMPCAPS_NOTEQUAL;
1975
1976     *pCaps->ShadeCaps     = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1977                             WINED3DPSHADECAPS_COLORGOURAUDRGB    |
1978                             WINED3DPSHADECAPS_ALPHAFLATBLEND     |
1979                             WINED3DPSHADECAPS_ALPHAGOURAUDBLEND  |
1980                             WINED3DPSHADECAPS_COLORFLATRGB       |
1981                             WINED3DPSHADECAPS_FOGFLAT            |
1982                             WINED3DPSHADECAPS_FOGGOURAUD         |
1983                             WINED3DPSHADECAPS_SPECULARFLATRGB;
1984
1985     *pCaps->TextureCaps =  WINED3DPTEXTURECAPS_ALPHA              |
1986                            WINED3DPTEXTURECAPS_ALPHAPALETTE       |
1987                            WINED3DPTEXTURECAPS_BORDER             |
1988                            WINED3DPTEXTURECAPS_MIPMAP             |
1989                            WINED3DPTEXTURECAPS_PROJECTED          |
1990                            WINED3DPTEXTURECAPS_PERSPECTIVE        |
1991                            WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1992
1993     if( GL_SUPPORT(EXT_TEXTURE3D)) {
1994         *pCaps->TextureCaps |=  WINED3DPTEXTURECAPS_VOLUMEMAP      |
1995                                 WINED3DPTEXTURECAPS_MIPVOLUMEMAP   |
1996                                 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1997     }
1998
1999     if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2000         *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP     |
2001                              WINED3DPTEXTURECAPS_MIPCUBEMAP    |
2002                              WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2003
2004     }
2005
2006     *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR       |
2007                                 WINED3DPTFILTERCAPS_MAGFPOINT        |
2008                                 WINED3DPTFILTERCAPS_MINFLINEAR       |
2009                                 WINED3DPTFILTERCAPS_MINFPOINT        |
2010                                 WINED3DPTFILTERCAPS_MIPFLINEAR       |
2011                                 WINED3DPTFILTERCAPS_MIPFPOINT        |
2012                                 WINED3DPTFILTERCAPS_LINEAR           |
2013                                 WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
2014                                 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2015                                 WINED3DPTFILTERCAPS_MIPLINEAR        |
2016                                 WINED3DPTFILTERCAPS_MIPNEAREST       |
2017                                 WINED3DPTFILTERCAPS_NEAREST;
2018
2019     if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2020         *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2021                                      WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2022     }
2023
2024     if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2025         *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR       |
2026                                         WINED3DPTFILTERCAPS_MAGFPOINT        |
2027                                         WINED3DPTFILTERCAPS_MINFLINEAR       |
2028                                         WINED3DPTFILTERCAPS_MINFPOINT        |
2029                                         WINED3DPTFILTERCAPS_MIPFLINEAR       |
2030                                         WINED3DPTFILTERCAPS_MIPFPOINT        |
2031                                         WINED3DPTFILTERCAPS_LINEAR           |
2032                                         WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
2033                                         WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2034                                         WINED3DPTFILTERCAPS_MIPLINEAR        |
2035                                         WINED3DPTFILTERCAPS_MIPNEAREST       |
2036                                         WINED3DPTFILTERCAPS_NEAREST;
2037
2038         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2039             *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2040                                             WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2041         }
2042     } else
2043         *pCaps->CubeTextureFilterCaps = 0;
2044
2045     if (GL_SUPPORT(EXT_TEXTURE3D)) {
2046         *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR       |
2047                                           WINED3DPTFILTERCAPS_MAGFPOINT        |
2048                                           WINED3DPTFILTERCAPS_MINFLINEAR       |
2049                                           WINED3DPTFILTERCAPS_MINFPOINT        |
2050                                           WINED3DPTFILTERCAPS_MIPFLINEAR       |
2051                                           WINED3DPTFILTERCAPS_MIPFPOINT        |
2052                                           WINED3DPTFILTERCAPS_LINEAR           |
2053                                           WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
2054                                           WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2055                                           WINED3DPTFILTERCAPS_MIPLINEAR        |
2056                                           WINED3DPTFILTERCAPS_MIPNEAREST       |
2057                                           WINED3DPTFILTERCAPS_NEAREST;
2058     } else
2059         *pCaps->VolumeTextureFilterCaps = 0;
2060
2061     *pCaps->TextureAddressCaps =  D3DPTADDRESSCAPS_INDEPENDENTUV |
2062                                   D3DPTADDRESSCAPS_CLAMP  |
2063                                   D3DPTADDRESSCAPS_WRAP;
2064
2065     if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2066         *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2067     }
2068     if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2069         *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2070     }
2071     if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2072         *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2073     }
2074
2075     if (GL_SUPPORT(EXT_TEXTURE3D)) {
2076         *pCaps->VolumeTextureAddressCaps =  D3DPTADDRESSCAPS_INDEPENDENTUV |
2077                                             D3DPTADDRESSCAPS_CLAMP  |
2078                                             D3DPTADDRESSCAPS_WRAP;
2079         if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2080             *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2081         }
2082         if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2083             *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2084         }
2085         if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2086             *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2087         }
2088     } else
2089         *pCaps->VolumeTextureAddressCaps = 0;
2090
2091     *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2092                        D3DLINECAPS_ZTEST;
2093                       /* FIXME: Add
2094                          D3DLINECAPS_BLEND
2095                          D3DLINECAPS_ALPHACMP
2096                          D3DLINECAPS_FOG */
2097
2098     *pCaps->MaxTextureWidth  = GL_LIMITS(texture_size);
2099     *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2100
2101     if(GL_SUPPORT(EXT_TEXTURE3D))
2102         *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2103     else
2104         *pCaps->MaxVolumeExtent = 0;
2105
2106     *pCaps->MaxTextureRepeat = 32768;
2107     *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2108     *pCaps->MaxVertexW = 1.0;
2109
2110     *pCaps->GuardBandLeft = 0;
2111     *pCaps->GuardBandTop = 0;
2112     *pCaps->GuardBandRight = 0;
2113     *pCaps->GuardBandBottom = 0;
2114
2115     *pCaps->ExtentsAdjust = 0;
2116
2117     *pCaps->StencilCaps =  D3DSTENCILCAPS_DECRSAT |
2118                            D3DSTENCILCAPS_INCRSAT |
2119                            D3DSTENCILCAPS_INVERT  |
2120                            D3DSTENCILCAPS_KEEP    |
2121                            D3DSTENCILCAPS_REPLACE |
2122                            D3DSTENCILCAPS_ZERO;
2123     if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2124       *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR  |
2125                              D3DSTENCILCAPS_INCR;
2126     }
2127     if ( This->dxVersion > 8 &&
2128         ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2129             GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2130         *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2131     }
2132
2133     *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2134
2135     *pCaps->TextureOpCaps =  D3DTEXOPCAPS_ADD         |
2136                              D3DTEXOPCAPS_ADDSIGNED   |
2137                              D3DTEXOPCAPS_ADDSIGNED2X |
2138                              D3DTEXOPCAPS_MODULATE    |
2139                              D3DTEXOPCAPS_MODULATE2X  |
2140                              D3DTEXOPCAPS_MODULATE4X  |
2141                              D3DTEXOPCAPS_SELECTARG1  |
2142                              D3DTEXOPCAPS_SELECTARG2  |
2143                              D3DTEXOPCAPS_DISABLE;
2144
2145     if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2146         GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2147         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2148         *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2149                                 D3DTEXOPCAPS_BLENDTEXTUREALPHA  |
2150                                 D3DTEXOPCAPS_BLENDFACTORALPHA   |
2151                                 D3DTEXOPCAPS_BLENDCURRENTALPHA  |
2152                                 D3DTEXOPCAPS_LERP               |
2153                                 D3DTEXOPCAPS_SUBTRACT;
2154     }
2155     if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2156         *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH             |
2157                                 D3DTEXOPCAPS_MULTIPLYADD            |
2158                                 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2159                                 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2160                                 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2161     }
2162     if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2163         *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2164
2165     if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2166         *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2167                                  D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2168     }
2169     
2170     
2171 #if 0
2172     *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2173                             /* FIXME: Add
2174                             D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 
2175                             D3DTEXOPCAPS_PREMODULATE */
2176 #endif
2177
2178     *pCaps->MaxTextureBlendStages   = GL_LIMITS(texture_stages);
2179     *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2180     *pCaps->MaxUserClipPlanes       = GL_LIMITS(clipplanes);
2181     *pCaps->MaxActiveLights         = GL_LIMITS(lights);
2182
2183
2184
2185 #if 0 /* TODO: Blends support in drawprim */
2186     *pCaps->MaxVertexBlendMatrices      = GL_LIMITS(blends);
2187 #else
2188     *pCaps->MaxVertexBlendMatrices      = 0;
2189 #endif
2190     *pCaps->MaxVertexBlendMatrixIndex   = 1;
2191
2192     *pCaps->MaxAnisotropy   = GL_LIMITS(anisotropy);
2193     *pCaps->MaxPointSize    = GL_LIMITS(pointsize);
2194
2195
2196     *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2197                                    WINED3DVTXPCAPS_MATERIALSOURCE7   |
2198                                    WINED3DVTXPCAPS_POSITIONALLIGHTS  |
2199                                    WINED3DVTXPCAPS_LOCALVIEWER       |
2200                                    WINED3DVTXPCAPS_VERTEXFOG         |
2201                                    WINED3DVTXPCAPS_TEXGEN;
2202                                   /* FIXME: Add 
2203                                      D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2204
2205     *pCaps->MaxPrimitiveCount   = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2206     *pCaps->MaxVertexIndex      = 0xFFFFF;
2207     *pCaps->MaxStreams          = MAX_STREAMS;
2208     *pCaps->MaxStreamStride     = 1024;
2209
2210     if (vs_selected_mode == SHADER_GLSL) {
2211         /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2212            models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2213            vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2214            now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2215         if(This->gl_info.vs_nv_version == VS_VERSION_20)
2216             *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2217         else
2218             *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2219         TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2220     } else if (vs_selected_mode == SHADER_ARB) {
2221         *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2222         TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2223     } else if (vs_selected_mode == SHADER_SW) {
2224         *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2225         TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2226     } else {
2227         *pCaps->VertexShaderVersion  = 0;
2228         TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2229     }
2230
2231     *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2232
2233     if (ps_selected_mode == SHADER_GLSL) {
2234         /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2235            in case of GeforceFX cards. */
2236         if(This->gl_info.ps_nv_version == PS_VERSION_20)
2237             *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2238         else
2239             *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2240         /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2241         *pCaps->PixelShader1xMaxValue = 1.0;
2242         TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2243     } else if (ps_selected_mode == SHADER_ARB) {
2244         *pCaps->PixelShaderVersion    = WINED3DPS_VERSION(1,4);
2245         *pCaps->PixelShader1xMaxValue = 1.0;
2246         TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2247     /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2248     } else if (ps_selected_mode = SHADER_SW) {
2249         *pCaps->PixelShaderVersion    = WINED3DPS_VERSION(3,0);
2250         *pCaps->PixelShader1xMaxValue = 1.0;
2251         TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2252     } else {
2253         *pCaps->PixelShaderVersion    = 0;
2254         *pCaps->PixelShader1xMaxValue = 0.0;
2255         TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2256     }
2257
2258     /* ------------------------------------------------
2259        The following fields apply to d3d9 only
2260        ------------------------------------------------ */
2261     if (This->dxVersion > 8) {
2262         FIXME("Caps support for directx9 is nonexistent at the moment!\n");
2263         *pCaps->DevCaps2                          = 0;
2264         /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES and VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2265         *pCaps->MaxNpatchTessellationLevel        = 0;
2266         *pCaps->MasterAdapterOrdinal              = 0;
2267         *pCaps->AdapterOrdinalInGroup             = 0;
2268         *pCaps->NumberOfAdaptersInGroup           = 1;
2269
2270         if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2271             /* OpenGL supports all formats below, perhaps not always without conversion but it supports them.
2272                Further GLSL doesn't seem to have an official unsigned type as I'm not sure how we handle it
2273                don't advertise it yet. We might need to add some clamping in the shader engine to support it.
2274                TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2275             *pCaps->DeclTypes = D3DDTCAPS_UBYTE4    |
2276                                 D3DDTCAPS_UBYTE4N   |
2277                                 D3DDTCAPS_SHORT2N   |
2278                                 D3DDTCAPS_SHORT4N   |
2279                                 D3DDTCAPS_FLOAT16_2 |
2280                                 D3DDTCAPS_FLOAT16_4;
2281
2282         } else
2283             *pCaps->DeclTypes                         = 0;
2284
2285 #if 0 /* We don't properly support multiple render targets yet, so disable this for now */
2286         if (GL_SUPPORT(ARB_DRAWBUFFERS)) {
2287             *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2288         } else    
2289 #endif
2290             *pCaps->NumSimultaneousRTs = 1;
2291             
2292         *pCaps->StretchRectFilterCaps             = 0;
2293         *pCaps->VertexTextureFilterCaps           = 0;
2294         
2295         if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2296             /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2297                use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2298             *pCaps->VS20Caps.Caps                     = D3DVS20CAPS_PREDICATION;
2299             *pCaps->VS20Caps.DynamicFlowControlDepth  = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2300             *pCaps->VS20Caps.NumTemps                 = max(32, This->gl_info.vs_arb_max_temps);
2301             *pCaps->VS20Caps.StaticFlowControlDepth   = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2302
2303             *pCaps->MaxVShaderInstructionsExecuted    = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2304             *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2305         } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2306             *pCaps->VS20Caps.Caps                     = 0;
2307             *pCaps->VS20Caps.DynamicFlowControlDepth  = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2308             *pCaps->VS20Caps.NumTemps                 = max(12, This->gl_info.vs_arb_max_temps);
2309             *pCaps->VS20Caps.StaticFlowControlDepth   = 1;    
2310
2311             *pCaps->MaxVShaderInstructionsExecuted    = 65535;
2312             *pCaps->MaxVertexShader30InstructionSlots = 0;
2313         } else { /* VS 1.x */
2314             *pCaps->VS20Caps.Caps                     = 0;
2315             *pCaps->VS20Caps.DynamicFlowControlDepth  = 0;
2316             *pCaps->VS20Caps.NumTemps                 = 0;
2317             *pCaps->VS20Caps.StaticFlowControlDepth   = 0;    
2318
2319             *pCaps->MaxVShaderInstructionsExecuted    = 0;
2320             *pCaps->MaxVertexShader30InstructionSlots = 0;        
2321         }
2322
2323         if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2324             /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2325                use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2326             
2327             /* Caps is more or less undocumented on MSDN but it appears to be used for PS20Caps based on results from R9600/FX5900/Geforce6800 cards from Windows */
2328             *pCaps->PS20Caps.Caps                     = D3DPS20CAPS_ARBITRARYSWIZZLE     |
2329                                                         D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2330                                                         D3DPS20CAPS_PREDICATION          |
2331                                                         D3DPS20CAPS_NODEPENDENTREADLIMIT |
2332                                                         D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2333             *pCaps->PS20Caps.DynamicFlowControlDepth  = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2334             *pCaps->PS20Caps.NumTemps                 = max(32, This->gl_info.ps_arb_max_temps);
2335             *pCaps->PS20Caps.StaticFlowControlDepth   = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2336             *pCaps->PS20Caps.NumInstructionSlots      = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2337
2338             *pCaps->MaxPShaderInstructionsExecuted    = 65535;
2339             *pCaps->MaxPixelShader30InstructionSlots  = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2340         } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2341             /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2342             *pCaps->PS20Caps.Caps                     = 0;
2343             *pCaps->PS20Caps.DynamicFlowControlDepth  = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2344             *pCaps->PS20Caps.NumTemps                 = max(12, This->gl_info.ps_arb_max_temps);
2345             *pCaps->PS20Caps.StaticFlowControlDepth   = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2346             *pCaps->PS20Caps.NumInstructionSlots      = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2347
2348             *pCaps->MaxPShaderInstructionsExecuted    = 512; /* Minimum value, a GeforceFX uses 1024 */
2349             *pCaps->MaxPixelShader30InstructionSlots  = 0;
2350         } else { /* PS 1.x */
2351             *pCaps->PS20Caps.Caps                     = 0;
2352             *pCaps->PS20Caps.DynamicFlowControlDepth  = 0;
2353             *pCaps->PS20Caps.NumTemps                 = 0;
2354             *pCaps->PS20Caps.StaticFlowControlDepth   = 0;
2355             *pCaps->PS20Caps.NumInstructionSlots      = 0;
2356
2357             *pCaps->MaxPShaderInstructionsExecuted    = 0;
2358             *pCaps->MaxPixelShader30InstructionSlots  = 0;
2359         }
2360     }
2361
2362     return WINED3D_OK;
2363 }
2364
2365
2366 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2367    and fields being inserted in the middle, a new structure is used in place    */
2368 static HRESULT  WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2369                                            DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2370                                            IUnknown *parent) {
2371
2372     IWineD3DDeviceImpl *object  = NULL;
2373     IWineD3DImpl       *This    = (IWineD3DImpl *)iface;
2374     HDC hDC;
2375     HRESULT temp_result;
2376
2377     /* Validate the adapter number */
2378     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2379         return WINED3DERR_INVALIDCALL;
2380     }
2381
2382     /* Create a WineD3DDevice object */
2383     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2384     *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2385     TRACE("Created WineD3DDevice object @ %p\n", object);
2386     if (NULL == object) {
2387       return WINED3DERR_OUTOFVIDEOMEMORY;
2388     }
2389
2390     /* Set up initial COM information */
2391     object->lpVtbl  = &IWineD3DDevice_Vtbl;
2392     object->ref     = 1;
2393     object->wineD3D = iface;
2394     IWineD3D_AddRef(object->wineD3D);
2395     object->parent  = parent;
2396
2397     /* Set the state up as invalid until the device is fully created */
2398     object->state   = WINED3DERR_DRIVERINTERNALERROR;
2399
2400     TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2401           hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2402
2403     /* Save the creation parameters */
2404     object->createParms.AdapterOrdinal = Adapter;
2405     object->createParms.DeviceType     = DeviceType;
2406     object->createParms.hFocusWindow   = hFocusWindow;
2407     object->createParms.BehaviorFlags  = BehaviourFlags;
2408
2409     /* Initialize other useful values */
2410     object->adapterNo                    = Adapter;
2411     object->devType                      = DeviceType;
2412
2413     TRACE("(%p) : Creating stateblock\n", This);
2414     /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2415     if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2416                                       WINED3DSBT_INIT,
2417                                     (IWineD3DStateBlock **)&object->stateBlock,
2418                                     NULL)  || NULL == object->stateBlock) {   /* Note: No parent needed for initial internal stateblock */
2419         WARN("Failed to create stateblock\n");
2420         goto create_device_error;
2421     }
2422     TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2423     object->updateStateBlock = object->stateBlock;
2424     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2425     /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2426
2427     /* Setup some defaults for creating the implicit swapchain */
2428     ENTER_GL();
2429     /* FIXME: GL info should be per adapter */
2430     IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2431     LEAVE_GL();
2432     select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2433     if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2434         object->shader_backend = &glsl_shader_backend;
2435     } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2436         object->shader_backend = &arb_program_shader_backend;
2437     } else {
2438         object->shader_backend = &none_shader_backend;
2439     }
2440
2441     /* This function should *not* be modifying GL caps
2442      * TODO: move the functionality where it belongs */
2443     select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2444
2445     temp_result = allocate_shader_constants(object->updateStateBlock);
2446     if (WINED3D_OK != temp_result)
2447         return temp_result;
2448
2449     /* set the state of the device to valid */
2450     object->state = WINED3D_OK;
2451
2452     /* Get the initial screen setup for ddraw */
2453     object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2454     object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2455     hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
2456     object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2457     DeleteDC(hDC);
2458
2459     return WINED3D_OK;
2460 create_device_error:
2461
2462     /* Set the device state to error */
2463     object->state = WINED3DERR_DRIVERINTERNALERROR;
2464
2465     if (object->updateStateBlock != NULL) {
2466         IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2467         object->updateStateBlock = NULL;
2468     }
2469     if (object->stateBlock != NULL) {
2470         IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2471         object->stateBlock = NULL;
2472     }
2473     if (object->renderTarget != NULL) {
2474         IWineD3DSurface_Release(object->renderTarget);
2475         object->renderTarget = NULL;
2476     }
2477     if (object->stencilBufferTarget != NULL) {
2478         IWineD3DSurface_Release(object->stencilBufferTarget);
2479         object->stencilBufferTarget = NULL;
2480     }
2481     HeapFree(GetProcessHeap(), 0, object);
2482     *ppReturnedDeviceInterface = NULL;
2483     return WINED3DERR_INVALIDCALL;
2484
2485 }
2486
2487 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2488     IWineD3DImpl *This = (IWineD3DImpl *)iface;
2489     IUnknown_AddRef(This->parent);
2490     *pParent = This->parent;
2491     return WINED3D_OK;
2492 }
2493
2494 /**********************************************************
2495  * IWineD3D VTbl follows
2496  **********************************************************/
2497
2498 const IWineD3DVtbl IWineD3D_Vtbl =
2499 {
2500     /* IUnknown */
2501     IWineD3DImpl_QueryInterface,
2502     IWineD3DImpl_AddRef,
2503     IWineD3DImpl_Release,
2504     /* IWineD3D */
2505     IWineD3DImpl_GetParent,
2506     IWineD3DImpl_GetAdapterCount,
2507     IWineD3DImpl_RegisterSoftwareDevice,
2508     IWineD3DImpl_GetAdapterMonitor,
2509     IWineD3DImpl_GetAdapterModeCount,
2510     IWineD3DImpl_EnumAdapterModes,
2511     IWineD3DImpl_GetAdapterDisplayMode,
2512     IWineD3DImpl_GetAdapterIdentifier,
2513     IWineD3DImpl_CheckDeviceMultiSampleType,
2514     IWineD3DImpl_CheckDepthStencilMatch,
2515     IWineD3DImpl_CheckDeviceType,
2516     IWineD3DImpl_CheckDeviceFormat,
2517     IWineD3DImpl_CheckDeviceFormatConversion,
2518     IWineD3DImpl_GetDeviceCaps,
2519     IWineD3DImpl_CreateDevice
2520 };