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