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