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