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