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