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