wined3d: Improve GetAdapterMonitor stub.
[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
89        TRACE_(d3d_caps)("Creating Fake GL Context\n");
90
91        ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
92
93        /* Get the display */
94        device_context = GetDC(0);
95        ctx.display = get_display(device_context);
96        ReleaseDC(0, device_context);
97
98        /* Get the X visual */
99        ENTER_GL();
100        if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
101            visual = win_attr.visual;
102        } else {
103            visual = DefaultVisual(ctx.display, DefaultScreen(ctx.display));
104        }
105        template.visualid = XVisualIDFromVisual(visual);
106        ctx.visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
107        if (ctx.visInfo == NULL) {
108            LEAVE_GL();
109            WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
110            failed = TRUE;
111        }
112
113        /* Create a GL context */
114        if (!failed) {
115            ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
116
117            if (ctx.glCtx == NULL) {
118                LEAVE_GL();
119                WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
120                failed = TRUE;
121            }
122        }
123
124        /* Make it the current GL context */
125        if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
126            glXDestroyContext(ctx.display, ctx.glCtx);
127            LEAVE_GL();
128            WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
129            failed = TRUE;
130        }
131
132        /* It worked! Wow... */
133        if (!failed) {
134            gotContext = TRUE;
135            created = TRUE;
136            ret = &ctx;
137        } else {
138            ret = NULL;
139        }
140
141    } else {
142      if (ctx.ref > 0) ret = &ctx;
143    }
144
145    if (NULL != ret) InterlockedIncrement(&ret->ref);
146    return ret;
147 }
148
149 static void WineD3D_ReleaseFakeGLContext(WineD3D_Context* ctx) {
150     /* If we created a dummy context, throw it away */
151     if (NULL != ctx) {
152         if (0 == InterlockedDecrement(&ctx->ref)) {
153             glXMakeCurrent(ctx->display, None, NULL);
154             glXDestroyContext(ctx->display, ctx->glCtx);
155             ctx->display = NULL;
156             ctx->glCtx = NULL;
157             LEAVE_GL();
158         }
159     }
160 }
161
162 /**********************************************************
163  * IUnknown parts follows
164  **********************************************************/
165
166 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
167 {
168     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
169
170     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
171     if (IsEqualGUID(riid, &IID_IUnknown)
172         || IsEqualGUID(riid, &IID_IWineD3DBase)
173         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
174         IUnknown_AddRef(iface);
175         *ppobj = This;
176         return S_OK;
177     }
178     *ppobj = NULL;
179     return E_NOINTERFACE;
180 }
181
182 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
183     IWineD3DImpl *This = (IWineD3DImpl *)iface;
184     ULONG refCount = InterlockedIncrement(&This->ref);
185
186     TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
187     return refCount;
188 }
189
190 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
191     IWineD3DImpl *This = (IWineD3DImpl *)iface;
192     ULONG ref;
193     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
194     ref = InterlockedDecrement(&This->ref);
195     if (ref == 0) {
196         HeapFree(GetProcessHeap(), 0, This);
197     }
198
199     return ref;
200 }
201
202 /* Set the shader type for this device, depending on the given capabilities,
203  * the device type, and the user preferences in wined3d_settings */
204
205 static void select_shader_mode(
206     WineD3D_GL_Info *gl_info,
207     WINED3DDEVTYPE DeviceType,
208     int* ps_selected,
209     int* vs_selected) {
210
211     /* Give priority to user disable/emulation request.
212      * Then respect REF device for software.
213      * Then check capabilities for hardware, and fallback to software */
214
215     if (wined3d_settings.vs_mode == VS_NONE)
216         *vs_selected = SHADER_NONE;
217     else if (DeviceType == WINED3DDEVTYPE_REF || wined3d_settings.vs_mode == VS_SW)
218         *vs_selected = SHADER_SW;
219     else if (gl_info->supported[ARB_SHADING_LANGUAGE_100] && wined3d_settings.glslRequested)
220         *vs_selected = SHADER_GLSL;
221     else if (gl_info->supported[ARB_VERTEX_PROGRAM])
222         *vs_selected = SHADER_ARB;
223     else
224         *vs_selected = SHADER_SW;
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_SHADING_LANGUAGE_100] && 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  * IWineD3D parts follows
241  **********************************************************/
242
243 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info, Display* display) {
244     const char *GL_Extensions    = NULL;
245     const char *GLX_Extensions   = NULL;
246     const char *gl_string        = NULL;
247     const char *gl_string_cursor = NULL;
248     GLint       gl_max;
249     GLfloat     gl_float;
250     Bool        test = 0;
251     int         major, minor;
252     WineD3D_Context *fake_ctx = NULL;
253     BOOL        gotContext    = FALSE;
254     int         i;
255
256     /* Make sure that we've got a context */
257     if (glXGetCurrentContext() == NULL) {
258         /* TODO: CreateFakeGLContext should really take a display as a parameter  */
259         fake_ctx = WineD3D_CreateFakeGLContext();
260         if (NULL != fake_ctx) gotContext = TRUE;
261     } else {
262         gotContext = TRUE;
263     }
264
265     TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
266
267     gl_string = (const char *) glGetString(GL_RENDERER);
268     strcpy(gl_info->gl_renderer, gl_string);
269
270     /* Fill in the GL info retrievable depending on the display */
271     if (NULL != display) {
272         test = glXQueryVersion(display, &major, &minor);
273         gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
274     } else {
275         FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
276     }
277     gl_string = (const char *) glGetString(GL_VENDOR);
278
279     TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
280     if (gl_string != NULL) {
281         /* Fill in the GL vendor */
282         if (strstr(gl_string, "NVIDIA")) {
283             gl_info->gl_vendor = VENDOR_NVIDIA;
284         } else if (strstr(gl_string, "ATI")) {
285             gl_info->gl_vendor = VENDOR_ATI;
286         } else if (strstr(gl_string, "Intel(R)") || 
287                    strstr(gl_info->gl_renderer, "Intel(R)")) {
288             gl_info->gl_vendor = VENDOR_INTEL;
289         } else if (strstr(gl_string, "Mesa")) {
290             gl_info->gl_vendor = VENDOR_MESA;
291         } else {
292             gl_info->gl_vendor = VENDOR_WINE;
293         }
294     } else {
295         gl_info->gl_vendor = VENDOR_WINE;
296     }
297
298
299     TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
300
301     /* Parse the GL_VERSION field into major and minor information */
302     gl_string = (const char *) glGetString(GL_VERSION);
303     if (gl_string != NULL) {
304
305         switch (gl_info->gl_vendor) {
306         case VENDOR_NVIDIA:
307             gl_string_cursor = strstr(gl_string, "NVIDIA");
308             if (!gl_string_cursor) {
309                 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
310                 break;
311             }
312
313             gl_string_cursor = strstr(gl_string_cursor, " ");
314             if (!gl_string_cursor) {
315                 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
316                 break;
317             }
318
319             while (*gl_string_cursor == ' ') {
320                 ++gl_string_cursor;
321             }
322
323             if (!*gl_string_cursor) {
324                 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
325                 break;
326             }
327
328             major = atoi(gl_string_cursor);
329             while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
330                 ++gl_string_cursor;
331             }
332
333             if (*gl_string_cursor++ != '.') {
334                 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
335                 break;
336             }
337
338             minor = atoi(gl_string_cursor);
339             minor = major*100+minor;
340             major = 10;
341
342             break;
343
344         case VENDOR_ATI:
345             major = minor = 0;
346             gl_string_cursor = strchr(gl_string, '-');
347             if (gl_string_cursor) {
348                 int error = 0;
349                 gl_string_cursor++;
350
351                 /* Check if version number is of the form x.y.z */
352                 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
353                     error = 1;
354                 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
355                     error = 1;
356                 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
357                     error = 1;
358                 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
359                     error = 1;
360
361                 /* Mark version number as malformed */
362                 if (error)
363                     gl_string_cursor = 0;
364             }
365
366             if (!gl_string_cursor)
367                 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
368             else {
369                 major = *gl_string_cursor - '0';
370                 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
371             }
372             break;
373
374         case VENDOR_INTEL:
375         case VENDOR_MESA:
376             gl_string_cursor = strstr(gl_string, "Mesa");
377             gl_string_cursor = strstr(gl_string_cursor, " ");
378             while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
379             if (*gl_string_cursor) {
380                 char tmp[16];
381                 int cursor = 0;
382
383                 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
384                     tmp[cursor++] = *gl_string_cursor;
385                     ++gl_string_cursor;
386                 }
387                 tmp[cursor] = 0;
388                 major = atoi(tmp);
389
390                 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
391                 ++gl_string_cursor;
392
393                 cursor = 0;
394                 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
395                     tmp[cursor++] = *gl_string_cursor;
396                     ++gl_string_cursor;
397                 }
398                 tmp[cursor] = 0;
399                 minor = atoi(tmp);
400             }
401             break;
402
403         default:
404             major = 0;
405             minor = 9;
406         }
407         gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
408         TRACE_(d3d_caps)("found GL_VERSION  (%s)->%i.%i->(0x%08lx)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
409
410         /* Fill in the renderer information */
411
412         switch (gl_info->gl_vendor) {
413         case VENDOR_NVIDIA:
414             if (strstr(gl_info->gl_renderer, "GeForce4 Ti")) {
415                 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
416             } else if (strstr(gl_info->gl_renderer, "GeForceFX")) {
417                 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5900ULTRA;
418             } else if (strstr(gl_info->gl_renderer, "Quadro FX 3000")) {
419                 gl_info->gl_card = CARD_NVIDIA_QUADROFX_3000;
420             } else if (strstr(gl_info->gl_renderer, "GeForce 6800")) {
421                 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800ULTRA;
422             } else if (strstr(gl_info->gl_renderer, "Quadro FX 4000")) {
423                 gl_info->gl_card = CARD_NVIDIA_QUADROFX_4000;
424             } else if (strstr(gl_info->gl_renderer, "GeForce 7800")) {
425                 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800ULTRA;
426             } else {
427                 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
428             }
429             break;
430
431         case VENDOR_ATI:
432             if (strstr(gl_info->gl_renderer, "RADEON 9800 PRO")) {
433                 gl_info->gl_card = CARD_ATI_RADEON_9800PRO;
434             } else if (strstr(gl_info->gl_renderer, "RADEON 9700 PRO")) {
435                 gl_info->gl_card = CARD_ATI_RADEON_9700PRO;
436             } else {
437                 gl_info->gl_card = CARD_ATI_RADEON_8500;
438             }
439             break;
440
441         case VENDOR_INTEL:
442             if (strstr(gl_info->gl_renderer, "915GM")) {
443                 gl_info->gl_card = CARD_INTEL_I915GM;
444             } else if (strstr(gl_info->gl_renderer, "915G")) {
445                 gl_info->gl_card = CARD_INTEL_I915G;
446             } else if (strstr(gl_info->gl_renderer, "865G")) {
447                 gl_info->gl_card = CARD_INTEL_I865G;
448             } else if (strstr(gl_info->gl_renderer, "855G")) {
449                 gl_info->gl_card = CARD_INTEL_I855G;
450             } else if (strstr(gl_info->gl_renderer, "830G")) {
451                 gl_info->gl_card = CARD_INTEL_I830G;
452             } else {
453               gl_info->gl_card = CARD_INTEL_I915G;
454             }
455             break;
456
457         default:
458             gl_info->gl_card = CARD_WINE;
459             break;
460         }
461     } else {
462         FIXME("get version string returned null\n");
463     }
464
465     TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
466
467     /*
468      * Initialize openGL extension related variables
469      *  with Default values
470      */
471     memset(&gl_info->supported, 0, sizeof(gl_info->supported));
472     gl_info->max_textures       = 1;
473     gl_info->max_texture_stages = 1;
474     gl_info->max_samplers       = 1;
475     gl_info->max_sampler_stages = 1;
476     gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
477     gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
478     gl_info->vs_nv_version  = VS_VERSION_NOT_SUPPORTED;
479     gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
480
481     /* Now work out what GL support this card really has */
482 #define USE_GL_FUNC(type, pfn) gl_info->pfn = NULL;
483     GL_EXT_FUNCS_GEN;
484 #undef USE_GL_FUNC
485
486     /* Retrieve opengl defaults */
487     glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
488     gl_info->max_clipplanes = min(D3DMAXUSERCLIPPLANES, gl_max);
489     TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
490
491     glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
492     gl_info->max_lights = gl_max;
493     TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
494
495     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
496     gl_info->max_texture_size = gl_max;
497     TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
498
499     glGetFloatv(GL_POINT_SIZE_RANGE, &gl_float);
500     gl_info->max_pointsize = gl_float;
501     TRACE_(d3d_caps)("Maximum point size support - max texture size=%f\n", gl_float);
502
503     /* Parse the gl supported features, in theory enabling parts of our code appropriately */
504     GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
505     TRACE_(d3d_caps)("GL_Extensions reported:\n");
506
507     if (NULL == GL_Extensions) {
508         ERR("   GL_Extensions returns NULL\n");
509     } else {
510         while (*GL_Extensions != 0x00) {
511             const char *Start = GL_Extensions;
512             char        ThisExtn[256];
513
514             memset(ThisExtn, 0x00, sizeof(ThisExtn));
515             while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
516                 GL_Extensions++;
517             }
518             memcpy(ThisExtn, Start, (GL_Extensions - Start));
519             TRACE_(d3d_caps)("- %s\n", ThisExtn);
520
521             /**
522              * ARB
523              */
524             if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
525                 gl_info->ps_arb_version = PS_VERSION_11;
526                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
527                 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
528                 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
529                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
530                 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
531             } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
532                 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
533                 gl_info->supported[ARB_IMAGING] = TRUE;
534             } else if (strcmp(ThisExtn, "GL_ARB_shading_language_100") == 0) {
535                 TRACE_(d3d_caps)(" FOUND: GL Shading Language v100 support\n");
536                 gl_info->supported[ARB_SHADING_LANGUAGE_100] = TRUE;
537             } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
538                 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
539                 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
540             } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
541                 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
542                 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
543                 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
544                 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
545                 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
546                 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
547             } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
548                 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
549                 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
550                 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
551                 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
552             } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
553                 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
554                 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
555             } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
556                 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
557                 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
558             } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
559                 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
560                 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
561             } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
562                 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
563                 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
564             } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
565                 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
566                 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
567             } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
568                 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
569                 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
570             } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
571                 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
572                 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
573             } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
574                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
575                 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
576             } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
577                 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
578                 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
579             } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
580                 gl_info->vs_arb_version = VS_VERSION_11;
581                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
582                 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
583             } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
584                 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
585                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
586                 gl_info->max_blends = gl_max;
587                 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
588             } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
589                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
590                 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
591             } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
592                 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
593                 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
594             } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
595                 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
596                 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
597             /**
598              * EXT
599              */
600             } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
601                 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
602                 gl_info->supported[EXT_FOG_COORD] = TRUE;
603             } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
604                 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
605                 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
606             } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
607                 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
608                 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
609             } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
610                 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
611                 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
612             } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
613                 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
614                 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
615             } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
616                 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
617                 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
618             } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
619                 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
620                 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
621             } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
622                 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
623                 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
624             } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
625                 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
626                 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
627             } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
628                 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
629                 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
630             } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
631                 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
632                 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
633             } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
634                 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
635                 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
636                 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
637                 gl_info->max_anisotropy = gl_max;
638             } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
639                 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
640                 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
641             } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
642                 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
643                 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
644             } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
645                 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
646                 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
647
648             /**
649              * NVIDIA
650              */
651             } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
652                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
653                 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
654             } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
655                 gl_info->ps_nv_version = PS_VERSION_11;
656                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
657             } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
658                 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
659                 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
660                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
661                 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
662             } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
663                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
664                 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
665             } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
666                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
667                 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
668             } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
669                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
670                 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
671             } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
672                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
673                 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
674             } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
675                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
676                 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
677             } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
678                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
679                 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
680             } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
681                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
682                 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
683             } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
684                 gl_info->vs_nv_version = max(gl_info->vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program1_1")) ? VS_VERSION_11 : VS_VERSION_10);
685                 gl_info->vs_nv_version = max(gl_info->vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program2"))   ? VS_VERSION_20 : VS_VERSION_10);
686                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
687                 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
688
689             /**
690              * ATI
691              */
692             /** TODO */
693             } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
694                 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
695                 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
696             } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
697                 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
698                 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
699             } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
700                 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
701                 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
702             } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
703                 gl_info->vs_ati_version = VS_VERSION_11;
704                 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
705                 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
706             }
707
708
709             if (*GL_Extensions == ' ') GL_Extensions++;
710         }
711     }
712     gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
713
714     /* Load all the lookup tables
715     TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
716     minLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_WRAP;
717     maxLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_MIRRORONCE;
718
719     minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
720     maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
721
722
723     for (i = 0; i < MAX_LOOKUPS; i++) {
724         stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
725     }
726
727     stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_WRAP   - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
728     stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_CLAMP  - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
729     stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
730              gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
731     stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
732              gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
733     stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
734              gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
735     stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
736              gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
737
738     stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE        - minLookup[WINELOOKUP_MAGFILTER]]  = GL_NEAREST;
739     stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT       - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
740     stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR      - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
741     stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
742              gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
743
744
745     minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE]     = GL_LINEAR;
746     minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT]    = GL_LINEAR;
747     minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR]   = GL_LINEAR;
748     minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE]    = GL_NEAREST;
749     minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT]   = GL_NEAREST_MIPMAP_NEAREST;
750     minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR]  = GL_NEAREST_MIPMAP_LINEAR;
751     minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE]   = GL_LINEAR;
752     minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT]  = GL_LINEAR_MIPMAP_NEAREST;
753     minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
754     minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE]   = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
755     GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
756     minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT]  = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
757     minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
758
759 /* TODO: config lookups */
760
761
762 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
763     GL_EXT_FUNCS_GEN;
764 #undef USE_GL_FUNC
765
766     if (display != NULL) {
767         GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
768         TRACE_(d3d_caps)("GLX_Extensions reported:\n");
769
770         if (NULL == GLX_Extensions) {
771             ERR("   GLX_Extensions returns NULL\n");
772         } else {
773             while (*GLX_Extensions != 0x00) {
774                 const char *Start = GLX_Extensions;
775                 char ThisExtn[256];
776
777                 memset(ThisExtn, 0x00, sizeof(ThisExtn));
778                 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
779                     GLX_Extensions++;
780                 }
781                 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
782                 TRACE_(d3d_caps)("- %s\n", ThisExtn);
783                 if (*GLX_Extensions == ' ') GLX_Extensions++;
784             }
785         }
786     }
787
788 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
789     GLX_EXT_FUNCS_GEN;
790 #undef USE_GL_FUNC
791
792     /* If we created a dummy context, throw it away */
793     if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
794
795     /* Only save the values obtained when a display is provided */
796     if (fake_ctx == NULL) {
797         return TRUE;
798     } else {
799         return FALSE;
800     }
801 }
802
803 /**********************************************************
804  * IWineD3D implementation follows
805  **********************************************************/
806
807 static UINT     WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
808     IWineD3DImpl *This = (IWineD3DImpl *)iface;
809
810     /* FIXME: Set to one for now to imply the display */
811     TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
812     return 1;
813 }
814
815 static HRESULT  WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
816     IWineD3DImpl *This = (IWineD3DImpl *)iface;
817     FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
818     return WINED3D_OK;
819 }
820
821 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
822     IWineD3DImpl *This = (IWineD3DImpl *)iface;
823     POINT pt = { -1, -1 };
824
825     if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
826         return NULL;
827     }
828
829     FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
830     return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
831 }
832
833 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
834      of the same bpp but different resolutions                                  */
835
836 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
837 static UINT     WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
838     IWineD3DImpl *This = (IWineD3DImpl *)iface;
839     TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
840
841     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
842         return 0;
843     }
844
845     if (Adapter == 0) { /* Display */
846         int i = 0;
847         int j = 0;
848 #if !defined( DEBUG_SINGLE_MODE )
849         DEVMODEW DevModeW;
850
851         /* Work out the current screen bpp */
852         HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
853         int bpp = GetDeviceCaps(hdc, BITSPIXEL);
854         DeleteDC(hdc);
855
856         while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
857             j++;
858             switch (Format)
859             {
860             case D3DFMT_UNKNOWN:
861                    i++;
862                    break;
863             case D3DFMT_X8R8G8B8:
864             case D3DFMT_A8R8G8B8:
865                    if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
866                    if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
867                    break;
868             case D3DFMT_X1R5G5B5:
869             case D3DFMT_A1R5G5B5:
870             case D3DFMT_R5G6B5:
871                    if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
872                    break;
873             default:
874                    /* Skip other modes as they do not match requested format */
875                    break;
876             }
877         }
878 #else
879         i = 1;
880         j = 1;
881 #endif
882         TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
883         return i;
884     } else {
885         FIXME_(d3d_caps)("Adapter not primary display\n");
886     }
887     return 0;
888 }
889
890 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
891 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
892     IWineD3DImpl *This = (IWineD3DImpl *)iface;
893     TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
894
895     /* Validate the parameters as much as possible */
896     if (NULL == pMode ||
897         Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
898         Mode    >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
899         return WINED3DERR_INVALIDCALL;
900     }
901
902     if (Adapter == 0) { /* Display */
903 #if !defined( DEBUG_SINGLE_MODE )
904         DEVMODEW DevModeW;
905         int ModeIdx = 0;
906
907         /* Work out the current screen bpp */
908         HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
909         int bpp = GetDeviceCaps(hdc, BITSPIXEL);
910         DeleteDC(hdc);
911
912         /* If we are filtering to a specific format, then need to skip all unrelated
913            modes, but if mode is irrelevant, then we can use the index directly      */
914         if (Format == D3DFMT_UNKNOWN)
915         {
916             ModeIdx = Mode;
917         } else {
918             int i = 0;
919             int j = 0;
920             DEVMODEW DevModeWtmp;
921
922
923             while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
924                 j++;
925                 switch (Format)
926                 {
927                 case D3DFMT_UNKNOWN:
928                        i++;
929                        break;
930                 case D3DFMT_X8R8G8B8:
931                 case D3DFMT_A8R8G8B8:
932                        if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
933                        if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
934                        break;
935                 case D3DFMT_X1R5G5B5:
936                 case D3DFMT_A1R5G5B5:
937                 case D3DFMT_R5G6B5:
938                        if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
939                        break;
940                 default:
941                        /* Skip other modes as they do not match requested format */
942                        break;
943                 }
944             }
945             ModeIdx = j;
946         }
947
948         /* Now get the display mode via the calculated index */
949         if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
950         {
951             pMode->Width        = DevModeW.dmPelsWidth;
952             pMode->Height       = DevModeW.dmPelsHeight;
953             bpp                 = min(DevModeW.dmBitsPerPel, bpp);
954             pMode->RefreshRate  = D3DADAPTER_DEFAULT;
955             if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
956             {
957                 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
958             }
959
960             if (Format == D3DFMT_UNKNOWN)
961             {
962                 switch (bpp) {
963                 case  8: pMode->Format = D3DFMT_R3G3B2;   break;
964                 case 16: pMode->Format = D3DFMT_R5G6B5;   break;
965                 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
966                 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
967                 default: pMode->Format = D3DFMT_UNKNOWN;
968                 }
969             } else {
970                 pMode->Format = Format;
971             }
972         }
973         else
974         {
975             TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
976             return WINED3DERR_INVALIDCALL;
977         }
978
979 #else
980         /* Return one setting of the format requested */
981         if (Mode > 0) return WINED3DERR_INVALIDCALL;
982         pMode->Width        = 800;
983         pMode->Height       = 600;
984         pMode->RefreshRate  = D3DADAPTER_DEFAULT;
985         pMode->Format       = (Format == D3DFMT_UNKNOWN) ? D3DFMT_A8R8G8B8 : Format;
986         bpp = 32;
987 #endif
988         TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
989                  pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
990
991     } else {
992         FIXME_(d3d_caps)("Adapter not primary display\n");
993     }
994
995     return WINED3D_OK;
996 }
997
998 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
999     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1000     TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1001
1002     if (NULL == pMode ||
1003         Adapter >= IWineD3D_GetAdapterCount(iface)) {
1004         return WINED3DERR_INVALIDCALL;
1005     }
1006
1007     if (Adapter == 0) { /* Display */
1008         int bpp = 0;
1009         DEVMODEW DevModeW;
1010
1011         EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1012         pMode->Width        = DevModeW.dmPelsWidth;
1013         pMode->Height       = DevModeW.dmPelsHeight;
1014         bpp                 = DevModeW.dmBitsPerPel;
1015         pMode->RefreshRate  = D3DADAPTER_DEFAULT;
1016         if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1017         {
1018             pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1019         }
1020
1021         switch (bpp) {
1022         case  8: pMode->Format       = D3DFMT_R3G3B2;   break;
1023         case 16: pMode->Format       = D3DFMT_R5G6B5;   break;
1024         case 24: pMode->Format       = D3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1025         case 32: pMode->Format       = D3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1026         default: pMode->Format       = D3DFMT_UNKNOWN;
1027         }
1028
1029     } else {
1030         FIXME_(d3d_caps)("Adapter not primary display\n");
1031     }
1032
1033     TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1034           pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1035     return WINED3D_OK;
1036 }
1037
1038 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1039     Display *display;
1040     HDC     device_context;
1041     /* only works with one adapter at the moment... */
1042
1043     /* Get the display */
1044     device_context = GetDC(0);
1045     display = get_display(device_context);
1046     ReleaseDC(0, device_context);
1047     return display;
1048 }
1049
1050 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1051    and fields being inserted in the middle, a new structure is used in place    */
1052 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1053                                                    WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1054     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1055
1056     TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1057
1058     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1059         return WINED3DERR_INVALIDCALL;
1060     }
1061
1062     if (Adapter == 0) { /* Display - only device supported for now */
1063
1064         BOOL isGLInfoValid = This->isGLInfoValid;
1065
1066         /* FillGLCaps updates gl_info, but we only want to store and
1067            reuse the values once we have a context which is valid. Values from
1068            a temporary context may differ from the final ones                 */
1069         if (isGLInfoValid == FALSE) {
1070             WineD3D_Context *fake_ctx = NULL;
1071             if (glXGetCurrentContext() == NULL) fake_ctx = WineD3D_CreateFakeGLContext();
1072             /* If we don't know the device settings, go query them now */
1073             isGLInfoValid = IWineD3DImpl_FillGLCaps(&This->gl_info, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1074             if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
1075         }
1076
1077         /* If it worked, return the information requested */
1078         if (isGLInfoValid) {
1079           TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1080           strcpy(pIdentifier->Driver, "Display");
1081           strcpy(pIdentifier->Description, "Direct3D HAL");
1082
1083           /* Note dx8 doesn't supply a DeviceName */
1084           if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1085           /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1086           pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1087           pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1088           *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1089           *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1090           *(pIdentifier->SubSysId) = 0;
1091           *(pIdentifier->Revision) = 0;
1092
1093         } else {
1094
1095           /* If it failed, return dummy values from an NVidia driver */
1096           WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1097           strcpy(pIdentifier->Driver, "Display");
1098           strcpy(pIdentifier->Description, "Direct3D HAL");
1099           if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1100           /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1101           pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1102           /* 71.74 is a current Linux Nvidia driver version */
1103           pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1104           *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1105           *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4600;
1106           *(pIdentifier->SubSysId) = 0;
1107           *(pIdentifier->Revision) = 0;
1108         }
1109
1110         /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1111         if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1112             *(pIdentifier->WHQLLevel) = 0;
1113         } else {
1114             *(pIdentifier->WHQLLevel) = 1;
1115         }
1116
1117     } else {
1118         FIXME_(d3d_caps)("Adapter not primary display\n");
1119     }
1120
1121     return WINED3D_OK;
1122 }
1123
1124 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1125 #if 0 /* This code performs a strict test between the format and the current X11  buffer depth, which may give the best performance */
1126   int gl_test;
1127   int rb, gb, bb, ab, type, buf_sz;
1128
1129   gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE,   &rb);
1130   gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
1131   gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE,  &bb);
1132   gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
1133   gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
1134   gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1135
1136   switch (Format) {
1137   case WINED3DFMT_X8R8G8B8:
1138   case WINED3DFMT_R8G8B8:
1139     if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1140     break;
1141   case WINED3DFMT_A8R8G8B8:
1142     if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1143     break;
1144   case WINED3DFMT_A2R10G10B10:
1145     if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1146     break;
1147   case WINED3DFMT_X1R5G5B5:
1148     if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1149     break;
1150   case WINED3DFMT_A1R5G5B5:
1151     if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1152     break;
1153   case WINED3DFMT_X4R4G4B4:
1154     if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1155     break;
1156   case WINED3DFMT_R5G6B5:
1157     if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1158     break;
1159   case WINED3DFMT_R3G3B2:
1160     if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1161     break;
1162   case WINED3DFMT_A8P8:
1163     if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1164     break;
1165   case WINED3DFMT_P8:
1166     if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1167     break;
1168   default:
1169     ERR("unsupported format %s\n", debug_d3dformat(Format));
1170     break;
1171   }
1172   return FALSE;
1173 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1174 switch (Format) {
1175   case WINED3DFMT_X8R8G8B8:
1176   case WINED3DFMT_R8G8B8:
1177   case WINED3DFMT_A8R8G8B8:
1178   case WINED3DFMT_A2R10G10B10:
1179   case WINED3DFMT_X1R5G5B5:
1180   case WINED3DFMT_A1R5G5B5:
1181   case WINED3DFMT_R5G6B5:
1182   case WINED3DFMT_R3G3B2:
1183   case WINED3DFMT_A8P8:
1184   case WINED3DFMT_P8:
1185 return TRUE;
1186   default:
1187     ERR("unsupported format %s\n", debug_d3dformat(Format));
1188     break;
1189   }
1190 return FALSE;
1191 #endif
1192 }
1193
1194 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1195 #if 0/* This code performs a strict test between the format and the current X11  buffer depth, which may give the best performance */
1196   int gl_test;
1197   int db, sb;
1198
1199   gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
1200   gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
1201
1202   switch (Format) {
1203   case WINED3DFMT_D16:
1204   case WINED3DFMT_D16_LOCKABLE:
1205     if (16 == db) return TRUE;
1206     break;
1207   case WINED3DFMT_D32:
1208     if (32 == db) return TRUE;
1209     break;
1210   case WINED3DFMT_D15S1:
1211     if (15 == db) return TRUE;
1212     break;
1213   case WINED3DFMT_D24S8:
1214     if (24 == db && 8 == sb) return TRUE;
1215     break;
1216   case WINED3DFMT_D24FS8:
1217     if (24 == db && 8 == sb) return TRUE;
1218     break;
1219   case WINED3DFMT_D24X8:
1220     if (24 == db) return TRUE;
1221     break;
1222   case WINED3DFMT_D24X4S4:
1223     if (24 == db && 4 == sb) return TRUE;
1224     break;
1225   case WINED3DFMT_D32F_LOCKABLE:
1226     if (32 == db) return TRUE;
1227     break;
1228   default:
1229     ERR("unsupported format %s\n", debug_d3dformat(Format));
1230     break;
1231   }
1232   return FALSE;
1233 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1234   switch (Format) {
1235   case WINED3DFMT_D16:
1236   case WINED3DFMT_D16_LOCKABLE:
1237   case WINED3DFMT_D32:
1238   case WINED3DFMT_D15S1:
1239   case WINED3DFMT_D24S8:
1240   case WINED3DFMT_D24FS8:
1241   case WINED3DFMT_D24X8:
1242   case WINED3DFMT_D24X4S4:
1243   case WINED3DFMT_D32F_LOCKABLE:
1244     return TRUE;
1245   default:
1246     ERR("unsupported format %s\n", debug_d3dformat(Format));
1247     break;
1248   }
1249   return FALSE;
1250 #endif
1251 }
1252
1253 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1254                                                    WINED3DFORMAT AdapterFormat,
1255                                                    WINED3DFORMAT RenderTargetFormat,
1256                                                    WINED3DFORMAT DepthStencilFormat) {
1257     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1258     HRESULT hr = WINED3DERR_NOTAVAILABLE;
1259     WineD3D_Context* ctx = NULL;
1260     GLXFBConfig* cfgs = NULL;
1261     int nCfgs = 0;
1262     int it;
1263
1264     WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1265            This, Adapter,
1266            DeviceType, debug_d3ddevicetype(DeviceType),
1267            AdapterFormat, debug_d3dformat(AdapterFormat),
1268            RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1269            DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1270
1271     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1272         TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1273         return WINED3DERR_INVALIDCALL;
1274     }
1275     /* TODO: use the real context if it's available */
1276     ctx = WineD3D_CreateFakeGLContext();
1277     if(NULL !=  ctx) {
1278         cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1279     } else {
1280         TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
1281     }
1282
1283     if (NULL != cfgs) {
1284         for (it = 0; it < nCfgs; ++it) {
1285             if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
1286                 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
1287                     hr = WINED3D_OK;
1288                     break ;
1289                 }
1290             }
1291         }
1292         XFree(cfgs);
1293         cfgs = NULL;
1294     } else {
1295         /* If there's a corrent context then we cannot create a fake one so pass everything */
1296         hr = WINED3D_OK;
1297     }
1298
1299     if (ctx != NULL)
1300         WineD3D_ReleaseFakeGLContext(ctx);
1301
1302     if (hr != WINED3D_OK)
1303         TRACE_(d3d_caps)("Failed to match stencil format to device\b");
1304
1305     TRACE_(d3d_caps)("(%p) : Returning %lx\n", This, hr);
1306     return hr;
1307 }
1308
1309 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, 
1310                                                        WINED3DFORMAT SurfaceFormat,
1311                                                        BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD*   pQualityLevels) {
1312
1313     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1314     TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1315           This,
1316           Adapter,
1317           DeviceType, debug_d3ddevicetype(DeviceType),
1318           SurfaceFormat, debug_d3dformat(SurfaceFormat),
1319           Windowed,
1320           MultiSampleType,
1321           pQualityLevels);
1322
1323     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1324         return WINED3DERR_INVALIDCALL;
1325     }
1326
1327     if (pQualityLevels != NULL) {
1328         static int s_single_shot = 0;
1329         if (!s_single_shot) {
1330             FIXME("Quality levels unsupported at present\n");
1331             s_single_shot = 1;
1332         }
1333         *pQualityLevels = 1; /* Guess at a value! */
1334     }
1335
1336     if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1337     return WINED3DERR_NOTAVAILABLE;
1338 }
1339
1340 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1341                                             WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1342
1343     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1344     TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1345           This,
1346           Adapter,
1347           CheckType, debug_d3ddevicetype(CheckType),
1348           DisplayFormat, debug_d3dformat(DisplayFormat),
1349           BackBufferFormat, debug_d3dformat(BackBufferFormat),
1350           Windowed);
1351
1352     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1353         return WINED3DERR_INVALIDCALL;
1354     }
1355
1356     {
1357       GLXFBConfig* cfgs = NULL;
1358       int nCfgs = 0;
1359       int it;
1360       HRESULT hr = WINED3DERR_NOTAVAILABLE;
1361
1362       WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1363       if (NULL != ctx) {
1364         cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1365         for (it = 0; it < nCfgs; ++it) {
1366             if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1367                 hr = WINED3D_OK;
1368                 break ;
1369             }
1370         }
1371         XFree(cfgs);
1372
1373         WineD3D_ReleaseFakeGLContext(ctx);
1374         return hr;
1375       }
1376     }
1377
1378     return WINED3DERR_NOTAVAILABLE;
1379 }
1380
1381 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, 
1382                                               WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1383     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1384     TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
1385           This,
1386           Adapter,
1387           DeviceType, debug_d3ddevicetype(DeviceType),
1388           AdapterFormat, debug_d3dformat(AdapterFormat),
1389           Usage, debug_d3dusage(Usage),
1390           RType, debug_d3dresourcetype(RType),
1391           CheckFormat, debug_d3dformat(CheckFormat));
1392
1393     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1394         return WINED3DERR_INVALIDCALL;
1395     }
1396
1397     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1398         switch (CheckFormat) {
1399         case D3DFMT_DXT1:
1400         case D3DFMT_DXT2:
1401         case D3DFMT_DXT3:
1402         case D3DFMT_DXT4:
1403         case D3DFMT_DXT5:
1404           TRACE_(d3d_caps)("[OK]\n");
1405           return WINED3D_OK;
1406         default:
1407             break; /* Avoid compiler warnings */
1408         }
1409     }
1410
1411     switch (CheckFormat) {
1412     /*****
1413      * check supported using GL_SUPPORT
1414      */
1415     case D3DFMT_DXT1:
1416     case D3DFMT_DXT2:
1417     case D3DFMT_DXT3:
1418     case D3DFMT_DXT4:
1419     case D3DFMT_DXT5:
1420
1421     /*****
1422      *  supported
1423      */
1424       /*case D3DFMT_R5G6B5: */
1425       /*case D3DFMT_X1R5G5B5:*/
1426       /*case D3DFMT_A1R5G5B5: */
1427       /*case D3DFMT_A4R4G4B4:*/
1428
1429     /*****
1430      * unsupported
1431      */
1432
1433       /* color buffer */
1434       /*case D3DFMT_X8R8G8B8:*/
1435     case D3DFMT_A8R3G3B2:
1436
1437       /* Paletted */
1438     case D3DFMT_P8:
1439     case D3DFMT_A8P8:
1440
1441       /* Luminance */
1442     case D3DFMT_L8:
1443     case D3DFMT_A8L8:
1444     case D3DFMT_A4L4:
1445
1446       /* Bump */
1447 #if 0
1448     case D3DFMT_V8U8:
1449     case D3DFMT_V16U16:
1450 #endif
1451     case D3DFMT_L6V5U5:
1452     case D3DFMT_X8L8V8U8:
1453     case D3DFMT_Q8W8V8U8:
1454     case D3DFMT_W11V11U10:
1455
1456     /****
1457      * currently hard to support
1458      */
1459     case D3DFMT_UYVY:
1460     case D3DFMT_YUY2:
1461
1462       /* Since we do not support these formats right now, don't pretend to. */
1463       TRACE_(d3d_caps)("[FAILED]\n");
1464       return WINED3DERR_NOTAVAILABLE;
1465     default:
1466       break;
1467     }
1468
1469     TRACE_(d3d_caps)("[OK]\n");
1470     return WINED3D_OK;
1471 }
1472
1473 static HRESULT  WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1474                                                           WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1475     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1476
1477     FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1478           This,
1479           Adapter,
1480           DeviceType, debug_d3ddevicetype(DeviceType),
1481           SourceFormat, debug_d3dformat(SourceFormat),
1482           TargetFormat, debug_d3dformat(TargetFormat));
1483     return WINED3D_OK;
1484 }
1485
1486 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1487       subset of a D3DCAPS9 structure. However, it has to come via a void *
1488       as the d3d8 interface cannot import the d3d9 header                  */
1489 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1490
1491     IWineD3DImpl    *This = (IWineD3DImpl *)iface;
1492
1493     TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1494
1495     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1496         return WINED3DERR_INVALIDCALL;
1497     }
1498
1499     /* FIXME: both the gl_info and the shader_mode should be made per adapter */
1500
1501     /* If we don't know the device settings, go query them now */
1502     if (This->isGLInfoValid == FALSE) {
1503         /* use the desktop window to fill gl caps */
1504         BOOL rc = IWineD3DImpl_FillGLCaps(&This->gl_info, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1505
1506         /* We are running off a real context, save the values */
1507         if (rc) This->isGLInfoValid = TRUE;
1508     }
1509     select_shader_mode(&This->gl_info, DeviceType,
1510         &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
1511
1512     /* ------------------------------------------------
1513        The following fields apply to both d3d8 and d3d9
1514        ------------------------------------------------ */
1515     *pCaps->DeviceType              = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF;  /* Not quite true, but use h/w supported by opengl I suppose */
1516     *pCaps->AdapterOrdinal          = Adapter;
1517
1518     *pCaps->Caps                    = 0;
1519     *pCaps->Caps2                   = D3DCAPS2_CANRENDERWINDOWED;
1520     *pCaps->Caps3                   = WINED3DDEVCAPS_HWTRANSFORMANDLIGHT;
1521     *pCaps->PresentationIntervals   = D3DPRESENT_INTERVAL_IMMEDIATE;
1522
1523     *pCaps->CursorCaps              = 0;
1524
1525
1526     *pCaps->DevCaps                 = WINED3DDEVCAPS_FLOATTLVERTEX       |
1527                                       WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1528                                       WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1529                                       WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1530                                       WINED3DDEVCAPS_DRAWPRIMTLVERTEX    |
1531                                       WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1532                                       WINED3DDEVCAPS_EXECUTEVIDEOMEMORY  |
1533                                       WINED3DDEVCAPS_PUREDEVICE          |
1534                                       WINED3DDEVCAPS_HWRASTERIZATION     |
1535                                       WINED3DDEVCAPS_TEXTUREVIDEOMEMORY  |
1536                                       WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1537                                       WINED3DDEVCAPS_CANRENDERAFTERFLIP  |
1538                                       WINED3DDEVCAPS_DRAWPRIMITIVES2     |
1539                                       WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1540
1541     *pCaps->PrimitiveMiscCaps       = D3DPMISCCAPS_CULLCCW               |
1542                                       D3DPMISCCAPS_CULLCW                |
1543                                       D3DPMISCCAPS_COLORWRITEENABLE      |
1544                                       D3DPMISCCAPS_CLIPTLVERTS           |
1545                                       D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1546                                       D3DPMISCCAPS_MASKZ;
1547                                /*NOT: D3DPMISCCAPS_TSSARGTEMP*/
1548
1549     *pCaps->RasterCaps              = WINED3DPRASTERCAPS_DITHER    |
1550                                       WINED3DPRASTERCAPS_PAT       |
1551                                       WINED3DPRASTERCAPS_WFOG      |
1552                                       WINED3DPRASTERCAPS_ZFOG      |
1553                                       WINED3DPRASTERCAPS_FOGVERTEX |
1554                                       WINED3DPRASTERCAPS_FOGTABLE  |
1555                                       WINED3DPRASTERCAPS_FOGRANGE  |
1556                                       WINED3DPRASTERCAPS_STIPPLE   |
1557                                       WINED3DPRASTERCAPS_SUBPIXEL  |
1558                                       WINED3DPRASTERCAPS_ZTEST;
1559
1560     if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1561       *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY    |
1562                             WINED3DPRASTERCAPS_ZBIAS         |
1563                             WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1564     }
1565                         /* FIXME Add:
1566                            WINED3DPRASTERCAPS_COLORPERSPECTIVE
1567                            WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1568                            WINED3DPRASTERCAPS_ANTIALIASEDGES
1569                            WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1570                            WINED3DPRASTERCAPS_WBUFFER */
1571
1572     *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS       |
1573                        D3DPCMPCAPS_EQUAL        |
1574                        D3DPCMPCAPS_GREATER      |
1575                        D3DPCMPCAPS_GREATEREQUAL |
1576                        D3DPCMPCAPS_LESS         |
1577                        D3DPCMPCAPS_LESSEQUAL    |
1578                        D3DPCMPCAPS_NEVER        |
1579                        D3DPCMPCAPS_NOTEQUAL;
1580
1581     *pCaps->SrcBlendCaps  = 0xFFFFFFFF;   /*FIXME: Tidy up later */
1582     *pCaps->DestBlendCaps = 0xFFFFFFFF;   /*FIXME: Tidy up later */
1583     *pCaps->AlphaCmpCaps  = 0xFFFFFFFF;   /*FIXME: Tidy up later */
1584
1585     *pCaps->ShadeCaps     = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1586                             WINED3DPSHADECAPS_COLORGOURAUDRGB    |
1587                             WINED3DPSHADECAPS_ALPHAFLATBLEND     |
1588                             WINED3DPSHADECAPS_ALPHAGOURAUDBLEND  |
1589                             WINED3DPSHADECAPS_COLORFLATRGB       |
1590                             WINED3DPSHADECAPS_FOGFLAT            |
1591                             WINED3DPSHADECAPS_FOGGOURAUD         |
1592                             WINED3DPSHADECAPS_SPECULARFLATRGB;
1593
1594     *pCaps->TextureCaps =  WINED3DPTEXTURECAPS_ALPHA              |
1595                            WINED3DPTEXTURECAPS_ALPHAPALETTE       |
1596                            WINED3DPTEXTURECAPS_BORDER             |
1597                            WINED3DPTEXTURECAPS_VOLUMEMAP          |
1598                            WINED3DPTEXTURECAPS_MIPMAP             |
1599                            WINED3DPTEXTURECAPS_PROJECTED          |
1600                            WINED3DPTEXTURECAPS_PERSPECTIVE        |
1601                            WINED3DPTEXTURECAPS_VOLUMEMAP_POW2     |
1602                            WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1603
1604     if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1605         *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP     |
1606                              WINED3DPTEXTURECAPS_MIPCUBEMAP    |
1607                              WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1608
1609     }
1610
1611     *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR       |
1612                                 WINED3DPTFILTERCAPS_MAGFPOINT        |
1613                                 WINED3DPTFILTERCAPS_MINFLINEAR       |
1614                                 WINED3DPTFILTERCAPS_MINFPOINT        |
1615                                 WINED3DPTFILTERCAPS_MIPFLINEAR       |
1616                                 WINED3DPTFILTERCAPS_MIPFPOINT        |
1617                                 WINED3DPTFILTERCAPS_LINEAR           |
1618                                 WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
1619                                 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1620                                 WINED3DPTFILTERCAPS_MIPLINEAR        |
1621                                 WINED3DPTFILTERCAPS_MIPNEAREST       |
1622                                 WINED3DPTFILTERCAPS_NEAREST;
1623
1624     *pCaps->CubeTextureFilterCaps = 0;
1625     *pCaps->VolumeTextureFilterCaps = 0;
1626
1627     *pCaps->TextureAddressCaps =  D3DPTADDRESSCAPS_BORDER |
1628                                   D3DPTADDRESSCAPS_CLAMP  |
1629                                   D3DPTADDRESSCAPS_WRAP;
1630
1631     if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
1632         *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
1633     }
1634     if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
1635         *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
1636     }
1637     if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
1638         *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
1639     }
1640
1641     *pCaps->VolumeTextureAddressCaps = 0;
1642
1643     *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
1644                        D3DLINECAPS_ZTEST;
1645                       /* FIXME: Add
1646                          D3DLINECAPS_BLEND
1647                          D3DLINECAPS_ALPHACMP
1648                          D3DLINECAPS_FOG */
1649
1650     *pCaps->MaxTextureWidth  = GL_LIMITS(texture_size);
1651     *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
1652
1653     *pCaps->MaxVolumeExtent = 0;
1654
1655     *pCaps->MaxTextureRepeat = 32768;
1656     *pCaps->MaxTextureAspectRatio = 32768;
1657     *pCaps->MaxVertexW = 1.0;
1658
1659     *pCaps->GuardBandLeft = 0;
1660     *pCaps->GuardBandTop = 0;
1661     *pCaps->GuardBandRight = 0;
1662     *pCaps->GuardBandBottom = 0;
1663
1664     *pCaps->ExtentsAdjust = 0;
1665
1666     *pCaps->StencilCaps =  D3DSTENCILCAPS_DECRSAT |
1667                            D3DSTENCILCAPS_INCRSAT |
1668                            D3DSTENCILCAPS_INVERT  |
1669                            D3DSTENCILCAPS_KEEP    |
1670                            D3DSTENCILCAPS_REPLACE |
1671                            D3DSTENCILCAPS_ZERO;
1672     if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
1673       *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR  |
1674                              D3DSTENCILCAPS_INCR;
1675     }
1676     if ( This->dxVersion > 8 &&
1677         ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
1678             GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
1679         *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
1680     }
1681
1682     *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
1683
1684     *pCaps->TextureOpCaps =  D3DTEXOPCAPS_ADD         |
1685                              D3DTEXOPCAPS_ADDSIGNED   |
1686                              D3DTEXOPCAPS_ADDSIGNED2X |
1687                              D3DTEXOPCAPS_MODULATE    |
1688                              D3DTEXOPCAPS_MODULATE2X  |
1689                              D3DTEXOPCAPS_MODULATE4X  |
1690                              D3DTEXOPCAPS_SELECTARG1  |
1691                              D3DTEXOPCAPS_SELECTARG2  |
1692                              D3DTEXOPCAPS_DISABLE;
1693 #if defined(GL_VERSION_1_3)
1694     *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3 |
1695                              D3DTEXOPCAPS_SUBTRACT;
1696 #endif
1697     if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
1698         GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
1699         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1700         *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
1701                                 D3DTEXOPCAPS_BLENDTEXTUREALPHA  |
1702                                 D3DTEXOPCAPS_BLENDFACTORALPHA   |
1703                                 D3DTEXOPCAPS_BLENDCURRENTALPHA  |
1704                                 D3DTEXOPCAPS_LERP;
1705     }
1706     if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1707         *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH             |
1708                                 D3DTEXOPCAPS_MULTIPLYADD            |
1709                                 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
1710                                 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
1711                                 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
1712     }
1713
1714 #if 0
1715     *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
1716                             /* FIXME: Add
1717                             D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 
1718                             D3DTEXOPCAPS_PREMODULATE */
1719 #endif
1720
1721     *pCaps->MaxTextureBlendStages   = GL_LIMITS(texture_stages);
1722     *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
1723     *pCaps->MaxUserClipPlanes       = GL_LIMITS(clipplanes);
1724     *pCaps->MaxActiveLights         = GL_LIMITS(lights);
1725
1726
1727
1728 #if 0 /* TODO: Blends support in drawprim */
1729     *pCaps->MaxVertexBlendMatrices      = GL_LIMITS(blends);
1730 #else
1731     *pCaps->MaxVertexBlendMatrices      = 0;
1732 #endif
1733     *pCaps->MaxVertexBlendMatrixIndex   = 1;
1734
1735     *pCaps->MaxAnisotropy   = GL_LIMITS(anisotropy);
1736     *pCaps->MaxPointSize    = GL_LIMITS(pointsize);
1737
1738
1739     *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
1740                                    WINED3DVTXPCAPS_MATERIALSOURCE7   |
1741                                    WINED3DVTXPCAPS_POSITIONALLIGHTS  |
1742                                    WINED3DVTXPCAPS_LOCALVIEWER       |
1743                                    WINED3DVTXPCAPS_VERTEXFOG         |
1744                                    WINED3DVTXPCAPS_TEXGEN;
1745                                   /* FIXME: Add 
1746                                      D3DVTXPCAPS_TWEENING */
1747
1748     *pCaps->MaxPrimitiveCount   = 0xFFFFFFFF;
1749     *pCaps->MaxVertexIndex      = 0xFFFFFFFF;
1750     *pCaps->MaxStreams          = MAX_STREAMS;
1751     *pCaps->MaxStreamStride     = 1024;
1752
1753     /* FIXME: the shader mode should be per adapter */
1754     if (wined3d_settings.vs_selected_mode == SHADER_GLSL) {
1755         *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
1756         TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
1757     } else if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
1758         *pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
1759         TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
1760     } else if (wined3d_settings.vs_selected_mode == SHADER_SW) {
1761         *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
1762         TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
1763     } else {
1764         *pCaps->VertexShaderVersion  = 0;
1765         TRACE_(d3d_caps)("Vertex shader functionality not available\n");
1766     }
1767
1768     if (This->gl_info.gl_vendor == VENDOR_MESA || This->gl_info.gl_vendor == VENDOR_WINE) {
1769         *pCaps->MaxVertexShaderConst = 95;
1770     } else {
1771         *pCaps->MaxVertexShaderConst = WINED3D_VSHADER_MAX_CONSTANTS;
1772     }
1773
1774     /* FIXME: the shader ode should be per adapter */
1775     if (wined3d_settings.ps_selected_mode == SHADER_GLSL) {
1776         *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
1777         /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
1778         *pCaps->PixelShader1xMaxValue = 1.0;
1779         TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
1780     } else if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
1781         *pCaps->PixelShaderVersion    = D3DPS_VERSION(1,4);
1782         *pCaps->PixelShader1xMaxValue = 1.0;
1783         TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
1784     /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
1785     } else if (wined3d_settings.ps_selected_mode = SHADER_SW) {
1786         *pCaps->PixelShaderVersion    = D3DPS_VERSION(3,0);
1787         *pCaps->PixelShader1xMaxValue = 1.0;
1788         TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
1789     } else {
1790         *pCaps->PixelShaderVersion    = 0;
1791         *pCaps->PixelShader1xMaxValue = 0.0;
1792         TRACE_(d3d_caps)("Pixel shader functionality not available\n");
1793     }
1794
1795     /* ------------------------------------------------
1796        The following fields apply to d3d9 only
1797        ------------------------------------------------ */
1798     if (This->dxVersion > 8) {
1799         GLint max_buffers = 1;
1800         FIXME("Caps support for directx9 is nonexistent at the moment!\n");
1801         *pCaps->DevCaps2                          = 0;
1802         /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES */
1803         *pCaps->MaxNpatchTessellationLevel        = 0;
1804         *pCaps->MasterAdapterOrdinal              = 0;
1805         *pCaps->AdapterOrdinalInGroup             = 0;
1806         *pCaps->NumberOfAdaptersInGroup           = 1;
1807         *pCaps->DeclTypes                         = 0;
1808 #if 0 /*FIXME: Simultaneous render targets*/
1809         GL_MAX_DRAW_BUFFERS_ATI 0x00008824
1810         if (GL_SUPPORT(GL_MAX_DRAW_BUFFERS_ATI)) {
1811             ENTER_GL();
1812             glEnable(GL_MAX_DRAW_BUFFERS_ATI);
1813             glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI, &max_buffers);
1814             glDisable(GL_MAX_DRAW_BUFFERS_ATI);
1815             LEAVE_GL();
1816         }
1817 #endif
1818         *pCaps->NumSimultaneousRTs                = max_buffers;
1819         *pCaps->StretchRectFilterCaps             = 0;
1820         *pCaps->VS20Caps.Caps                     = 0;
1821         *pCaps->PS20Caps.Caps                     = 0;
1822         *pCaps->VertexTextureFilterCaps           = 0;
1823         *pCaps->MaxVShaderInstructionsExecuted    = 0;
1824         *pCaps->MaxPShaderInstructionsExecuted    = 0;
1825         *pCaps->MaxVertexShader30InstructionSlots = 0;
1826         *pCaps->MaxPixelShader30InstructionSlots  = 0;
1827     }
1828
1829     return WINED3D_OK;
1830 }
1831
1832
1833 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
1834    and fields being inserted in the middle, a new structure is used in place    */
1835 static HRESULT  WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
1836                                            DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
1837                                            IUnknown *parent) {
1838
1839     IWineD3DDeviceImpl *object  = NULL;
1840     IWineD3DImpl       *This    = (IWineD3DImpl *)iface;
1841     HDC hDC;
1842
1843     /* Validate the adapter number */
1844     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1845         return WINED3DERR_INVALIDCALL;
1846     }
1847
1848     /* Create a WineD3DDevice object */
1849     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
1850     *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
1851     TRACE("Created WineD3DDevice object @ %p\n", object);
1852     if (NULL == object) {
1853       return WINED3DERR_OUTOFVIDEOMEMORY;
1854     }
1855
1856     /* Set up initial COM information */
1857     object->lpVtbl  = &IWineD3DDevice_Vtbl;
1858     object->ref     = 1;
1859     object->wineD3D = iface;
1860     IWineD3D_AddRef(object->wineD3D);
1861     object->parent  = parent;
1862
1863     /* Set the state up as invalid until the device is fully created */
1864     object->state   = WINED3DERR_DRIVERINTERNALERROR;
1865
1866     TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, RetDevInt: %p)\n", This, Adapter, DeviceType,
1867           hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
1868
1869     /* Save the creation parameters */
1870     object->createParms.AdapterOrdinal = Adapter;
1871     object->createParms.DeviceType     = DeviceType;
1872     object->createParms.hFocusWindow   = hFocusWindow;
1873     object->createParms.BehaviorFlags  = BehaviourFlags;
1874
1875     /* Initialize other useful values */
1876     object->adapterNo                    = Adapter;
1877     object->devType                      = DeviceType;
1878
1879     TRACE("(%p) : Creating stateblock\n", This);
1880     /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
1881     if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
1882                                       WINED3DSBT_INIT,
1883                                     (IWineD3DStateBlock **)&object->stateBlock,
1884                                     NULL)  || NULL == object->stateBlock) {   /* Note: No parent needed for initial internal stateblock */
1885         WARN("Failed to create stateblock\n");
1886         goto create_device_error;
1887     }
1888     TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
1889     object->updateStateBlock = object->stateBlock;
1890     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
1891     /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
1892
1893     /* Setup some defaults for creating the implicit swapchain */
1894     ENTER_GL();
1895     /* FIXME: both of those should be made per adapter */
1896     IWineD3DImpl_FillGLCaps(&This->gl_info, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1897     LEAVE_GL();
1898     select_shader_mode(&This->gl_info, DeviceType,
1899         &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
1900
1901     /* set the state of the device to valid */
1902     object->state = WINED3D_OK;
1903
1904     /* Get the initial screen setup for ddraw */
1905     object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
1906     object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
1907     hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
1908     object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
1909     DeleteDC(hDC);
1910
1911     return WINED3D_OK;
1912 create_device_error:
1913
1914     /* Set the device state to error */
1915     object->state = WINED3DERR_DRIVERINTERNALERROR;
1916
1917     if (object->updateStateBlock != NULL) {
1918         IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
1919         object->updateStateBlock = NULL;
1920     }
1921     if (object->stateBlock != NULL) {
1922         IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
1923         object->stateBlock = NULL;
1924     }
1925     if (object->renderTarget != NULL) {
1926         IWineD3DSurface_Release(object->renderTarget);
1927         object->renderTarget = NULL;
1928     }
1929     if (object->stencilBufferTarget != NULL) {
1930         IWineD3DSurface_Release(object->stencilBufferTarget);
1931         object->stencilBufferTarget = NULL;
1932     }
1933     if (object->stencilBufferTarget != NULL) {
1934         IWineD3DSurface_Release(object->stencilBufferTarget);
1935         object->stencilBufferTarget = NULL;
1936     }
1937     HeapFree(GetProcessHeap(), 0, object);
1938     *ppReturnedDeviceInterface = NULL;
1939     return WINED3DERR_INVALIDCALL;
1940
1941 }
1942
1943 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
1944     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1945     IUnknown_AddRef(This->parent);
1946     *pParent = This->parent;
1947     return WINED3D_OK;
1948 }
1949
1950 /**********************************************************
1951  * IWineD3D VTbl follows
1952  **********************************************************/
1953
1954 const IWineD3DVtbl IWineD3D_Vtbl =
1955 {
1956     /* IUnknown */
1957     IWineD3DImpl_QueryInterface,
1958     IWineD3DImpl_AddRef,
1959     IWineD3DImpl_Release,
1960     /* IWineD3D */
1961     IWineD3DImpl_GetParent,
1962     IWineD3DImpl_GetAdapterCount,
1963     IWineD3DImpl_RegisterSoftwareDevice,
1964     IWineD3DImpl_GetAdapterMonitor,
1965     IWineD3DImpl_GetAdapterModeCount,
1966     IWineD3DImpl_EnumAdapterModes,
1967     IWineD3DImpl_GetAdapterDisplayMode,
1968     IWineD3DImpl_GetAdapterIdentifier,
1969     IWineD3DImpl_CheckDeviceMultiSampleType,
1970     IWineD3DImpl_CheckDepthStencilMatch,
1971     IWineD3DImpl_CheckDeviceType,
1972     IWineD3DImpl_CheckDeviceFormat,
1973     IWineD3DImpl_CheckDeviceFormatConversion,
1974     IWineD3DImpl_GetDeviceCaps,
1975     IWineD3DImpl_CreateDevice
1976 };