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