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