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