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