Move the Check* type functions into wined3d and copy from d3d9, and
[wine/gsoc_dplay.git] / dlls / d3d8 / directx.c
blob2c814412e973fc57cf3efee27f2025ec3145b17b
1 /*
2 * IDirect3D8 implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
25 #include <stdarg.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
36 #include "d3d8_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
39 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
41 /* x11drv GDI escapes */
42 #define X11DRV_ESCAPE 6789
43 enum x11drv_escape_codes
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 */
50 #define NUM_FORMATS 7
51 static const D3DFORMAT device_formats[NUM_FORMATS] = {
52 D3DFMT_P8,
53 D3DFMT_R3G3B2,
54 D3DFMT_R5G6B5,
55 D3DFMT_X1R5G5B5,
56 D3DFMT_X4R4G4B4,
57 D3DFMT_R8G8B8,
58 D3DFMT_X8R8G8B8
61 static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display);
64 /* retrieve the X display to use on a given DC */
65 inline static Display *get_display( HDC hdc )
67 Display *display;
68 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
70 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
71 sizeof(display), (LPSTR)&display )) display = NULL;
72 return display;
75 /**
76 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
77 * ie there is no GL Context - Get a default rendering context to enable the
78 * function query some info from GL
79 */
80 static
81 WineD3D_Context* WineD3DCreateFakeGLContext(void) {
82 static WineD3D_Context ctx = { NULL, NULL, NULL, 0, 0 };
83 WineD3D_Context* ret = NULL;
85 if (glXGetCurrentContext() == NULL) {
86 BOOL gotContext = FALSE;
87 BOOL created = FALSE;
88 XVisualInfo template;
89 HDC device_context;
90 Visual* visual;
91 BOOL failed = FALSE;
92 int num;
93 XWindowAttributes win_attr;
95 TRACE_(d3d_caps)("Creating Fake GL Context\n");
97 ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
99 /* Get the display */
100 device_context = GetDC(0);
101 ctx.display = get_display(device_context);
102 ReleaseDC(0, device_context);
104 /* Get the X visual */
105 ENTER_GL();
106 if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
107 visual = win_attr.visual;
108 } else {
109 visual = DefaultVisual(ctx.display, DefaultScreen(ctx.display));
111 template.visualid = XVisualIDFromVisual(visual);
112 ctx.visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
113 if (ctx.visInfo == NULL) {
114 LEAVE_GL();
115 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
116 failed = TRUE;
119 /* Create a GL context */
120 if (!failed) {
121 ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
123 if (ctx.glCtx == NULL) {
124 LEAVE_GL();
125 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
126 failed = TRUE;
130 /* Make it the current GL context */
131 if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
132 glXDestroyContext(ctx.display, ctx.glCtx);
133 LEAVE_GL();
134 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
135 failed = TRUE;
138 /* It worked! Wow... */
139 if (!failed) {
140 gotContext = TRUE;
141 created = TRUE;
142 ret = &ctx;
143 } else {
144 ret = NULL;
146 } else {
147 if (ctx.ref > 0) ret = &ctx;
150 if (NULL != ret) ++ret->ref;
152 return ret;
155 static
156 void WineD3DReleaseFakeGLContext(WineD3D_Context* ctx) {
157 /* If we created a dummy context, throw it away */
158 if (NULL != ctx) {
159 --ctx->ref;
160 if (0 == ctx->ref) {
161 glXMakeCurrent(ctx->display, None, NULL);
162 glXDestroyContext(ctx->display, ctx->glCtx);
163 ctx->display = NULL;
164 ctx->glCtx = NULL;
165 LEAVE_GL();
171 /* IDirect3D IUnknown parts follow: */
172 HRESULT WINAPI IDirect3D8Impl_QueryInterface(LPDIRECT3D8 iface,REFIID riid,LPVOID *ppobj)
174 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
176 if (IsEqualGUID(riid, &IID_IUnknown)
177 || IsEqualGUID(riid, &IID_IDirect3D8)) {
178 IDirect3D8Impl_AddRef(iface);
179 *ppobj = This;
180 return D3D_OK;
183 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
184 return E_NOINTERFACE;
187 ULONG WINAPI IDirect3D8Impl_AddRef(LPDIRECT3D8 iface) {
188 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
189 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
190 return ++(This->ref);
193 ULONG WINAPI IDirect3D8Impl_Release(LPDIRECT3D8 iface) {
194 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
195 ULONG ref = --This->ref;
196 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
197 if (ref == 0) {
198 IWineD3D_Release(This->WineD3D);
199 HeapFree(GetProcessHeap(), 0, This);
201 return ref;
204 /* IDirect3D Interface follow: */
205 HRESULT WINAPI IDirect3D8Impl_RegisterSoftwareDevice (LPDIRECT3D8 iface, void* pInitializeFunction) {
206 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
207 return IWineD3D_RegisterSoftwareDevice(This->WineD3D, pInitializeFunction);
210 UINT WINAPI IDirect3D8Impl_GetAdapterCount (LPDIRECT3D8 iface) {
211 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
212 return IWineD3D_GetAdapterCount(This->WineD3D);
215 HRESULT WINAPI IDirect3D8Impl_GetAdapterIdentifier (LPDIRECT3D8 iface,
216 UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8* pIdentifier) {
217 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
218 WINED3DADAPTER_IDENTIFIER adapter_id;
220 /* dx8 and dx9 have different structures to be filled in, with incompatible
221 layouts so pass in pointers to the places to be filled via an internal
222 structure */
223 adapter_id.Driver = pIdentifier->Driver;
224 adapter_id.Description = pIdentifier->Description;
225 adapter_id.DeviceName = NULL;
226 adapter_id.DriverVersion = &pIdentifier->DriverVersion;
227 adapter_id.VendorId = &pIdentifier->VendorId;
228 adapter_id.DeviceId = &pIdentifier->DeviceId;
229 adapter_id.SubSysId = &pIdentifier->SubSysId;
230 adapter_id.Revision = &pIdentifier->Revision;
231 adapter_id.DeviceIdentifier = &pIdentifier->DeviceIdentifier;
232 adapter_id.WHQLLevel = &pIdentifier->WHQLLevel;
234 return IWineD3D_GetAdapterIdentifier(This->WineD3D, Adapter, Flags, &adapter_id);
237 UINT WINAPI IDirect3D8Impl_GetAdapterModeCount (LPDIRECT3D8 iface,UINT Adapter) {
238 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
239 return IWineD3D_GetAdapterModeCount(This->WineD3D, Adapter, D3DFMT_UNKNOWN);
242 HRESULT WINAPI IDirect3D8Impl_EnumAdapterModes (LPDIRECT3D8 iface, UINT Adapter, UINT Mode, D3DDISPLAYMODE* pMode) {
243 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
244 return IWineD3D_EnumAdapterModes(This->WineD3D, Adapter, D3DFMT_UNKNOWN, Mode, pMode);
247 HRESULT WINAPI IDirect3D8Impl_GetAdapterDisplayMode (LPDIRECT3D8 iface, UINT Adapter, D3DDISPLAYMODE* pMode) {
248 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
249 return IWineD3D_GetAdapterDisplayMode(This->WineD3D, Adapter, pMode);
252 HRESULT WINAPI IDirect3D8Impl_CheckDeviceType (LPDIRECT3D8 iface,
253 UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat,
254 D3DFORMAT BackBufferFormat, BOOL Windowed) {
255 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
256 return IWineD3D_CheckDeviceType(This->WineD3D, Adapter, CheckType, DisplayFormat,
257 BackBufferFormat, Windowed);
260 HRESULT WINAPI IDirect3D8Impl_CheckDeviceFormat (LPDIRECT3D8 iface,
261 UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
262 DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) {
263 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
264 return IWineD3D_CheckDeviceFormat(This->WineD3D, Adapter, DeviceType, AdapterFormat,
265 Usage, RType, CheckFormat);
268 HRESULT WINAPI IDirect3D8Impl_CheckDeviceMultiSampleType(LPDIRECT3D8 iface,
269 UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat,
270 BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType) {
271 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
272 return IWineD3D_CheckDeviceMultiSampleType(This->WineD3D, Adapter, DeviceType, SurfaceFormat,
273 Windowed, MultiSampleType, NULL);
276 HRESULT WINAPI IDirect3D8Impl_CheckDepthStencilMatch(LPDIRECT3D8 iface,
277 UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
278 D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) {
279 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
280 return IWineD3D_CheckDepthStencilMatch(This->WineD3D, Adapter, DeviceType, AdapterFormat,
281 RenderTargetFormat, DepthStencilFormat);
284 HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS8* pCaps) {
286 BOOL gotContext = FALSE;
287 GLint gl_tex_size = 0;
288 WineD3D_Context* fake_ctx = NULL;
289 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
291 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
293 if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
294 return D3DERR_INVALIDCALL;
297 /* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
298 ie there is no GL Context - Get a default rendering context to enable the
299 function query some info from GL */
300 if (glXGetCurrentContext() == NULL) {
301 fake_ctx = WineD3DCreateFakeGLContext();
302 if (NULL != fake_ctx) gotContext = TRUE;
303 } else {
304 gotContext = TRUE;
307 if (gotContext == FALSE) {
309 FIXME_(d3d_caps)("GetDeviceCaps called but no GL Context - Returning dummy values\n");
310 gl_tex_size=65535;
311 pCaps->MaxTextureBlendStages = 2;
312 pCaps->MaxSimultaneousTextures = 2;
313 pCaps->MaxUserClipPlanes = 8;
314 pCaps->MaxActiveLights = 8;
315 pCaps->MaxVertexBlendMatrices = 0;
316 pCaps->MaxVertexBlendMatrixIndex = 1;
317 pCaps->MaxAnisotropy = 0;
318 pCaps->MaxPointSize = 255.0;
319 } else {
320 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_tex_size);
323 /* If we don't know the device settings, go query them now */
324 if (This->isGLInfoValid == FALSE) IDirect3D8Impl_FillGLCaps(iface, NULL);
326 pCaps->DeviceType = (DeviceType == D3DDEVTYPE_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
327 pCaps->AdapterOrdinal = Adapter;
329 pCaps->Caps = 0;
330 pCaps->Caps2 = D3DCAPS2_CANRENDERWINDOWED;
331 pCaps->Caps3 = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
332 pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
334 pCaps->CursorCaps = 0;
336 pCaps->DevCaps = D3DDEVCAPS_DRAWPRIMTLVERTEX |
337 D3DDEVCAPS_HWTRANSFORMANDLIGHT |
338 D3DDEVCAPS_PUREDEVICE;
340 pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLCCW |
341 D3DPMISCCAPS_CULLCW |
342 D3DPMISCCAPS_COLORWRITEENABLE |
343 D3DPMISCCAPS_CLIPTLVERTS |
344 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
345 D3DPMISCCAPS_MASKZ;
346 /*NOT: D3DPMISCCAPS_TSSARGTEMP*/
348 pCaps->RasterCaps = D3DPRASTERCAPS_DITHER |
349 D3DPRASTERCAPS_PAT |
350 D3DPRASTERCAPS_WFOG |
351 D3DPRASTERCAPS_ZFOG |
352 D3DPRASTERCAPS_FOGVERTEX |
353 D3DPRASTERCAPS_FOGTABLE |
354 D3DPRASTERCAPS_FOGRANGE;
356 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
357 pCaps->RasterCaps |= D3DPRASTERCAPS_ANISOTROPY;
359 /* FIXME Add:
360 D3DPRASTERCAPS_MIPMAPLODBIAS
361 D3DPRASTERCAPS_ZBIAS
362 D3DPRASTERCAPS_COLORPERSPECTIVE
363 D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
364 D3DPRASTERCAPS_ANTIALIASEDGES
365 D3DPRASTERCAPS_ZBUFFERLESSHSR
366 D3DPRASTERCAPS_WBUFFER */
368 pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
369 D3DPCMPCAPS_EQUAL |
370 D3DPCMPCAPS_GREATER |
371 D3DPCMPCAPS_GREATEREQUAL |
372 D3DPCMPCAPS_LESS |
373 D3DPCMPCAPS_LESSEQUAL |
374 D3DPCMPCAPS_NEVER |
375 D3DPCMPCAPS_NOTEQUAL;
377 pCaps->SrcBlendCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
378 pCaps->DestBlendCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
379 pCaps->AlphaCmpCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
381 pCaps->ShadeCaps = D3DPSHADECAPS_SPECULARGOURAUDRGB |
382 D3DPSHADECAPS_COLORGOURAUDRGB;
384 pCaps->TextureCaps = D3DPTEXTURECAPS_ALPHA |
385 D3DPTEXTURECAPS_ALPHAPALETTE |
386 D3DPTEXTURECAPS_POW2 |
387 D3DPTEXTURECAPS_VOLUMEMAP |
388 D3DPTEXTURECAPS_MIPMAP |
389 D3DPTEXTURECAPS_PROJECTED;
391 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
392 pCaps->TextureCaps |= D3DPTEXTURECAPS_CUBEMAP |
393 D3DPTEXTURECAPS_MIPCUBEMAP |
394 D3DPTEXTURECAPS_CUBEMAP_POW2;
397 pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MAGFLINEAR |
398 D3DPTFILTERCAPS_MAGFPOINT |
399 D3DPTFILTERCAPS_MINFLINEAR |
400 D3DPTFILTERCAPS_MINFPOINT |
401 D3DPTFILTERCAPS_MIPFLINEAR |
402 D3DPTFILTERCAPS_MIPFPOINT;
404 pCaps->CubeTextureFilterCaps = 0;
405 pCaps->VolumeTextureFilterCaps = 0;
407 pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_BORDER |
408 D3DPTADDRESSCAPS_CLAMP |
409 D3DPTADDRESSCAPS_WRAP;
411 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
412 pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
414 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
415 pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
417 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
418 pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
421 pCaps->VolumeTextureAddressCaps = 0;
423 pCaps->LineCaps = D3DLINECAPS_TEXTURE |
424 D3DLINECAPS_ZTEST;
425 /* FIXME: Add
426 D3DLINECAPS_BLEND
427 D3DLINECAPS_ALPHACMP
428 D3DLINECAPS_FOG */
430 pCaps->MaxTextureWidth = gl_tex_size;
431 pCaps->MaxTextureHeight = gl_tex_size;
433 pCaps->MaxVolumeExtent = 0;
435 pCaps->MaxTextureRepeat = 32768;
436 pCaps->MaxTextureAspectRatio = 32768;
437 pCaps->MaxVertexW = 1.0;
439 pCaps->GuardBandLeft = 0;
440 pCaps->GuardBandTop = 0;
441 pCaps->GuardBandRight = 0;
442 pCaps->GuardBandBottom = 0;
444 pCaps->ExtentsAdjust = 0;
446 pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
447 D3DSTENCILCAPS_INCRSAT |
448 D3DSTENCILCAPS_INVERT |
449 D3DSTENCILCAPS_KEEP |
450 D3DSTENCILCAPS_REPLACE |
451 D3DSTENCILCAPS_ZERO;
452 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
453 pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
454 D3DSTENCILCAPS_INCR;
457 pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
459 pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
460 D3DTEXOPCAPS_ADDSIGNED |
461 D3DTEXOPCAPS_ADDSIGNED2X |
462 D3DTEXOPCAPS_MODULATE |
463 D3DTEXOPCAPS_MODULATE2X |
464 D3DTEXOPCAPS_MODULATE4X |
465 D3DTEXOPCAPS_SELECTARG1 |
466 D3DTEXOPCAPS_SELECTARG2 |
467 D3DTEXOPCAPS_DISABLE;
468 #if defined(GL_VERSION_1_3)
469 pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3 |
470 D3DTEXOPCAPS_SUBTRACT;
471 #endif
472 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
473 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
474 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
475 pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
476 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
477 D3DTEXOPCAPS_BLENDFACTORALPHA |
478 D3DTEXOPCAPS_BLENDCURRENTALPHA |
479 D3DTEXOPCAPS_LERP;
481 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
482 pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
483 D3DTEXOPCAPS_MULTIPLYADD |
484 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
485 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
486 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
489 #if 0
490 pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
491 /* FIXME: Add
492 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
493 D3DTEXOPCAPS_PREMODULATE */
494 #endif
496 if (gotContext) {
497 GLint gl_max;
498 GLfloat gl_float;
499 #if defined(GL_VERSION_1_3)
500 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max);
501 #else
502 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
503 #endif
504 TRACE_(d3d_caps)("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max);
505 pCaps->MaxTextureBlendStages = min(8, gl_max);
506 pCaps->MaxSimultaneousTextures = min(8, gl_max);
508 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
509 pCaps->MaxUserClipPlanes = min(MAX_CLIPPLANES, gl_max);
510 TRACE_(d3d_caps)("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", pCaps->MaxUserClipPlanes);
512 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
513 pCaps->MaxActiveLights = gl_max;
514 TRACE_(d3d_caps)("GLCaps: GL_MAX_LIGHTS=%ld\n", pCaps->MaxActiveLights);
516 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
517 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
518 pCaps->MaxVertexBlendMatrices = gl_max;
519 pCaps->MaxVertexBlendMatrixIndex = 1;
520 } else {
521 pCaps->MaxVertexBlendMatrices = 0;
522 pCaps->MaxVertexBlendMatrixIndex = 1;
525 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
526 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
527 checkGLcall("glGetInterv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)");
528 pCaps->MaxAnisotropy = gl_max;
529 } else {
530 pCaps->MaxAnisotropy = 0;
533 glGetFloatv(GL_POINT_SIZE_RANGE, &gl_float);
534 pCaps->MaxPointSize = gl_float;
537 pCaps->VertexProcessingCaps = D3DVTXPCAPS_DIRECTIONALLIGHTS |
538 D3DVTXPCAPS_MATERIALSOURCE7 |
539 D3DVTXPCAPS_POSITIONALLIGHTS |
540 D3DVTXPCAPS_LOCALVIEWER |
541 D3DVTXPCAPS_TEXGEN;
542 /* FIXME: Add
543 D3DVTXPCAPS_TWEENING */
545 pCaps->MaxPrimitiveCount = 0xFFFFFFFF;
546 pCaps->MaxVertexIndex = 0xFFFFFFFF;
547 pCaps->MaxStreams = MAX_STREAMS;
548 pCaps->MaxStreamStride = 1024;
550 if (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) || (vs_mode == VS_SW) || (DeviceType == D3DDEVTYPE_REF)) {
551 pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
553 if (This->gl_info.gl_vendor == VENDOR_MESA ||
554 This->gl_info.gl_vendor == VENDOR_WINE) {
555 pCaps->MaxVertexShaderConst = 95;
556 } else {
557 pCaps->MaxVertexShaderConst = D3D8_VSHADER_MAX_CONSTANTS;
559 } else {
560 pCaps->VertexShaderVersion = 0;
561 pCaps->MaxVertexShaderConst = 0;
564 if ((ps_mode == PS_HW) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && (DeviceType != D3DDEVTYPE_REF)) {
565 pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
566 pCaps->MaxPixelShaderValue = 1.0;
567 } else {
568 pCaps->PixelShaderVersion = 0;
569 pCaps->MaxPixelShaderValue = 0.0;
572 /* If we created a dummy context, throw it away */
573 WineD3DReleaseFakeGLContext(fake_ctx);
574 return D3D_OK;
577 HMONITOR WINAPI IDirect3D8Impl_GetAdapterMonitor(LPDIRECT3D8 iface, UINT Adapter) {
578 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
579 return IWineD3D_GetAdapterMonitor(This->WineD3D, Adapter);
582 static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display) {
583 const char *GL_Extensions = NULL;
584 const char *GLX_Extensions = NULL;
585 GLint gl_max;
586 const char* gl_string = NULL;
587 const char* gl_string_cursor = NULL;
588 Bool test = 0;
589 int major, minor;
590 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
592 if (This->gl_info.bIsFilled) return;
593 This->gl_info.bIsFilled = 1;
595 TRACE_(d3d_caps)("(%p, %p)\n", This, display);
597 if (NULL != display) {
598 test = glXQueryVersion(display, &major, &minor);
599 This->gl_info.glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
600 gl_string = glXGetClientString(display, GLX_VENDOR);
601 } else {
602 gl_string = glGetString(GL_VENDOR);
605 if (strstr(gl_string, "NVIDIA")) {
606 This->gl_info.gl_vendor = VENDOR_NVIDIA;
607 } else if (strstr(gl_string, "ATI")) {
608 This->gl_info.gl_vendor = VENDOR_ATI;
609 } else {
610 This->gl_info.gl_vendor = VENDOR_WINE;
613 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), This->gl_info.gl_vendor);
615 gl_string = glGetString(GL_VERSION);
616 switch (This->gl_info.gl_vendor) {
617 case VENDOR_NVIDIA:
618 gl_string_cursor = strstr(gl_string, "NVIDIA");
619 gl_string_cursor = strstr(gl_string_cursor, " ");
620 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
621 if (*gl_string_cursor) {
622 char tmp[16];
623 int cursor = 0;
625 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
626 tmp[cursor++] = *gl_string_cursor;
627 ++gl_string_cursor;
629 tmp[cursor] = 0;
630 major = atoi(tmp);
632 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
633 ++gl_string_cursor;
635 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
636 tmp[cursor++] = *gl_string_cursor;
637 ++gl_string_cursor;
639 tmp[cursor] = 0;
640 minor = atoi(tmp);
641 break;
643 case VENDOR_ATI:
644 major = minor = 0;
645 gl_string_cursor = strchr(gl_string, '-');
646 if (gl_string_cursor++) {
647 int error = 0;
648 /* Check if version number is of the form x.y.z */
649 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
650 error = 1;
651 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
652 error = 1;
653 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
654 error = 1;
655 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
656 error = 1;
657 /* Mark version number as malformed */
658 if (error)
659 gl_string_cursor = 0;
661 if (!gl_string_cursor)
662 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
663 else {
664 major = *gl_string_cursor - '0';
665 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
667 break;
668 default:
669 major = 0;
670 minor = 9;
672 This->gl_info.gl_driver_version = MAKEDWORD_VERSION(major, minor);
674 FIXME_(d3d_caps)("found GL_VERSION (%s)->(0x%08lx)\n", debugstr_a(gl_string), This->gl_info.gl_driver_version);
676 gl_string = glGetString(GL_RENDERER);
677 strcpy(This->gl_info.gl_renderer, gl_string);
679 switch (This->gl_info.gl_vendor) {
680 case VENDOR_NVIDIA:
681 if (strstr(This->gl_info.gl_renderer, "GeForce4 Ti")) {
682 This->gl_info.gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
683 } else if (strstr(This->gl_info.gl_renderer, "GeForceFX")) {
684 This->gl_info.gl_card = CARD_NVIDIA_GEFORCEFX_5900ULTRA;
685 } else {
686 This->gl_info.gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
688 break;
689 case VENDOR_ATI:
690 if (strstr(This->gl_info.gl_renderer, "RADEON 9800 PRO")) {
691 This->gl_info.gl_card = CARD_ATI_RADEON_9800PRO;
692 } else if (strstr(This->gl_info.gl_renderer, "RADEON 9700 PRO")) {
693 This->gl_info.gl_card = CARD_ATI_RADEON_9700PRO;
694 } else {
695 This->gl_info.gl_card = CARD_ATI_RADEON_8500;
697 break;
698 default:
699 This->gl_info.gl_card = CARD_WINE;
700 break;
703 FIXME_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(This->gl_info.gl_renderer), This->gl_info.gl_card);
706 * Initialize openGL extension related variables
707 * with Default values
709 memset(&This->gl_info.supported, 0, sizeof(This->gl_info.supported));
710 This->gl_info.max_textures = 1;
711 This->gl_info.ps_arb_version = PS_VERSION_NOT_SUPPORTED;
712 This->gl_info.vs_arb_version = VS_VERSION_NOT_SUPPORTED;
713 This->gl_info.vs_nv_version = VS_VERSION_NOT_SUPPORTED;
714 This->gl_info.vs_ati_version = VS_VERSION_NOT_SUPPORTED;
716 #define USE_GL_FUNC(type, pfn) This->gl_info.pfn = NULL;
717 GL_EXT_FUNCS_GEN;
718 #undef USE_GL_FUNC
720 /* Retrieve opengl defaults */
721 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
722 This->gl_info.max_clipplanes = min(MAX_CLIPPLANES, gl_max);
723 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
725 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
726 This->gl_info.max_lights = gl_max;
727 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
729 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
730 GL_Extensions = glGetString(GL_EXTENSIONS);
731 TRACE_(d3d_caps)("GL_Extensions reported:\n");
733 if (NULL == GL_Extensions) {
734 ERR(" GL_Extensions returns NULL\n");
735 } else {
736 while (*GL_Extensions != 0x00) {
737 const char *Start = GL_Extensions;
738 char ThisExtn[256];
740 memset(ThisExtn, 0x00, sizeof(ThisExtn));
741 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
742 GL_Extensions++;
744 memcpy(ThisExtn, Start, (GL_Extensions - Start));
745 TRACE_(d3d_caps)("- %s\n", ThisExtn);
748 * ARB
750 if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
751 This->gl_info.ps_arb_version = PS_VERSION_11;
752 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", This->gl_info.ps_arb_version);
753 This->gl_info.supported[ARB_FRAGMENT_PROGRAM] = TRUE;
754 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
755 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
756 This->gl_info.supported[ARB_MULTISAMPLE] = TRUE;
757 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
758 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
759 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
760 This->gl_info.supported[ARB_MULTITEXTURE] = TRUE;
761 This->gl_info.max_textures = min(8, gl_max);
762 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
763 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
764 This->gl_info.supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
765 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
766 This->gl_info.supported[NV_TEXGEN_REFLECTION] = TRUE;
767 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
768 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
769 This->gl_info.supported[ARB_TEXTURE_COMPRESSION] = TRUE;
770 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
771 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
772 This->gl_info.supported[ARB_TEXTURE_ENV_ADD] = TRUE;
773 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
774 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
775 This->gl_info.supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
776 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
777 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
778 This->gl_info.supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
779 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
780 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
781 This->gl_info.supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
782 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
783 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
784 This->gl_info.supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
785 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
786 This->gl_info.vs_arb_version = VS_VERSION_11;
787 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", This->gl_info.vs_arb_version);
788 This->gl_info.supported[ARB_VERTEX_PROGRAM] = TRUE;
791 * EXT
793 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
794 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
795 This->gl_info.supported[EXT_FOG_COORD] = TRUE;
796 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
797 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
798 This->gl_info.supported[EXT_PALETTED_TEXTURE] = TRUE;
799 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
800 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
801 This->gl_info.supported[EXT_POINT_PARAMETERS] = TRUE;
802 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
803 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
804 This->gl_info.supported[EXT_SECONDARY_COLOR] = TRUE;
805 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
806 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
807 This->gl_info.supported[EXT_STENCIL_WRAP] = TRUE;
808 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
809 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
810 This->gl_info.supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
811 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
812 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
813 This->gl_info.supported[EXT_TEXTURE_ENV_ADD] = TRUE;
814 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
815 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
816 This->gl_info.supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
817 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
818 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
819 This->gl_info.supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
820 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
821 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support\n");
822 This->gl_info.supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
823 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
824 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
825 This->gl_info.supported[EXT_TEXTURE_LOD] = TRUE;
826 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
827 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
828 This->gl_info.supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
829 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
830 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
831 This->gl_info.supported[EXT_VERTEX_WEIGHTING] = TRUE;
834 * NVIDIA
836 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
837 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
838 This->gl_info.supported[NV_FOG_DISTANCE] = TRUE;
839 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
840 This->gl_info.ps_nv_version = PS_VERSION_11;
841 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", This->gl_info.ps_nv_version);
842 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
843 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support\n");
844 This->gl_info.supported[NV_REGISTER_COMBINERS] = TRUE;
845 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
846 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
847 This->gl_info.supported[NV_REGISTER_COMBINERS2] = TRUE;
848 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
849 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
850 This->gl_info.supported[NV_TEXGEN_REFLECTION] = TRUE;
851 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
852 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
853 This->gl_info.supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
854 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
855 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
856 This->gl_info.supported[NV_TEXTURE_SHADER] = TRUE;
857 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
858 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
859 This->gl_info.supported[NV_TEXTURE_SHADER2] = TRUE;
860 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
861 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
862 This->gl_info.supported[NV_TEXTURE_SHADER3] = TRUE;
863 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
864 This->gl_info.vs_nv_version = max(This->gl_info.vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program1_1")) ? VS_VERSION_11 : VS_VERSION_10);
865 This->gl_info.vs_nv_version = max(This->gl_info.vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program2")) ? VS_VERSION_20 : VS_VERSION_10);
866 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", This->gl_info.vs_nv_version);
867 This->gl_info.supported[NV_VERTEX_PROGRAM] = TRUE;
870 * ATI
872 /** TODO */
873 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
874 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
875 This->gl_info.supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
876 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
877 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
878 This->gl_info.supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
879 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
880 This->gl_info.vs_ati_version = VS_VERSION_11;
881 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", This->gl_info.vs_ati_version);
882 This->gl_info.supported[EXT_VERTEX_SHADER] = TRUE;
886 if (*GL_Extensions == ' ') GL_Extensions++;
890 #define USE_GL_FUNC(type, pfn) This->gl_info.pfn = (type) glXGetProcAddressARB(#pfn);
891 GL_EXT_FUNCS_GEN;
892 #undef USE_GL_FUNC
894 if (display != NULL) {
895 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
896 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
898 if (NULL == GLX_Extensions) {
899 ERR(" GLX_Extensions returns NULL\n");
900 } else {
901 while (*GLX_Extensions != 0x00) {
902 const char *Start = GLX_Extensions;
903 char ThisExtn[256];
905 memset(ThisExtn, 0x00, sizeof(ThisExtn));
906 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
907 GLX_Extensions++;
909 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
910 TRACE_(d3d_caps)("- %s\n", ThisExtn);
911 if (*GLX_Extensions == ' ') GLX_Extensions++;
916 #define USE_GL_FUNC(type, pfn) This->gl_info.pfn = (type) glXGetProcAddressARB(#pfn);
917 GLX_EXT_FUNCS_GEN;
918 #undef USE_GL_FUNC
920 /* Only save the values obtained when a display is provided */
921 if (display != NULL) This->isGLInfoValid = TRUE;
925 HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
926 UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow,
927 DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters,
928 IDirect3DDevice8** ppReturnedDeviceInterface) {
929 IDirect3DDevice8Impl *object;
930 HWND whichHWND;
931 int num;
932 XVisualInfo template;
933 HDC hDc;
935 IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
936 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This, Adapter, DeviceType,
937 hFocusWindow, BehaviourFlags, pPresentationParameters, ppReturnedDeviceInterface);
939 if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
940 return D3DERR_INVALIDCALL;
943 /* Allocate the storage for the device */
944 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
945 if (NULL == object) {
946 return D3DERR_OUTOFVIDEOMEMORY;
948 object->lpVtbl = &Direct3DDevice8_Vtbl;
949 object->ref = 1;
950 object->direct3d8 = This;
951 /** The device AddRef the direct3d8 Interface else crash in propers clients codes */
952 IDirect3D8_AddRef((LPDIRECT3D8) object->direct3d8);
954 /** use StateBlock Factory here, for creating the startup stateBlock */
955 object->StateBlock = NULL;
956 IDirect3DDeviceImpl_CreateStateBlock(object, D3DSBT_ALL, NULL);
957 object->UpdateStateBlock = object->StateBlock;
959 /* Save the creation parameters */
960 object->CreateParms.AdapterOrdinal = Adapter;
961 object->CreateParms.DeviceType = DeviceType;
962 object->CreateParms.hFocusWindow = hFocusWindow;
963 object->CreateParms.BehaviorFlags = BehaviourFlags;
965 *ppReturnedDeviceInterface = (LPDIRECT3DDEVICE8) object;
967 /* Initialize settings */
968 object->PresentParms.BackBufferCount = 1; /* Opengl only supports one? */
969 object->adapterNo = Adapter;
970 object->devType = DeviceType;
972 /* Initialize openGl - Note the visual is chosen as the window is created and the glcontext cannot
973 use different properties after that point in time. FIXME: How to handle when requested format
974 doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
975 it chooses is identical to the one already being used! */
976 /* FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat */
978 /* Which hwnd are we using? */
979 whichHWND = pPresentationParameters->hDeviceWindow;
980 if (!whichHWND) {
981 whichHWND = hFocusWindow;
983 object->win_handle = whichHWND;
984 object->win = (Window)GetPropA( whichHWND, "__wine_x11_client_window" );
986 hDc = GetDC(whichHWND);
987 object->display = get_display(hDc);
989 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
990 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
991 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
993 ENTER_GL();
995 /* Create a context based off the properties of the existing visual */
996 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
997 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
998 if (NULL == object->visInfo) {
999 ERR("cannot really get XVisual\n");
1000 LEAVE_GL();
1001 return D3DERR_NOTAVAILABLE;
1003 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1004 if (NULL == object->glCtx) {
1005 ERR("cannot create glxContext\n");
1006 LEAVE_GL();
1007 return D3DERR_NOTAVAILABLE;
1009 LEAVE_GL();
1011 ReleaseDC(whichHWND, hDc);
1013 if (object->glCtx == NULL) {
1014 ERR("Error in context creation !\n");
1015 return D3DERR_INVALIDCALL;
1016 } else {
1017 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1018 whichHWND, object->glCtx, object->win, object->visInfo);
1021 /* If not windowed, need to go fullscreen, and resize the HWND to the appropriate */
1022 /* dimensions */
1023 if (!pPresentationParameters->Windowed) {
1024 #if 1
1025 DEVMODEW devmode;
1026 HDC hdc;
1027 int bpp = 0;
1028 memset(&devmode, 0, sizeof(DEVMODEW));
1029 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1030 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1031 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1032 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1033 DeleteDC(hdc);
1034 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp;/*Stupid XVidMode cannot change bpp D3DFmtGetBpp(object, pPresentationParameters->BackBufferFormat);*/
1035 devmode.dmPelsWidth = pPresentationParameters->BackBufferWidth;
1036 devmode.dmPelsHeight = pPresentationParameters->BackBufferHeight;
1037 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1038 #else
1039 FIXME("Requested full screen support not implemented, expect windowed operation\n");
1040 #endif
1042 /* Make popup window */
1043 SetWindowLongA(whichHWND, GWL_STYLE, WS_POPUP);
1044 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1045 pPresentationParameters->BackBufferWidth,
1046 pPresentationParameters->BackBufferHeight, SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1049 TRACE("Creating back buffer\n");
1050 /* MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1051 then the corresponding dimension of the client area of the hDeviceWindow
1052 (or the focus window, if hDeviceWindow is NULL) is taken. */
1053 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
1054 (pPresentationParameters->BackBufferHeight == 0))) {
1055 RECT Rect;
1057 GetClientRect(whichHWND, &Rect);
1059 if (pPresentationParameters->BackBufferWidth == 0) {
1060 pPresentationParameters->BackBufferWidth = Rect.right;
1061 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
1063 if (pPresentationParameters->BackBufferHeight == 0) {
1064 pPresentationParameters->BackBufferHeight = Rect.bottom;
1065 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
1069 /* Save the presentation parms now filled in correctly */
1070 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
1073 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
1074 pPresentationParameters->BackBufferWidth,
1075 pPresentationParameters->BackBufferHeight,
1076 pPresentationParameters->BackBufferFormat,
1077 pPresentationParameters->MultiSampleType,
1078 TRUE,
1079 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
1081 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
1082 pPresentationParameters->BackBufferWidth,
1083 pPresentationParameters->BackBufferHeight,
1084 pPresentationParameters->BackBufferFormat,
1085 pPresentationParameters->MultiSampleType,
1086 TRUE,
1087 (LPDIRECT3DSURFACE8*) &object->backBuffer);
1089 if (pPresentationParameters->EnableAutoDepthStencil) {
1090 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
1091 pPresentationParameters->BackBufferWidth,
1092 pPresentationParameters->BackBufferHeight,
1093 pPresentationParameters->AutoDepthStencilFormat,
1094 D3DMULTISAMPLE_NONE,
1095 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
1096 } else {
1097 object->depthStencilBuffer = NULL;
1099 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil @ %p\n",object->frontBuffer, object->backBuffer, object->depthStencilBuffer);
1101 /* init the default renderTarget management */
1102 object->drawable = object->win;
1103 object->render_ctx = object->glCtx;
1104 object->renderTarget = object->backBuffer;
1105 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->renderTarget);
1106 object->stencilBufferTarget = object->depthStencilBuffer;
1107 if (NULL != object->stencilBufferTarget) {
1108 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->stencilBufferTarget);
1111 ENTER_GL();
1113 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1114 ERR("Error in setting current context (context %p drawable %ld)!\n", object->glCtx, object->win);
1116 checkGLcall("glXMakeCurrent");
1118 /* Clear the screen */
1119 glClearColor(1.0, 0.0, 0.0, 0.0);
1120 checkGLcall("glClearColor");
1121 glColor3f(1.0, 1.0, 1.0);
1122 checkGLcall("glColor3f");
1124 glEnable(GL_LIGHTING);
1125 checkGLcall("glEnable");
1127 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1128 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1130 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1131 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1133 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1134 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1137 * Initialize openGL extension related variables
1138 * with Default values
1140 IDirect3D8Impl_FillGLCaps(iface, object->display);
1142 /* Setup all the devices defaults */
1143 IDirect3DDeviceImpl_InitStartupStateBlock(object);
1145 LEAVE_GL();
1147 { /* Set a default viewport */
1148 D3DVIEWPORT8 vp;
1149 vp.X = 0;
1150 vp.Y = 0;
1151 vp.Width = pPresentationParameters->BackBufferWidth;
1152 vp.Height = pPresentationParameters->BackBufferHeight;
1153 vp.MinZ = 0.0f;
1154 vp.MaxZ = 1.0f;
1155 IDirect3DDevice8Impl_SetViewport((LPDIRECT3DDEVICE8) object, &vp);
1158 /* Initialize the current view state */
1159 object->modelview_valid = 1;
1160 object->proj_valid = 0;
1161 object->view_ident = 1;
1162 object->last_was_rhw = 0;
1163 glGetIntegerv(GL_MAX_LIGHTS, &object->maxConcurrentLights);
1164 TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object);
1166 /* Clear the screen */
1167 IDirect3DDevice8Impl_Clear((LPDIRECT3DDEVICE8) object, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1169 return D3D_OK;
1172 IDirect3D8Vtbl Direct3D8_Vtbl =
1174 IDirect3D8Impl_QueryInterface,
1175 IDirect3D8Impl_AddRef,
1176 IDirect3D8Impl_Release,
1177 IDirect3D8Impl_RegisterSoftwareDevice,
1178 IDirect3D8Impl_GetAdapterCount,
1179 IDirect3D8Impl_GetAdapterIdentifier,
1180 IDirect3D8Impl_GetAdapterModeCount,
1181 IDirect3D8Impl_EnumAdapterModes,
1182 IDirect3D8Impl_GetAdapterDisplayMode,
1183 IDirect3D8Impl_CheckDeviceType,
1184 IDirect3D8Impl_CheckDeviceFormat,
1185 IDirect3D8Impl_CheckDeviceMultiSampleType,
1186 IDirect3D8Impl_CheckDepthStencilMatch,
1187 IDirect3D8Impl_GetDeviceCaps,
1188 IDirect3D8Impl_GetAdapterMonitor,
1189 IDirect3D8Impl_CreateDevice