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