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