Added version information.
[wine] / dlls / d3d8 / directx.c
1 /*
2  * IDirect3D8 implementation
3  *
4  * Copyright 2002 Jason Edmeades
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "wingdi.h"
29 #include "wine/debug.h"
30
31 #include "d3d8_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
34
35 /* x11drv GDI escapes */
36 #define X11DRV_ESCAPE 6789
37 enum x11drv_escape_codes
38 {
39     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
40     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
41     X11DRV_GET_FONT,      /* get current X font for a DC */
42 };
43
44 #define NUM_MODES 10
45 static const int modes[NUM_MODES][3] = {
46     {640, 480, 85},
47     {800, 600, 85},
48     {1024, 768, 85},
49     {1152, 864, 85},
50     {1280, 768, 85},
51     {1280, 960, 85},
52     {1280, 1024, 85},
53     {1600, 900, 85},
54     {1600, 1024, 85},
55     {1600, 1200, 85}
56 };
57
58 /* retrieve the X display to use on a given DC */
59 inline static Display *get_display( HDC hdc )
60 {
61     Display *display;
62     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
63
64     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
65                     sizeof(display), (LPSTR)&display )) display = NULL;
66     return display;
67 }
68
69
70 /* IDirect3D IUnknown parts follow: */
71 HRESULT WINAPI IDirect3D8Impl_QueryInterface(LPDIRECT3D8 iface,REFIID riid,LPVOID *ppobj)
72 {
73     ICOM_THIS(IDirect3D8Impl,iface);
74
75     if (IsEqualGUID(riid, &IID_IUnknown)
76         || IsEqualGUID(riid, &IID_IDirect3D8)) {
77         IDirect3D8Impl_AddRef(iface);
78         *ppobj = This;
79         return D3D_OK;
80     }
81
82     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
83     return E_NOINTERFACE;
84 }
85
86 ULONG WINAPI IDirect3D8Impl_AddRef(LPDIRECT3D8 iface) {
87     ICOM_THIS(IDirect3D8Impl,iface);
88     TRACE("(%p) : AddRef from %ld\n", This, This->ref);
89     return ++(This->ref);
90 }
91
92 ULONG WINAPI IDirect3D8Impl_Release(LPDIRECT3D8 iface) {
93     ICOM_THIS(IDirect3D8Impl,iface);
94     ULONG ref = --This->ref;
95     TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
96     if (ref == 0)
97         HeapFree(GetProcessHeap(), 0, This);
98     return ref;
99 }
100
101 /* IDirect3D Interface follow: */
102 HRESULT  WINAPI  IDirect3D8Impl_RegisterSoftwareDevice     (LPDIRECT3D8 iface, void* pInitializeFunction) {
103     ICOM_THIS(IDirect3D8Impl,iface);
104     FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
105     return D3D_OK;
106 }
107
108 UINT     WINAPI  IDirect3D8Impl_GetAdapterCount            (LPDIRECT3D8 iface) {
109     ICOM_THIS(IDirect3D8Impl,iface);
110     /* FIXME: Set to one for now to imply the display */
111     TRACE("(%p): Mostly stub, only returns primary display\n", This);
112     return 1;
113 }
114
115 HRESULT  WINAPI  IDirect3D8Impl_GetAdapterIdentifier       (LPDIRECT3D8 iface,
116                                                             UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8* pIdentifier) {
117     ICOM_THIS(IDirect3D8Impl,iface);
118
119     TRACE("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);
120
121     if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
122         return D3DERR_INVALIDCALL;
123     }
124
125     if (Adapter == 0) { /* Display */
126         strcpy(pIdentifier->Driver, "Display");
127         strcpy(pIdentifier->Description, "Direct3D Display");
128         pIdentifier->DriverVersion.s.HighPart = 1;
129         pIdentifier->DriverVersion.s.LowPart = 0;
130         pIdentifier->VendorId = 0;
131         pIdentifier->DeviceId = 0;
132         pIdentifier->SubSysId = 0;
133         pIdentifier->Revision = 0;
134         /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
135         if (Flags & D3DENUM_NO_WHQL_LEVEL ) {
136             pIdentifier->WHQLLevel = 0;
137         } else {
138             pIdentifier->WHQLLevel = 1;
139         }
140     } else {
141         FIXME("Adapter not primary display\n");
142     }
143
144     return D3D_OK;
145 }
146
147 UINT     WINAPI  IDirect3D8Impl_GetAdapterModeCount        (LPDIRECT3D8 iface,
148                                                             UINT Adapter) {
149     ICOM_THIS(IDirect3D8Impl,iface);
150
151     TRACE("(%p}->(Adapter: %d)\n", This, Adapter);
152
153     if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
154         return D3DERR_INVALIDCALL;
155     }
156
157     if (Adapter == 0) { /* Display */
158         int maxWidth        = GetSystemMetrics(SM_CXSCREEN);
159         int maxHeight       = GetSystemMetrics(SM_CYSCREEN);
160         int i;
161
162         for (i=0; i<NUM_MODES; i++) {
163             if (modes[i][0] > maxWidth || modes[i][1] > maxHeight) {
164                 return i+1;
165             }
166         }
167         return NUM_MODES+1;
168     } else {
169         FIXME("Adapter not primary display\n");
170     }
171
172     return 0;
173 }
174
175 HRESULT  WINAPI  IDirect3D8Impl_EnumAdapterModes           (LPDIRECT3D8 iface,
176                                                             UINT Adapter, UINT Mode, D3DDISPLAYMODE* pMode) {
177     ICOM_THIS(IDirect3D8Impl,iface);
178
179     TRACE("(%p}->(Adapter: %d, mode: %d, pMode=%p)\n", This, Adapter, Mode, pMode);
180
181     if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
182         return D3DERR_INVALIDCALL;
183     }
184
185     if (Adapter == 0) { /* Display */
186         HDC hdc;
187         int bpp = 0;
188
189         if (Mode == 0) {
190             pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
191             pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
192             pMode->RefreshRate  = 85; /*FIXME: How to identify? */
193         } else if (Mode < (NUM_MODES+1)) {
194             pMode->Width        = modes[Mode-1][0];
195             pMode->Height       = modes[Mode-1][1];
196             pMode->RefreshRate  = modes[Mode-1][2];
197         } else {
198             TRACE("Requested mode out of range %d\n", Mode);
199             return D3DERR_INVALIDCALL;
200         }
201
202         hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
203         bpp = GetDeviceCaps(hdc, BITSPIXEL);
204         DeleteDC(hdc);
205
206         switch (bpp) {
207         case  8: pMode->Format       = D3DFMT_R3G3B2;   break;
208         case 16: pMode->Format       = D3DFMT_R5G6B5;   break;
209         case 24: pMode->Format       = D3DFMT_R5G6B5;   break; /* Make 24bit appear as 16 bit */
210         case 32: pMode->Format       = D3DFMT_A8R8G8B8; break;
211         default: pMode->Format       = D3DFMT_UNKNOWN;
212         }
213         TRACE("W %d H %d rr %d fmt %x\n", pMode->Width, pMode->Height, pMode->RefreshRate, pMode->Format);
214
215     } else {
216         FIXME("Adapter not primary display\n");
217     }
218
219     return D3D_OK;
220 }
221
222 HRESULT  WINAPI  IDirect3D8Impl_GetAdapterDisplayMode      (LPDIRECT3D8 iface,
223                                                             UINT Adapter, D3DDISPLAYMODE* pMode) {
224     ICOM_THIS(IDirect3D8Impl,iface);
225     TRACE("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
226
227     if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
228         return D3DERR_INVALIDCALL;
229     }
230
231     if (Adapter == 0) { /* Display */
232         HDC hdc;
233         int bpp = 0;
234
235         pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
236         pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
237         pMode->RefreshRate  = 85; /*FIXME: How to identify? */
238
239         hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
240         bpp = GetDeviceCaps(hdc, BITSPIXEL);
241         DeleteDC(hdc);
242
243         switch (bpp) {
244         case  8: pMode->Format       = D3DFMT_R3G3B2;   break;
245         case 16: pMode->Format       = D3DFMT_R5G6B5;   break;
246         case 24: pMode->Format       = D3DFMT_R5G6B5;   break; /* Make 24bit appear as 16 bit */
247         case 32: pMode->Format       = D3DFMT_A8R8G8B8; break;
248         default: pMode->Format       = D3DFMT_UNKNOWN;
249         }
250
251     } else {
252         FIXME("Adapter not primary display\n");
253     }
254
255     TRACE("returning w:%d, h:%d, ref:%d, fmt:%x\n", pMode->Width,
256           pMode->Height, pMode->RefreshRate, pMode->Format);
257     return D3D_OK;
258 }
259
260 HRESULT  WINAPI  IDirect3D8Impl_CheckDeviceType            (LPDIRECT3D8 iface,
261                                                             UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat,
262                                                             D3DFORMAT BackBufferFormat, BOOL Windowed) {
263     ICOM_THIS(IDirect3D8Impl,iface);
264     FIXME("(%p)->(Adptr:%d, CheckType:%x, DispFmt:%x, BackBuf:%x, Win? %d): stub\n", This, Adapter, CheckType,
265           DisplayFormat, BackBufferFormat, Windowed);
266     return D3D_OK;
267 }
268
269 HRESULT  WINAPI  IDirect3D8Impl_CheckDeviceFormat          (LPDIRECT3D8 iface,
270                                                             UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
271                                                             DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) {
272     ICOM_THIS(IDirect3D8Impl,iface);
273     FIXME("(%p)->(Adptr:%d, DevType: %x, AdptFmt: %d, Use: %ld, ResTyp: %x, CheckFmt: %d)\n", This, Adapter, DeviceType,
274           AdapterFormat, Usage, RType, CheckFormat);
275     return D3D_OK;
276 }
277
278 HRESULT  WINAPI  IDirect3D8Impl_CheckDeviceMultiSampleType (LPDIRECT3D8 iface,
279                                                             UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat,
280                                                             BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType) {
281     ICOM_THIS(IDirect3D8Impl,iface);
282     FIXME("(%p)->(Adptr:%d, DevType: %x, SurfFmt: %x, Win? %d, MultiSamp: %x)\n", This, Adapter, DeviceType,
283           SurfaceFormat, Windowed, MultiSampleType);
284     return D3D_OK;
285 }
286
287 HRESULT  WINAPI  IDirect3D8Impl_CheckDepthStencilMatch     (LPDIRECT3D8 iface,
288                                                             UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
289                                                             D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) {
290     ICOM_THIS(IDirect3D8Impl,iface);
291     FIXME("(%p)->(Adptr:%d, DevType: %x, AdptFmt: %x, RendrTgtFmt: %x, DepthStencilFmt: %x)\n", This, Adapter, DeviceType,
292           AdapterFormat, RenderTargetFormat, DepthStencilFormat);
293     return D3D_OK;
294 }
295
296 HRESULT  WINAPI  IDirect3D8Impl_GetDeviceCaps              (LPDIRECT3D8 iface,
297                                                             UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS8* pCaps) {
298     ICOM_THIS(IDirect3D8Impl,iface);
299     TRACE("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
300
301
302     /* NOTE: Most of the values here are complete garbage for now */
303     pCaps->DeviceType = (DeviceType == D3DDEVTYPE_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;  /* Not quite true, but use h/w supported by opengl I suppose */
304     pCaps->AdapterOrdinal = Adapter;
305
306     pCaps->Caps = 0;
307     pCaps->Caps2 = D3DCAPS2_CANRENDERWINDOWED;
308     pCaps->Caps3 = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
309     pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
310
311     pCaps->CursorCaps = 0;
312
313     pCaps->DevCaps = D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_PUREDEVICE;
314
315     pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPTLVERTS  |
316                                D3DPMISCCAPS_CLIPPLANESCALEDPOINTS | D3DPMISCCAPS_MASKZ; /*NOT: D3DPMISCCAPS_TSSARGTEMP*/
317     pCaps->RasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_PAT;
318     pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
319                       D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
320
321     pCaps->SrcBlendCaps  = 0xFFFFFFFF;   /*FIXME: Tidy up later */
322     pCaps->DestBlendCaps = 0xFFFFFFFF;   /*FIXME: Tidy up later */
323     pCaps->AlphaCmpCaps  = 0xFFFFFFFF;   /*FIXME: Tidy up later */
324     pCaps->ShadeCaps = D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_COLORGOURAUDRGB ;
325     pCaps->TextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_VOLUMEMAP | D3DPTEXTURECAPS_MIPMAP;
326     pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MAGFLINEAR  | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT |
327                                D3DPTFILTERCAPS_MIPFLINEAR  | D3DPTFILTERCAPS_MIPFPOINT ;
328     pCaps->CubeTextureFilterCaps = 0;
329     pCaps->VolumeTextureFilterCaps = 0;
330     pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
331 #if defined(GL_VERSION_1_3)
332     pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
333 #endif
334     pCaps->VolumeTextureAddressCaps = 0;
335
336     pCaps->LineCaps = D3DLINECAPS_TEXTURE | D3DLINECAPS_ZTEST;
337
338     /*pCaps->MaxTextureWidth = 16384;
339     pCaps->MaxTextureHeight = 16384;*/
340     {
341       GLint gl_tex_size;    
342       glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_tex_size);
343       pCaps->MaxTextureWidth = gl_tex_size;
344       pCaps->MaxTextureHeight = gl_tex_size;
345     }
346
347     pCaps->MaxVolumeExtent = 0;
348
349     pCaps->MaxTextureRepeat = 32768;
350     pCaps->MaxTextureAspectRatio = 32768;
351     pCaps->MaxAnisotropy = 0;
352     pCaps->MaxVertexW = 1.0;
353
354     pCaps->GuardBandLeft = 0;
355     pCaps->GuardBandTop = 0;
356     pCaps->GuardBandRight = 0;
357     pCaps->GuardBandBottom = 0;
358
359     pCaps->ExtentsAdjust = 0;
360
361     pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | 
362                          D3DSTENCILCAPS_INVERT  | D3DSTENCILCAPS_KEEP    | 
363                          D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO /* | D3DSTENCILCAPS_DECR | D3DSTENCILCAPS_INCR */;
364
365     pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x80000;
366
367     pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED | D3DTEXOPCAPS_ADDSIGNED2X |
368                            D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE4X |
369                            D3DTEXOPCAPS_SELECTARG1  | D3DTEXOPCAPS_DISABLE;
370 #if defined(GL_VERSION_1_3)
371     pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
372 #endif
373               /* FIXME: Add D3DTEXOPCAPS_ADDSMOOTH D3DTEXOPCAPS_BLENDCURRENTALPHA D3DTEXOPCAPS_BLENDDIFFUSEALPHA D3DTEXOPCAPS_BLENDFACTORALPHA 
374                             D3DTEXOPCAPS_BLENDTEXTUREALPHA D3DTEXOPCAPS_BLENDTEXTUREALPHAPM D3DTEXOPCAPS_BUMPENVMAP D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 
375                             D3DTEXOPCAPS_LERP D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 
376                             D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA D3DTEXOPCAPS_MULTIPLYADD 
377                             D3DTEXOPCAPS_PREMODULATE D3DTEXOPCAPS_SELECTARG2 D3DTEXOPCAPS_SUBTRACT */
378
379     {
380         GLint gl_max;
381 #if defined(GL_VERSION_1_3)
382         glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max);
383 #else
384         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
385 #endif
386         TRACE("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max);
387         pCaps->MaxTextureBlendStages = min(8, gl_max);
388         pCaps->MaxSimultaneousTextures = min(8, gl_max);
389
390         glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
391         pCaps->MaxUserClipPlanes = min(MAX_CLIPPLANES, gl_max);
392         TRACE("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", pCaps->MaxUserClipPlanes);
393
394         glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
395         pCaps->MaxActiveLights = min(MAX_ACTIVE_LIGHTS, gl_max);
396         TRACE("GLCaps: GL_MAX_LIGHTS=%ld\n", pCaps->MaxActiveLights);
397     }
398
399     pCaps->VertexProcessingCaps = D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_TEXGEN;
400
401     pCaps->MaxVertexBlendMatrices = 1;
402     pCaps->MaxVertexBlendMatrixIndex = 1;
403
404     pCaps->MaxPointSize = 128.0;
405
406     pCaps->MaxPrimitiveCount = 0xFFFFFFFF;
407     pCaps->MaxVertexIndex = 0xFFFFFFFF;
408     pCaps->MaxStreams = 2; /* HACK: Some games want at least 2 */ 
409     pCaps->MaxStreamStride = 1024;
410
411     pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
412     pCaps->MaxVertexShaderConst = D3D8_VSHADER_MAX_CONSTANTS;
413
414     pCaps->PixelShaderVersion = D3DPS_VERSION(1,1);
415     pCaps->MaxPixelShaderValue = 1.0;
416
417     return D3D_OK;
418 }
419
420 HMONITOR WINAPI  IDirect3D8Impl_GetAdapterMonitor          (LPDIRECT3D8 iface,
421                                                             UINT Adapter) {
422     ICOM_THIS(IDirect3D8Impl,iface);
423     FIXME("(%p)->(Adptr:%d)\n", This, Adapter);
424     return D3D_OK;
425 }
426
427 HRESULT  WINAPI  IDirect3D8Impl_CreateDevice               (LPDIRECT3D8 iface,
428                                                             UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow,
429                                                             DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters,
430                                                             IDirect3DDevice8** ppReturnedDeviceInterface) {
431     IDirect3DDevice8Impl *object;
432     HWND whichHWND;
433     int num;
434     XVisualInfo template;
435     const char *GL_Extensions = NULL;
436     const char *GLX_Extensions = NULL;
437     GLint gl_max;
438
439     ICOM_THIS(IDirect3D8Impl,iface);
440     TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This, Adapter, DeviceType,
441           hFocusWindow, BehaviourFlags, pPresentationParameters, ppReturnedDeviceInterface);
442
443     /* Allocate the storage for the device */
444     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
445     if (NULL == object) {
446       return D3DERR_OUTOFVIDEOMEMORY;
447     }
448     object->lpVtbl = &Direct3DDevice8_Vtbl;
449     object->ref = 1;
450     object->direct3d8 = This;
451     /** The device AddRef the direct3d8 Interface else crash in propers clients codes */
452     IDirect3D8_AddRef((LPDIRECT3D8) object->direct3d8);
453
454     /** use StateBlock Factory here, for creating the startup stateBlock */
455     object->StateBlock = NULL;
456     IDirect3DDeviceImpl_CreateStateBlock(object, D3DSBT_ALL, NULL);
457     object->UpdateStateBlock = object->StateBlock;
458
459     /* Save the creation parameters */
460     object->CreateParms.AdapterOrdinal = Adapter;
461     object->CreateParms.DeviceType = DeviceType;
462     object->CreateParms.hFocusWindow = hFocusWindow;
463     object->CreateParms.BehaviorFlags = BehaviourFlags;
464
465     *ppReturnedDeviceInterface = (LPDIRECT3DDEVICE8)object;
466
467     /* Initialize settings */
468     memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
469
470     object->PresentParms.BackBufferCount = 1; /* Opengl only supports one? */
471     pPresentationParameters->BackBufferCount = 1;
472
473     object->adapterNo = Adapter;
474     object->devType = DeviceType;
475
476     /* Initialize openGl */
477     {
478         HDC hDc;
479         int          dblBuf[]={GLX_STENCIL_SIZE,8,GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_DOUBLEBUFFER,None};
480         /* FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat */
481         /*int          dblBuf[]={GLX_RGBA,GLX_RED_SIZE,4,GLX_GREEN_SIZE,4,GLX_BLUE_SIZE,4,GLX_DOUBLEBUFFER,None}; */
482
483         /* Which hwnd are we using? */
484 /*      if (pPresentationParameters->Windowed) { */
485            whichHWND = pPresentationParameters->hDeviceWindow;
486            if (!whichHWND) {
487                whichHWND = hFocusWindow;
488            }
489            object->win     = (Window)GetPropA( whichHWND, "__wine_x11_client_window" );
490 /*
491  *      } else {
492  *           whichHWND       = (HWND) GetDesktopWindow();
493  *           object->win     = (Window)GetPropA(whichHWND, "__wine_x11_whole_window" );
494  *         root_window
495  *        }
496  */
497
498         hDc = GetDC(whichHWND);
499         object->display = get_display(hDc);
500
501         ENTER_GL();
502         object->visInfo = glXChooseVisual(object->display, DefaultScreen(object->display), dblBuf);
503         if (NULL == object->visInfo) {
504           FIXME("cannot choose needed glxVisual with Stencil Buffer\n"); 
505
506           /**
507            * second try using wine initialized visual ...
508            * must be fixed reworking wine-glx init
509            */
510           template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
511           object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
512           if (NULL == object->visInfo) {
513             ERR("cannot really get XVisual\n"); 
514             LEAVE_GL();
515             return D3DERR_NOTAVAILABLE;
516           }
517         }
518         object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
519         if (NULL == object->glCtx) {
520           ERR("cannot create glxContext\n"); 
521           LEAVE_GL();
522           return D3DERR_NOTAVAILABLE;
523         }
524         LEAVE_GL();
525
526         ReleaseDC(whichHWND, hDc);
527     }
528
529     if (object->glCtx == NULL) {
530         ERR("Error in context creation !\n");
531         return D3DERR_INVALIDCALL;
532     } else {
533         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
534                         whichHWND, object->glCtx, object->win, object->visInfo);
535     }
536
537     /* If not windowed, need to go fullscreen, and resize the HWND to the appropriate  */
538     /*        dimensions                                                               */
539     if (!pPresentationParameters->Windowed) {
540         FIXME("Requested full screen support not implemented, expect windowed operation\n");
541         SetWindowPos(whichHWND, HWND_TOP, 0, 0, pPresentationParameters->BackBufferWidth,
542             pPresentationParameters->BackBufferHeight, SWP_SHOWWINDOW);
543     }
544
545     TRACE("Creating back buffer\n");
546     /* MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
547        then the corresponding dimension of the client area of the hDeviceWindow
548        (or the focus window, if hDeviceWindow is NULL) is taken. */
549     if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth  == 0) ||
550                                               (pPresentationParameters->BackBufferHeight  == 0))) {
551         RECT Rect;
552
553         GetClientRect(whichHWND, &Rect);
554
555         if (pPresentationParameters->BackBufferWidth  == 0) {
556            pPresentationParameters->BackBufferWidth = Rect.right;
557            TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
558         }
559         if (pPresentationParameters->BackBufferHeight  == 0) {
560            pPresentationParameters->BackBufferHeight = Rect.bottom;
561            TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
562         }
563     }
564
565     IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
566                                             pPresentationParameters->BackBufferWidth,
567                                             pPresentationParameters->BackBufferHeight,
568                                             pPresentationParameters->BackBufferFormat,
569                                             D3DMULTISAMPLE_NONE, TRUE,
570                                             (LPDIRECT3DSURFACE8*) &object->frontBuffer);
571
572     IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
573                                             pPresentationParameters->BackBufferWidth,
574                                             pPresentationParameters->BackBufferHeight,
575                                             pPresentationParameters->BackBufferFormat,
576                                             D3DMULTISAMPLE_NONE, TRUE,
577                                             (LPDIRECT3DSURFACE8*) &object->backBuffer);
578
579     if (pPresentationParameters->EnableAutoDepthStencil)
580         IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
581                                                        pPresentationParameters->BackBufferWidth,
582                                                        pPresentationParameters->BackBufferHeight,
583                                                        pPresentationParameters->AutoDepthStencilFormat,
584                                                        D3DMULTISAMPLE_NONE,
585                                                        (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
586     
587     /* Now override the surface's Flip method (if in double buffering) ?COPIED from DDRAW!?
588     ((x11_ds_private *) surface->private)->opengl_flip = TRUE;
589     {
590     int i;
591     struct _surface_chain *chain = surface->s.chain;
592     for (i=0;i<chain->nrofsurfaces;i++)
593       if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
594           ((x11_ds_private *) chain->surfaces[i]->private)->opengl_flip = TRUE;
595     }
596     */
597
598     ENTER_GL();
599
600     /*TRACE("hereeee. %x %x %x\n", object->display, object->win, object->glCtx);*/
601     if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
602       ERR("Error in setting current context (context %p drawable %ld)!\n", object->glCtx, object->win);
603     }
604     checkGLcall("glXMakeCurrent");
605
606     /* Clear the screen */
607     glClearColor(1.0, 0.0, 0.0, 0.0);
608     checkGLcall("glClearColor");
609     glColor3f(1.0, 1.0, 1.0);
610     checkGLcall("glColor3f");
611
612     glEnable(GL_LIGHTING);
613     checkGLcall("glEnable");
614
615     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
616     checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
617
618     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
619     checkGLcall("glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
620
621     /* Initialize openGL extension related variables */
622     object->isMultiTexture = FALSE;
623     object->isDot3         = FALSE;
624     object->TextureUnits   = 1;
625
626     /* Retrieve opengl defaults */
627     glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
628     object->clipPlanes   = min(MAX_CLIPPLANES, gl_max);
629     TRACE("ClipPlanes support - num Planes=%d\n", gl_max);
630
631     glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
632     object->maxLights = min(MAX_ACTIVE_LIGHTS, gl_max);
633     TRACE("Lights support - max lights=%d\n", gl_max);
634
635     /* Parse the gl supported features, in theory enabling parts of our code appropriately */
636     GL_Extensions = glGetString(GL_EXTENSIONS);
637     TRACE("GL_Extensions reported:\n");  
638     
639     if (NULL == GL_Extensions) {
640       ERR("   GL_Extensions returns NULL\n");      
641     } else {
642       while (*GL_Extensions != 0x00) {
643         const char *Start = GL_Extensions;
644         char ThisExtn[256];
645
646         memset(ThisExtn, 0x00, sizeof(ThisExtn));
647         while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
648           GL_Extensions++;
649         }
650         memcpy(ThisExtn, Start, (GL_Extensions - Start));
651         TRACE ("   %s\n", ThisExtn);
652
653         if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
654             glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
655             object->isMultiTexture = TRUE;
656             object->TextureUnits   = min(8, gl_max);
657             TRACE("FOUND: Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max);
658         } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
659             object->isDot3 = TRUE;
660             TRACE("FOUND: Dot3 support\n");
661         }
662
663         if (*GL_Extensions == ' ') GL_Extensions++;
664       }
665     }
666
667     GLX_Extensions = glXQueryExtensionsString(object->display, DefaultScreen(object->display));
668     TRACE("GLX_Extensions reported:\n");  
669     
670     if (NULL == GLX_Extensions) {
671       ERR("   GLX_Extensions returns NULL\n");      
672     } else {
673       while (*GLX_Extensions != 0x00) {
674         const char *Start = GLX_Extensions;
675         char ThisExtn[256];
676         
677         memset(ThisExtn, 0x00, sizeof(ThisExtn));
678         while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
679           GLX_Extensions++;
680         }
681         memcpy(ThisExtn, Start, (GLX_Extensions - Start));
682         TRACE ("   %s\n", ThisExtn);
683         if (*GLX_Extensions == ' ') GLX_Extensions++;
684       }
685     }
686
687     /* Setup all the devices defaults */
688     IDirect3DDeviceImpl_InitStartupStateBlock(object);
689
690     LEAVE_GL();
691
692     { /* Set a default viewport */
693        D3DVIEWPORT8 vp;
694        vp.X      = 0;
695        vp.Y      = 0;
696        vp.Width  = pPresentationParameters->BackBufferWidth;
697        vp.Height = pPresentationParameters->BackBufferHeight;
698        vp.MinZ   = 0.0f;
699        vp.MaxZ   = 1.0f;
700        IDirect3DDevice8Impl_SetViewport((LPDIRECT3DDEVICE8) object, &vp);
701     }
702
703     TRACE("(%p,%d) All defaults now set up, leaving CreateDevice\n", This, Adapter);
704     return D3D_OK;
705 }
706
707 ICOM_VTABLE(IDirect3D8) Direct3D8_Vtbl =
708 {
709     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
710     IDirect3D8Impl_QueryInterface,
711     IDirect3D8Impl_AddRef,
712     IDirect3D8Impl_Release,
713     IDirect3D8Impl_RegisterSoftwareDevice,
714     IDirect3D8Impl_GetAdapterCount,
715     IDirect3D8Impl_GetAdapterIdentifier,
716     IDirect3D8Impl_GetAdapterModeCount,
717     IDirect3D8Impl_EnumAdapterModes,
718     IDirect3D8Impl_GetAdapterDisplayMode,
719     IDirect3D8Impl_CheckDeviceType,
720     IDirect3D8Impl_CheckDeviceFormat,
721     IDirect3D8Impl_CheckDeviceMultiSampleType,
722     IDirect3D8Impl_CheckDepthStencilMatch,
723     IDirect3D8Impl_GetDeviceCaps,
724     IDirect3D8Impl_GetAdapterMonitor,
725     IDirect3D8Impl_CreateDevice
726 };