Rename _D3DCAPS9.MaxPixelShaderValue to the correct
[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* pCapsIn) {
1165
1166     IWineD3DImpl    *This = (IWineD3DImpl *)iface;
1167     BOOL             gotContext  = FALSE;
1168     GLint            gl_tex_size = 0;    
1169     WineD3D_Context *fake_ctx = NULL;
1170     D3DCAPS9        *pCaps = (D3DCAPS9 *)pCapsIn;
1171
1172     TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1173
1174     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1175         return D3DERR_INVALIDCALL;
1176     }
1177
1178     /* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
1179        ie there is no GL Context - Get a default rendering context to enable the 
1180        function query some info from GL                                           */    
1181     if (glXGetCurrentContext() == NULL) {
1182         fake_ctx = WineD3D_CreateFakeGLContext();
1183         if (NULL != fake_ctx) gotContext = TRUE;
1184     } else {
1185         gotContext = TRUE;
1186     }
1187
1188     if (gotContext == FALSE) {
1189
1190         FIXME_(d3d_caps)("GetDeviceCaps called but no GL Context - Returning dummy values\n");
1191         gl_tex_size=65535;
1192         pCaps->MaxTextureBlendStages = 2;
1193         pCaps->MaxSimultaneousTextures = 2;
1194         pCaps->MaxUserClipPlanes = 8;
1195         pCaps->MaxActiveLights = 8;
1196         pCaps->MaxVertexBlendMatrices = 0;
1197         pCaps->MaxVertexBlendMatrixIndex = 1;
1198         pCaps->MaxAnisotropy = 0;
1199         pCaps->MaxPointSize = 255.0;
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     pCaps->DevCaps = D3DDEVCAPS_DRAWPRIMTLVERTEX    | 
1226                      D3DDEVCAPS_HWTRANSFORMANDLIGHT |
1227                      D3DDEVCAPS_PUREDEVICE | D3DDEVCAPS_HWRASTERIZATION;
1228
1229     pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLCCW               | 
1230                                D3DPMISCCAPS_CULLCW                | 
1231                                D3DPMISCCAPS_COLORWRITEENABLE      |
1232                                D3DPMISCCAPS_CLIPTLVERTS           |
1233                                D3DPMISCCAPS_CLIPPLANESCALEDPOINTS | 
1234                                D3DPMISCCAPS_MASKZ; 
1235                                /*NOT: D3DPMISCCAPS_TSSARGTEMP*/
1236
1237     pCaps->RasterCaps = D3DPRASTERCAPS_DITHER   | 
1238                         D3DPRASTERCAPS_PAT      | 
1239                         D3DPRASTERCAPS_WFOG |
1240                         D3DPRASTERCAPS_ZFOG |
1241                         D3DPRASTERCAPS_FOGVERTEX |
1242                         D3DPRASTERCAPS_FOGTABLE  |
1243                         D3DPRASTERCAPS_FOGRANGE;
1244
1245     if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1246       pCaps->RasterCaps |= D3DPRASTERCAPS_ANISOTROPY;
1247     }
1248                         /* FIXME Add:
1249                            D3DPRASTERCAPS_MIPMAPLODBIAS
1250                            D3DPRASTERCAPS_ZBIAS
1251                            D3DPRASTERCAPS_COLORPERSPECTIVE
1252                            D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1253                            D3DPRASTERCAPS_ANTIALIASEDGES
1254                            D3DPRASTERCAPS_ZBUFFERLESSHSR
1255                            D3DPRASTERCAPS_WBUFFER */
1256
1257     pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS       | 
1258                       D3DPCMPCAPS_EQUAL        | 
1259                       D3DPCMPCAPS_GREATER      | 
1260                       D3DPCMPCAPS_GREATEREQUAL |
1261                       D3DPCMPCAPS_LESS         | 
1262                       D3DPCMPCAPS_LESSEQUAL    | 
1263                       D3DPCMPCAPS_NEVER        |
1264                       D3DPCMPCAPS_NOTEQUAL;
1265
1266     pCaps->SrcBlendCaps  = 0xFFFFFFFF;   /*FIXME: Tidy up later */
1267     pCaps->DestBlendCaps = 0xFFFFFFFF;   /*FIXME: Tidy up later */
1268     pCaps->AlphaCmpCaps  = 0xFFFFFFFF;   /*FIXME: Tidy up later */
1269
1270     pCaps->ShadeCaps = D3DPSHADECAPS_SPECULARGOURAUDRGB | 
1271                        D3DPSHADECAPS_COLORGOURAUDRGB;
1272
1273     pCaps->TextureCaps =  D3DPTEXTURECAPS_ALPHA        | 
1274                           D3DPTEXTURECAPS_ALPHAPALETTE | 
1275                           D3DPTEXTURECAPS_POW2         | 
1276                           D3DPTEXTURECAPS_VOLUMEMAP    | 
1277                           D3DPTEXTURECAPS_MIPMAP       |
1278                           D3DPTEXTURECAPS_PROJECTED;
1279
1280     if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1281       pCaps->TextureCaps |= D3DPTEXTURECAPS_CUBEMAP      | 
1282                             D3DPTEXTURECAPS_MIPCUBEMAP   | 
1283                             D3DPTEXTURECAPS_CUBEMAP_POW2;
1284     }
1285
1286     pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MAGFLINEAR | 
1287                                D3DPTFILTERCAPS_MAGFPOINT  | 
1288                                D3DPTFILTERCAPS_MINFLINEAR | 
1289                                D3DPTFILTERCAPS_MINFPOINT  |
1290                                D3DPTFILTERCAPS_MIPFLINEAR | 
1291                                D3DPTFILTERCAPS_MIPFPOINT;
1292
1293     pCaps->CubeTextureFilterCaps = 0;
1294     pCaps->VolumeTextureFilterCaps = 0;
1295
1296     pCaps->TextureAddressCaps =  D3DPTADDRESSCAPS_BORDER | 
1297                                  D3DPTADDRESSCAPS_CLAMP  | 
1298                                  D3DPTADDRESSCAPS_WRAP;
1299
1300     if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
1301       pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
1302     }
1303     if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
1304       pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
1305     }
1306     if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
1307       pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
1308     }
1309
1310     pCaps->VolumeTextureAddressCaps = 0;
1311
1312     pCaps->LineCaps = D3DLINECAPS_TEXTURE | 
1313                       D3DLINECAPS_ZTEST;
1314                       /* FIXME: Add 
1315                          D3DLINECAPS_BLEND
1316                          D3DLINECAPS_ALPHACMP
1317                          D3DLINECAPS_FOG */
1318
1319     pCaps->MaxTextureWidth = gl_tex_size;
1320     pCaps->MaxTextureHeight = gl_tex_size;
1321
1322     pCaps->MaxVolumeExtent = 0;
1323
1324     pCaps->MaxTextureRepeat = 32768;
1325     pCaps->MaxTextureAspectRatio = 32768;
1326     pCaps->MaxVertexW = 1.0;
1327
1328     pCaps->GuardBandLeft = 0;
1329     pCaps->GuardBandTop = 0;
1330     pCaps->GuardBandRight = 0;
1331     pCaps->GuardBandBottom = 0;
1332
1333     pCaps->ExtentsAdjust = 0;
1334
1335     pCaps->StencilCaps =  D3DSTENCILCAPS_DECRSAT | 
1336                           D3DSTENCILCAPS_INCRSAT | 
1337                           D3DSTENCILCAPS_INVERT  | 
1338                           D3DSTENCILCAPS_KEEP    | 
1339                           D3DSTENCILCAPS_REPLACE | 
1340                           D3DSTENCILCAPS_ZERO;
1341     if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
1342       pCaps->StencilCaps |= D3DSTENCILCAPS_DECR    | 
1343                             D3DSTENCILCAPS_INCR;
1344     }
1345
1346     pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
1347
1348     pCaps->TextureOpCaps =  D3DTEXOPCAPS_ADD         | 
1349                             D3DTEXOPCAPS_ADDSIGNED   | 
1350                             D3DTEXOPCAPS_ADDSIGNED2X |
1351                             D3DTEXOPCAPS_MODULATE    | 
1352                             D3DTEXOPCAPS_MODULATE2X  | 
1353                             D3DTEXOPCAPS_MODULATE4X  |
1354                             D3DTEXOPCAPS_SELECTARG1  | 
1355                             D3DTEXOPCAPS_SELECTARG2  | 
1356                             D3DTEXOPCAPS_DISABLE;
1357 #if defined(GL_VERSION_1_3)
1358     pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3 | 
1359                             D3DTEXOPCAPS_SUBTRACT;
1360 #endif
1361     if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) || 
1362         GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) || 
1363         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1364       pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
1365                               D3DTEXOPCAPS_BLENDTEXTUREALPHA | 
1366                               D3DTEXOPCAPS_BLENDFACTORALPHA  |
1367                               D3DTEXOPCAPS_BLENDCURRENTALPHA |
1368                               D3DTEXOPCAPS_LERP;
1369     }
1370     if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1371       pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH | 
1372                               D3DTEXOPCAPS_MULTIPLYADD |
1373                               D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
1374                               D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
1375                               D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
1376     }
1377     
1378 #if 0
1379     pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
1380                             /* FIXME: Add 
1381                               D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 
1382                               D3DTEXOPCAPS_PREMODULATE */
1383 #endif
1384
1385     if (gotContext) {
1386         GLint gl_max;
1387         GLfloat gl_float;
1388 #if defined(GL_VERSION_1_3)
1389         glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max);
1390 #else
1391         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1392 #endif
1393         TRACE_(d3d_caps)("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max);
1394         pCaps->MaxTextureBlendStages = min(8, gl_max);
1395         pCaps->MaxSimultaneousTextures = min(8, gl_max);
1396
1397         glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1398         pCaps->MaxUserClipPlanes = min(D3DMAXUSERCLIPPLANES, gl_max);
1399         TRACE_(d3d_caps)("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", pCaps->MaxUserClipPlanes);
1400
1401         glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1402         pCaps->MaxActiveLights = gl_max;
1403         TRACE_(d3d_caps)("GLCaps: GL_MAX_LIGHTS=%ld\n", pCaps->MaxActiveLights);
1404
1405         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
1406            glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1407            pCaps->MaxVertexBlendMatrices = gl_max;
1408            pCaps->MaxVertexBlendMatrixIndex = 1;
1409         } else {
1410            pCaps->MaxVertexBlendMatrices = 0;
1411            pCaps->MaxVertexBlendMatrixIndex = 1;
1412         }
1413
1414         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1415           glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1416           pCaps->MaxAnisotropy = gl_max;
1417         } else {
1418           pCaps->MaxAnisotropy = 0;
1419         }
1420
1421         glGetFloatv(GL_POINT_SIZE_RANGE, &gl_float);
1422         pCaps->MaxPointSize = gl_float;
1423     }
1424
1425     pCaps->VertexProcessingCaps = D3DVTXPCAPS_DIRECTIONALLIGHTS | 
1426                                   D3DVTXPCAPS_MATERIALSOURCE7   | 
1427                                   D3DVTXPCAPS_POSITIONALLIGHTS  | 
1428                                   D3DVTXPCAPS_LOCALVIEWER |
1429                                   D3DVTXPCAPS_TEXGEN;
1430                                   /* FIXME: Add 
1431                                      D3DVTXPCAPS_TWEENING */
1432
1433     pCaps->MaxPrimitiveCount = 0xFFFFFFFF;
1434     pCaps->MaxVertexIndex = 0xFFFFFFFF;
1435     pCaps->MaxStreams = MAX_STREAMS;
1436     pCaps->MaxStreamStride = 1024;
1437
1438     if (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) || (vs_mode == VS_SW) || (DeviceType == D3DDEVTYPE_REF)) {
1439       pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
1440       
1441       if (This->gl_info.gl_vendor == VENDOR_MESA || 
1442           This->gl_info.gl_vendor == VENDOR_WINE) {
1443         pCaps->MaxVertexShaderConst = 95;
1444       } else {
1445         pCaps->MaxVertexShaderConst = WINED3D_VSHADER_MAX_CONSTANTS;
1446       }
1447     } else {
1448       pCaps->VertexShaderVersion = 0;
1449       pCaps->MaxVertexShaderConst = 0;
1450     }
1451
1452     if ((ps_mode == PS_HW) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && (DeviceType != D3DDEVTYPE_REF)) {
1453         pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
1454         pCaps->PixelShader1xMaxValue = 1.0;
1455     } else {
1456         pCaps->PixelShaderVersion = 0;
1457         pCaps->PixelShader1xMaxValue = 0.0;
1458     }
1459
1460     /* ------------------------------------------------
1461        The following fields apply to d3d9 only
1462        ------------------------------------------------ */
1463     if (This->dxVersion > 8) {
1464         FIXME("Caps support for directx9 is nonexistent at the moment!\n");
1465         pCaps->DevCaps2 = 0;
1466         pCaps->MaxNpatchTessellationLevel = 0;
1467         pCaps->MasterAdapterOrdinal = 0;
1468         pCaps->AdapterOrdinalInGroup = 0;
1469         pCaps->NumberOfAdaptersInGroup = 1;
1470         pCaps->DeclTypes = 0;
1471         pCaps->NumSimultaneousRTs = 0;
1472         pCaps->StretchRectFilterCaps = 0;
1473         pCaps->VS20Caps.Caps = 0;
1474         pCaps->PS20Caps.Caps = 0;
1475         pCaps->VertexTextureFilterCaps = 0;
1476         pCaps->MaxVShaderInstructionsExecuted = 0;
1477         pCaps->MaxPShaderInstructionsExecuted = 0;
1478         pCaps->MaxVertexShader30InstructionSlots = 0;
1479         pCaps->MaxPixelShader30InstructionSlots = 0;
1480     }
1481
1482     /* If we created a dummy context, throw it away */
1483     if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
1484     return D3D_OK;
1485 }
1486
1487 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
1488    and fields being inserted in the middle, a new structure is used in place    */
1489 HRESULT  WINAPI  IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow,
1490                                            DWORD BehaviourFlags, WINED3DPRESENT_PARAMETERS* pPresentationParameters,
1491                                            IWineD3DDevice** ppReturnedDeviceInterface, IUnknown *parent, D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget) {
1492
1493     HWND                whichHWND;
1494     HDC                 hDc;
1495     IWineD3DDeviceImpl *object  = NULL;
1496     IWineD3DImpl       *This    = (IWineD3DImpl *)iface;
1497     int                 num;
1498     XVisualInfo         template;
1499     HRESULT             res;
1500
1501     /* Validate the adapter number */
1502     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1503         return D3DERR_INVALIDCALL;
1504     }
1505
1506     /* Create a WineD3DDevice object */
1507     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
1508     *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
1509     TRACE("Created WineD3DDevice object @ %p \n", object);
1510     if (NULL == object) {
1511       return D3DERR_OUTOFVIDEOMEMORY;
1512     }
1513
1514     /* Set up initial COM information */
1515     object->lpVtbl  = &IWineD3DDevice_Vtbl;
1516     object->ref     = 1;
1517     object->wineD3D = iface;
1518     IWineD3D_AddRef(object->wineD3D);
1519     object->parent  = parent;
1520     
1521     TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This, Adapter, DeviceType,
1522           hFocusWindow, BehaviourFlags, pPresentationParameters, ppReturnedDeviceInterface);
1523     TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This, 
1524           *(pPresentationParameters->AutoDepthStencilFormat), debug_d3dformat(*(pPresentationParameters->AutoDepthStencilFormat)),
1525           *(pPresentationParameters->BackBufferFormat), debug_d3dformat(*(pPresentationParameters->BackBufferFormat)));
1526
1527     /* Save the creation parameters */
1528     object->createParms.AdapterOrdinal = Adapter;
1529     object->createParms.DeviceType     = DeviceType;
1530     object->createParms.hFocusWindow   = hFocusWindow;
1531     object->createParms.BehaviorFlags  = BehaviourFlags;
1532
1533     /* Initialize other useful values */
1534     object->presentParms.BackBufferCount = 1; /* Opengl only supports one? */
1535     object->adapterNo                    = Adapter;
1536     object->devType                      = DeviceType;
1537
1538     /* Setup hwnd we are using, plus which display this equates to */
1539     whichHWND = *(pPresentationParameters->hDeviceWindow);
1540     if (!whichHWND) {
1541         whichHWND = hFocusWindow;
1542     }
1543     object->win_handle = whichHWND;
1544     object->win        = (Window)GetPropA( whichHWND, "__wine_x11_whole_window" );
1545     hDc                = GetDC(whichHWND);
1546     object->display    = get_display(hDc);
1547     ReleaseDC(whichHWND, hDc);
1548
1549     /* FIXME: Use for dx8 code eventually too! */
1550     /* Deliberately no indentation here, as this if will be removed when dx8 support merged in */
1551     if (This->dxVersion > 8) {   
1552
1553     /* Create a context based off the properties of the existing visual */
1554     /*   Note the visual is chosen as the window is created and the glcontext cannot
1555          use different properties after that point in time. FIXME: How to handle when requested format 
1556          doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1557          it chooses is identical to the one already being used!                                        */
1558     /* FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat */
1559     ENTER_GL();
1560     template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1561     object->visInfo   = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1562     if (NULL == object->visInfo) {
1563         ERR("cannot really get XVisual\n"); 
1564         LEAVE_GL();
1565         return D3DERR_NOTAVAILABLE;
1566     }
1567     object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1568     if (NULL == object->glCtx) {
1569         ERR("cannot create glxContext\n"); 
1570         LEAVE_GL();
1571         return D3DERR_NOTAVAILABLE;
1572     }
1573     LEAVE_GL();
1574
1575     if (object->glCtx == NULL) {
1576         ERR("Error in context creation !\n");
1577         return D3DERR_INVALIDCALL;
1578     } else {
1579         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1580                 whichHWND, object->glCtx, object->win, object->visInfo);
1581     }
1582
1583     /* If not windowed, need to go fullscreen, and resize the HWND to the appropriate  */
1584     /*        dimensions                                                               */
1585     if (!*(pPresentationParameters->Windowed)) {
1586
1587         DEVMODEW devmode;
1588         HDC      hdc;
1589         int      bpp = 0;
1590
1591         /* Get info on the current display setup */
1592         hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1593         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1594         DeleteDC(hdc);
1595
1596         /* Change the display settings */
1597         memset(&devmode, 0, sizeof(DEVMODEW));
1598         devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; 
1599         devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp;   /*Stupid XVidMode cannot change bpp D3DFmtGetBpp(object, pPresentationParameters->BackBufferFormat);*/
1600         devmode.dmPelsWidth  = *(pPresentationParameters->BackBufferWidth);
1601         devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1602         MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1603         ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1604
1605         /* Make popup window */
1606         SetWindowLongA(whichHWND, GWL_STYLE, WS_POPUP);
1607         SetWindowPos(object->win_handle, HWND_TOP, 0, 0, 
1608                      *(pPresentationParameters->BackBufferWidth),
1609                      *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1610     }
1611
1612     /* MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1613        then the corresponding dimension of the client area of the hDeviceWindow
1614        (or the focus window, if hDeviceWindow is NULL) is taken. */
1615     if (*(pPresentationParameters->Windowed) && 
1616         ((*(pPresentationParameters->BackBufferWidth)  == 0) ||
1617          (*(pPresentationParameters->BackBufferHeight) == 0))) {
1618
1619         RECT Rect;
1620         GetClientRect(whichHWND, &Rect);
1621
1622         if (*(pPresentationParameters->BackBufferWidth) == 0) {
1623            *(pPresentationParameters->BackBufferWidth) = Rect.right;
1624            TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1625         }
1626         if (*(pPresentationParameters->BackBufferHeight) == 0) {
1627            *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1628            TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1629         }
1630     }
1631
1632     /* Save the presentation parms now filled in correctly */
1633     object->presentParms.BackBufferWidth                = *(pPresentationParameters->BackBufferWidth);
1634     object->presentParms.BackBufferHeight               = *(pPresentationParameters->BackBufferHeight);           
1635     object->presentParms.BackBufferFormat               = *(pPresentationParameters->BackBufferFormat);           
1636     object->presentParms.BackBufferCount                = *(pPresentationParameters->BackBufferCount);            
1637     object->presentParms.MultiSampleType                = *(pPresentationParameters->MultiSampleType);            
1638     object->presentParms.MultiSampleQuality             = *(pPresentationParameters->MultiSampleQuality);         
1639     object->presentParms.SwapEffect                     = *(pPresentationParameters->SwapEffect);                 
1640     object->presentParms.hDeviceWindow                  = *(pPresentationParameters->hDeviceWindow);              
1641     object->presentParms.Windowed                       = *(pPresentationParameters->Windowed);                   
1642     object->presentParms.EnableAutoDepthStencil         = *(pPresentationParameters->EnableAutoDepthStencil);     
1643     object->presentParms.AutoDepthStencilFormat         = *(pPresentationParameters->AutoDepthStencilFormat);     
1644     object->presentParms.Flags                          = *(pPresentationParameters->Flags);                      
1645     object->presentParms.FullScreen_RefreshRateInHz     = *(pPresentationParameters->FullScreen_RefreshRateInHz); 
1646     object->presentParms.PresentationInterval           = *(pPresentationParameters->PresentationInterval);       
1647
1648     /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
1649     IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object, 
1650                                     (D3DSTATEBLOCKTYPE) 0, 
1651                                     (IWineD3DStateBlock **)&object->stateBlock,
1652                                     NULL);   /* Note: No parent needed for initial internal stateblock */
1653     object->updateStateBlock = object->stateBlock;
1654
1655     /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
1656     TRACE("Creating initial device surfaces\n");
1657
1658     /* We need to 'magic' either d3d8 or d3d9 surfaces for the front and backbuuffer 
1659        but the respective CreateRenderTarget functions take a differing number of
1660        parms. Fix this by passing in a function to call which takes identical parms
1661        and handles the differences at the d3dx layer, and returns the IWineD3DSurface
1662        pointer rather than the created D3D8/9 one                                      */
1663     if ((res = D3DCB_CreateRenderTarget((IUnknown *) parent,
1664                                         *(pPresentationParameters->BackBufferWidth),
1665                                         *(pPresentationParameters->BackBufferHeight),
1666                                         *(pPresentationParameters->BackBufferFormat),
1667                                         *(pPresentationParameters->MultiSampleType),
1668                                         *(pPresentationParameters->MultiSampleQuality),
1669                                         TRUE,
1670                                         (IWineD3DSurface **) &object->frontBuffer,
1671                                         NULL) != D3D_OK) ||
1672         (res = D3DCB_CreateRenderTarget((IUnknown *) parent,
1673                                         *(pPresentationParameters->BackBufferWidth),
1674                                         *(pPresentationParameters->BackBufferHeight),
1675                                         *(pPresentationParameters->BackBufferFormat),
1676                                         *(pPresentationParameters->MultiSampleType),
1677                                         *(pPresentationParameters->MultiSampleQuality),
1678                                         TRUE,
1679                                         (IWineD3DSurface **) &object->backBuffer,
1680                                        NULL) != D3D_OK))
1681     {
1682         ERR("D3DCB_CreateRenderTarget() failed\n");
1683         return res;
1684     }
1685
1686 /* TODO: 
1687     if (*(pPresentationParameters->EnableAutoDepthStencil)) {
1688        IWineD3DDevice_CreateDepthStencilSurface((IWineD3DDevice *) object,
1689                                                 *(pPresentationParameters->BackBufferWidth),
1690                                                 *(pPresentationParameters->BackBufferHeight),
1691                                                 *(pPresentationParameters->AutoDepthStencilFormat,
1692                                                 D3DMULTISAMPLE_NONE,
1693                                                 (IWineD3DSurface *) &object->depthStencilBuffer);
1694     } else {
1695       object->depthStencilBuffer = NULL;
1696     }
1697     TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil @ %p\n",object->frontBuffer, object->backBuffer, object->depthStencilBuffer);
1698 */    
1699
1700     /* init the default renderTarget management */
1701     object->drawable     = object->win;
1702     object->render_ctx   = object->glCtx;
1703     object->renderTarget = object->backBuffer;
1704     
1705     IWineD3DSurface_AddRef((IWineD3DSurface *) object->renderTarget);
1706 /* TODO: Depth Stencil support
1707     object->stencilBufferTarget = object->depthStencilBuffer;
1708     if (NULL != object->stencilBufferTarget) {
1709       IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->stencilBufferTarget);
1710     }
1711 */    
1712
1713     /* Set up some starting GL setup */
1714     ENTER_GL();
1715
1716     if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1717       ERR("Error in setting current context (context %p drawable %ld)!\n", object->glCtx, object->win);
1718     }
1719     checkGLcall("glXMakeCurrent");
1720
1721     /* Clear the screen */
1722     glClearColor(1.0, 0.0, 0.0, 0.0);
1723     checkGLcall("glClearColor");
1724     glColor3f(1.0, 1.0, 1.0);
1725     checkGLcall("glColor3f");
1726
1727     glEnable(GL_LIGHTING);
1728     checkGLcall("glEnable");
1729
1730     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1731     checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1732
1733     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1734     checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1735
1736     glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1737     checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1738
1739     /* 
1740      * Initialize openGL extension related variables
1741      *  with Default values 
1742      */
1743     This->isGLInfoValid = IWineD3DImpl_FillGLCaps(&This->gl_info, object->display);
1744
1745     /* Setup all the devices defaults */
1746     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)object->stateBlock); 
1747
1748     LEAVE_GL();
1749
1750     { /* Set a default viewport */
1751        D3DVIEWPORT9 vp;
1752        vp.X      = 0;
1753        vp.Y      = 0;
1754        vp.Width  = *(pPresentationParameters->BackBufferWidth);
1755        vp.Height = *(pPresentationParameters->BackBufferHeight);
1756        vp.MinZ   = 0.0f;
1757        vp.MaxZ   = 1.0f;
1758        IWineD3DDevice_SetViewport((IWineD3DDevice *)object, &vp);
1759     }
1760
1761     /* Initialize the current view state */
1762     object->modelview_valid = 1;
1763     object->proj_valid = 0;
1764     object->view_ident = 1;
1765     object->last_was_rhw = 0;
1766     glGetIntegerv(GL_MAX_LIGHTS, &object->maxConcurrentLights);
1767     TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object);
1768
1769     /* Clear the screen */
1770     IWineD3DDevice_Clear((IWineD3DDevice *) object, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1771
1772     } /* End of FIXME: remove when dx8 merged in */
1773
1774     return D3D_OK;
1775 }
1776
1777 HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
1778     IWineD3DImpl *This = (IWineD3DImpl *)iface;
1779     IUnknown_AddRef(This->parent);
1780     *pParent = This->parent;
1781     return D3D_OK;
1782 }
1783
1784 /**********************************************************
1785  * IWineD3D VTbl follows
1786  **********************************************************/
1787
1788 const IWineD3DVtbl IWineD3D_Vtbl =
1789 {
1790     IWineD3DImpl_QueryInterface,
1791     IWineD3DImpl_AddRef,
1792     IWineD3DImpl_Release,
1793     IWineD3DImpl_GetParent,
1794     IWineD3DImpl_GetAdapterCount,
1795     IWineD3DImpl_RegisterSoftwareDevice,
1796     IWineD3DImpl_GetAdapterMonitor,
1797     IWineD3DImpl_GetAdapterModeCount,
1798     IWineD3DImpl_EnumAdapterModes,
1799     IWineD3DImpl_GetAdapterDisplayMode,
1800     IWineD3DImpl_GetAdapterIdentifier,
1801     IWineD3DImpl_CheckDeviceMultiSampleType,
1802     IWineD3DImpl_CheckDepthStencilMatch,
1803     IWineD3DImpl_CheckDeviceType,
1804     IWineD3DImpl_CheckDeviceFormat,
1805     IWineD3DImpl_CheckDeviceFormatConversion,
1806     IWineD3DImpl_GetDeviceCaps,
1807     IWineD3DImpl_CreateDevice
1808 };