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