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