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