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