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