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