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