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