2 * IWineD3D 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 /* Compile time diagnostics: */
25 /* Uncomment this to force only a single display mode to be exposed: */
26 /*#define DEBUG_SINGLE_MODE*/
30 #include "wined3d_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
33 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps
);
34 #define GLINFO_LOCATION This->gl_info
36 /**********************************************************
37 * Utility functions follow
38 **********************************************************/
40 /* x11drv GDI escapes */
41 #define X11DRV_ESCAPE 6789
42 enum x11drv_escape_codes
44 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
45 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
46 X11DRV_GET_FONT
, /* get current X font for a DC */
49 /* retrieve the X display to use on a given DC */
50 inline static Display
*get_display( HDC hdc
)
53 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
55 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
56 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
61 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
62 * ie there is no GL Context - Get a default rendering context to enable the
63 * function query some info from GL
65 static WineD3D_Context
* WineD3D_CreateFakeGLContext(void) {
66 static WineD3D_Context ctx
= { NULL
, NULL
, NULL
, 0, 0 };
67 WineD3D_Context
* ret
= NULL
;
69 if (glXGetCurrentContext() == NULL
) {
70 BOOL gotContext
= FALSE
;
77 XWindowAttributes win_attr
;
79 TRACE_(d3d_caps
)("Creating Fake GL Context\n");
81 ctx
.drawable
= (Drawable
) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
84 device_context
= GetDC(0);
85 ctx
.display
= get_display(device_context
);
86 ReleaseDC(0, device_context
);
88 /* Get the X visual */
90 if (XGetWindowAttributes(ctx
.display
, ctx
.drawable
, &win_attr
)) {
91 visual
= win_attr
.visual
;
93 visual
= DefaultVisual(ctx
.display
, DefaultScreen(ctx
.display
));
95 template.visualid
= XVisualIDFromVisual(visual
);
96 ctx
.visInfo
= XGetVisualInfo(ctx
.display
, VisualIDMask
, &template, &num
);
97 if (ctx
.visInfo
== NULL
) {
99 WARN_(d3d_caps
)("Error creating visual info for capabilities initialization\n");
103 /* Create a GL context */
105 ctx
.glCtx
= glXCreateContext(ctx
.display
, ctx
.visInfo
, NULL
, GL_TRUE
);
107 if (ctx
.glCtx
== NULL
) {
109 WARN_(d3d_caps
)("Error creating default context for capabilities initialization\n");
114 /* Make it the current GL context */
115 if (!failed
&& glXMakeCurrent(ctx
.display
, ctx
.drawable
, ctx
.glCtx
) == False
) {
116 glXDestroyContext(ctx
.display
, ctx
.glCtx
);
118 WARN_(d3d_caps
)("Error setting default context as current for capabilities initialization\n");
122 /* It worked! Wow... */
132 if (ctx
.ref
> 0) ret
= &ctx
;
135 if (NULL
!= ret
) InterlockedIncrement(&ret
->ref
);
139 static void WineD3D_ReleaseFakeGLContext(WineD3D_Context
* ctx
) {
140 /* If we created a dummy context, throw it away */
142 if (0 == InterlockedDecrement(&ctx
->ref
)) {
143 glXMakeCurrent(ctx
->display
, None
, NULL
);
144 glXDestroyContext(ctx
->display
, ctx
->glCtx
);
152 /**********************************************************
153 * IUnknown parts follows
154 **********************************************************/
156 HRESULT WINAPI
IWineD3DImpl_QueryInterface(IWineD3D
*iface
,REFIID riid
,LPVOID
*ppobj
)
158 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
159 /* FIXME: This needs to extend an IWineD3DBaseObject */
161 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
162 if (IsEqualGUID(riid
, &IID_IUnknown
)
163 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
164 IUnknown_AddRef(iface
);
169 return E_NOINTERFACE
;
172 ULONG WINAPI
IWineD3DImpl_AddRef(IWineD3D
*iface
) {
173 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
174 ULONG refCount
= InterlockedIncrement(&This
->ref
);
176 TRACE("(%p) : AddRef increasing from %ld\n", This
, refCount
- 1);
180 ULONG WINAPI
IWineD3DImpl_Release(IWineD3D
*iface
) {
181 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
183 TRACE("(%p) : Releasing from %ld\n", This
, This
->ref
);
184 ref
= InterlockedDecrement(&This
->ref
);
186 HeapFree(GetProcessHeap(), 0, This
);
192 /**********************************************************
193 * IWineD3D parts follows
194 **********************************************************/
196 static BOOL
IWineD3DImpl_FillGLCaps(WineD3D_GL_Info
*gl_info
, Display
* display
) {
197 const char *GL_Extensions
= NULL
;
198 const char *GLX_Extensions
= NULL
;
199 const char *gl_string
= NULL
;
200 const char *gl_string_cursor
= NULL
;
205 TRACE_(d3d_caps
)("(%p, %p)\n", gl_info
, display
);
207 /* Fill in the GL info retrievable depending on the display */
208 if (NULL
!= display
) {
209 test
= glXQueryVersion(display
, &major
, &minor
);
210 gl_info
->glx_version
= ((major
& 0x0000FFFF) << 16) | (minor
& 0x0000FFFF);
211 gl_string
= glXGetClientString(display
, GLX_VENDOR
);
213 gl_string
= glGetString(GL_VENDOR
);
216 /* Fill in the GL vendor */
217 if (strstr(gl_string
, "NVIDIA")) {
218 gl_info
->gl_vendor
= VENDOR_NVIDIA
;
219 } else if (strstr(gl_string
, "ATI")) {
220 gl_info
->gl_vendor
= VENDOR_ATI
;
222 gl_info
->gl_vendor
= VENDOR_WINE
;
225 TRACE_(d3d_caps
)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string
), gl_info
->gl_vendor
);
227 /* Parse the GL_VERSION field into major and minor information */
228 gl_string
= glGetString(GL_VERSION
);
229 switch (gl_info
->gl_vendor
) {
231 gl_string_cursor
= strstr(gl_string
, "NVIDIA");
232 gl_string_cursor
= strstr(gl_string_cursor
, " ");
233 while (*gl_string_cursor
&& ' ' == *gl_string_cursor
) ++gl_string_cursor
;
234 if (*gl_string_cursor
) {
238 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
239 tmp
[cursor
++] = *gl_string_cursor
;
245 if (*gl_string_cursor
!= '.') WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
248 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
249 tmp
[cursor
++] = *gl_string_cursor
;
259 gl_string_cursor
= strchr(gl_string
, '-');
260 if (gl_string_cursor
) {
264 /* Check if version number is of the form x.y.z */
265 if (*gl_string_cursor
> '9' && *gl_string_cursor
< '0')
267 if (!error
&& *(gl_string_cursor
+2) > '9' && *(gl_string_cursor
+2) < '0')
269 if (!error
&& *(gl_string_cursor
+4) > '9' && *(gl_string_cursor
+4) < '0')
271 if (!error
&& *(gl_string_cursor
+1) != '.' && *(gl_string_cursor
+3) != '.')
274 /* Mark version number as malformed */
276 gl_string_cursor
= 0;
279 if (!gl_string_cursor
)
280 WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
282 major
= *gl_string_cursor
- '0';
283 minor
= (*(gl_string_cursor
+2) - '0') * 256 + (*(gl_string_cursor
+4) - '0');
291 gl_info
->gl_driver_version
= MAKEDWORD_VERSION(major
, minor
);
292 TRACE_(d3d_caps
)("found GL_VERSION (%s)->(0x%08lx)\n", debugstr_a(gl_string
), gl_info
->gl_driver_version
);
294 /* Fill in the renderer information */
295 gl_string
= glGetString(GL_RENDERER
);
296 strcpy(gl_info
->gl_renderer
, gl_string
);
298 switch (gl_info
->gl_vendor
) {
300 if (strstr(gl_info
->gl_renderer
, "GeForce4 Ti")) {
301 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_TI4600
;
302 } else if (strstr(gl_info
->gl_renderer
, "GeForceFX")) {
303 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5900ULTRA
;
305 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_TI4600
;
310 if (strstr(gl_info
->gl_renderer
, "RADEON 9800 PRO")) {
311 gl_info
->gl_card
= CARD_ATI_RADEON_9800PRO
;
312 } else if (strstr(gl_info
->gl_renderer
, "RADEON 9700 PRO")) {
313 gl_info
->gl_card
= CARD_ATI_RADEON_9700PRO
;
315 gl_info
->gl_card
= CARD_ATI_RADEON_8500
;
320 gl_info
->gl_card
= CARD_WINE
;
324 TRACE_(d3d_caps
)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info
->gl_renderer
), gl_info
->gl_card
);
327 * Initialize openGL extension related variables
328 * with Default values
330 memset(&gl_info
->supported
, 0, sizeof(gl_info
->supported
));
331 gl_info
->max_textures
= 1;
332 gl_info
->ps_arb_version
= PS_VERSION_NOT_SUPPORTED
;
333 gl_info
->vs_arb_version
= VS_VERSION_NOT_SUPPORTED
;
334 gl_info
->vs_nv_version
= VS_VERSION_NOT_SUPPORTED
;
335 gl_info
->vs_ati_version
= VS_VERSION_NOT_SUPPORTED
;
337 /* Now work out what GL support this card really has */
338 #define USE_GL_FUNC(type, pfn) gl_info->pfn = NULL;
342 /* Retrieve opengl defaults */
343 glGetIntegerv(GL_MAX_CLIP_PLANES
, &gl_max
);
344 gl_info
->max_clipplanes
= min(D3DMAXUSERCLIPPLANES
, gl_max
);
345 TRACE_(d3d_caps
)("ClipPlanes support - num Planes=%d\n", gl_max
);
347 glGetIntegerv(GL_MAX_LIGHTS
, &gl_max
);
348 gl_info
->max_lights
= gl_max
;
349 TRACE_(d3d_caps
)("Lights support - max lights=%d\n", gl_max
);
351 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
352 GL_Extensions
= glGetString(GL_EXTENSIONS
);
353 TRACE_(d3d_caps
)("GL_Extensions reported:\n");
355 if (NULL
== GL_Extensions
) {
356 ERR(" GL_Extensions returns NULL\n");
358 while (*GL_Extensions
!= 0x00) {
359 const char *Start
= GL_Extensions
;
362 memset(ThisExtn
, 0x00, sizeof(ThisExtn
));
363 while (*GL_Extensions
!= ' ' && *GL_Extensions
!= 0x00) {
366 memcpy(ThisExtn
, Start
, (GL_Extensions
- Start
));
367 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
372 if (strcmp(ThisExtn
, "GL_ARB_fragment_program") == 0) {
373 gl_info
->ps_arb_version
= PS_VERSION_11
;
374 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info
->ps_arb_version
);
375 gl_info
->supported
[ARB_FRAGMENT_PROGRAM
] = TRUE
;
376 } else if (strcmp(ThisExtn
, "GL_ARB_multisample") == 0) {
377 TRACE_(d3d_caps
)(" FOUND: ARB Multisample support\n");
378 gl_info
->supported
[ARB_MULTISAMPLE
] = TRUE
;
379 } else if (strcmp(ThisExtn
, "GL_ARB_multitexture") == 0) {
380 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB
, &gl_max
);
381 TRACE_(d3d_caps
)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max
);
382 gl_info
->supported
[ARB_MULTITEXTURE
] = TRUE
;
383 gl_info
->max_textures
= min(8, gl_max
);
384 } else if (strcmp(ThisExtn
, "GL_ARB_texture_cube_map") == 0) {
385 TRACE_(d3d_caps
)(" FOUND: ARB Texture Cube Map support\n");
386 gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
] = TRUE
;
387 TRACE_(d3d_caps
)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
388 gl_info
->supported
[NV_TEXGEN_REFLECTION
] = TRUE
;
389 } else if (strcmp(ThisExtn
, "GL_ARB_texture_compression") == 0) {
390 TRACE_(d3d_caps
)(" FOUND: ARB Texture Compression support\n");
391 gl_info
->supported
[ARB_TEXTURE_COMPRESSION
] = TRUE
;
392 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_add") == 0) {
393 TRACE_(d3d_caps
)(" FOUND: ARB Texture Env Add support\n");
394 gl_info
->supported
[ARB_TEXTURE_ENV_ADD
] = TRUE
;
395 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_combine") == 0) {
396 TRACE_(d3d_caps
)(" FOUND: ARB Texture Env combine support\n");
397 gl_info
->supported
[ARB_TEXTURE_ENV_COMBINE
] = TRUE
;
398 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_dot3") == 0) {
399 TRACE_(d3d_caps
)(" FOUND: ARB Dot3 support\n");
400 gl_info
->supported
[ARB_TEXTURE_ENV_DOT3
] = TRUE
;
401 } else if (strcmp(ThisExtn
, "GL_ARB_texture_border_clamp") == 0) {
402 TRACE_(d3d_caps
)(" FOUND: ARB Texture border clamp support\n");
403 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] = TRUE
;
404 } else if (strcmp(ThisExtn
, "GL_ARB_texture_mirrored_repeat") == 0) {
405 TRACE_(d3d_caps
)(" FOUND: ARB Texture mirrored repeat support\n");
406 gl_info
->supported
[ARB_TEXTURE_MIRRORED_REPEAT
] = TRUE
;
407 } else if (strstr(ThisExtn
, "GL_ARB_vertex_program")) {
408 gl_info
->vs_arb_version
= VS_VERSION_11
;
409 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info
->vs_arb_version
);
410 gl_info
->supported
[ARB_VERTEX_PROGRAM
] = TRUE
;
411 } else if (strcmp(ThisExtn
, "GL_ARB_vertex_blend") == 0) {
412 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Blend support\n");
413 gl_info
->supported
[ARB_VERTEX_BLEND
] = TRUE
;
414 } else if (strcmp(ThisExtn
, "GL_ARB_vertex_buffer_object") == 0) {
415 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Buffer support\n");
416 gl_info
->supported
[ARB_VERTEX_BUFFER_OBJECT
] = TRUE
;
421 } else if (strcmp(ThisExtn
, "GL_EXT_fog_coord") == 0) {
422 TRACE_(d3d_caps
)(" FOUND: EXT Fog coord support\n");
423 gl_info
->supported
[EXT_FOG_COORD
] = TRUE
;
424 } else if (strcmp(ThisExtn
, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
425 TRACE_(d3d_caps
)(" FOUND: EXT Paletted texture support\n");
426 gl_info
->supported
[EXT_PALETTED_TEXTURE
] = TRUE
;
427 } else if (strcmp(ThisExtn
, "GL_EXT_point_parameters") == 0) {
428 TRACE_(d3d_caps
)(" FOUND: EXT Point parameters support\n");
429 gl_info
->supported
[EXT_POINT_PARAMETERS
] = TRUE
;
430 } else if (strcmp(ThisExtn
, "GL_EXT_secondary_color") == 0) {
431 TRACE_(d3d_caps
)(" FOUND: EXT Secondary coord support\n");
432 gl_info
->supported
[EXT_SECONDARY_COLOR
] = TRUE
;
433 } else if (strcmp(ThisExtn
, "GL_EXT_stencil_wrap") == 0) {
434 TRACE_(d3d_caps
)(" FOUND: EXT Stencil wrap support\n");
435 gl_info
->supported
[EXT_STENCIL_WRAP
] = TRUE
;
436 } else if (strcmp(ThisExtn
, "GL_EXT_texture_compression_s3tc") == 0) {
437 TRACE_(d3d_caps
)(" FOUND: EXT Texture S3TC compression support\n");
438 gl_info
->supported
[EXT_TEXTURE_COMPRESSION_S3TC
] = TRUE
;
439 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_add") == 0) {
440 TRACE_(d3d_caps
)(" FOUND: EXT Texture Env Add support\n");
441 gl_info
->supported
[EXT_TEXTURE_ENV_ADD
] = TRUE
;
442 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_combine") == 0) {
443 TRACE_(d3d_caps
)(" FOUND: EXT Texture Env combine support\n");
444 gl_info
->supported
[EXT_TEXTURE_ENV_COMBINE
] = TRUE
;
445 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_dot3") == 0) {
446 TRACE_(d3d_caps
)(" FOUND: EXT Dot3 support\n");
447 gl_info
->supported
[EXT_TEXTURE_ENV_DOT3
] = TRUE
;
448 } else if (strcmp(ThisExtn
, "GL_EXT_texture_filter_anisotropic") == 0) {
449 TRACE_(d3d_caps
)(" FOUND: EXT Texture Anisotropic filter support\n");
450 gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] = TRUE
;
451 } else if (strcmp(ThisExtn
, "GL_EXT_texture_lod") == 0) {
452 TRACE_(d3d_caps
)(" FOUND: EXT Texture LOD support\n");
453 gl_info
->supported
[EXT_TEXTURE_LOD
] = TRUE
;
454 } else if (strcmp(ThisExtn
, "GL_EXT_texture_lod_bias") == 0) {
455 TRACE_(d3d_caps
)(" FOUND: EXT Texture LOD bias support\n");
456 gl_info
->supported
[EXT_TEXTURE_LOD_BIAS
] = TRUE
;
457 } else if (strcmp(ThisExtn
, "GL_EXT_vertex_weighting") == 0) {
458 TRACE_(d3d_caps
)(" FOUND: EXT Vertex weighting support\n");
459 gl_info
->supported
[EXT_VERTEX_WEIGHTING
] = TRUE
;
464 } else if (strstr(ThisExtn
, "GL_NV_fog_distance")) {
465 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Fog Distance support\n");
466 gl_info
->supported
[NV_FOG_DISTANCE
] = TRUE
;
467 } else if (strstr(ThisExtn
, "GL_NV_fragment_program")) {
468 gl_info
->ps_nv_version
= PS_VERSION_11
;
469 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info
->ps_nv_version
);
470 } else if (strcmp(ThisExtn
, "GL_NV_register_combiners") == 0) {
471 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Register combiners (1) support\n");
472 gl_info
->supported
[NV_REGISTER_COMBINERS
] = TRUE
;
473 } else if (strcmp(ThisExtn
, "GL_NV_register_combiners2") == 0) {
474 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
475 gl_info
->supported
[NV_REGISTER_COMBINERS2
] = TRUE
;
476 } else if (strcmp(ThisExtn
, "GL_NV_texgen_reflection") == 0) {
477 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
478 gl_info
->supported
[NV_TEXGEN_REFLECTION
] = TRUE
;
479 } else if (strcmp(ThisExtn
, "GL_NV_texture_env_combine4") == 0) {
480 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
481 gl_info
->supported
[NV_TEXTURE_ENV_COMBINE4
] = TRUE
;
482 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader") == 0) {
483 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
484 gl_info
->supported
[NV_TEXTURE_SHADER
] = TRUE
;
485 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader2") == 0) {
486 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
487 gl_info
->supported
[NV_TEXTURE_SHADER2
] = TRUE
;
488 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader3") == 0) {
489 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
490 gl_info
->supported
[NV_TEXTURE_SHADER3
] = TRUE
;
491 } else if (strstr(ThisExtn
, "GL_NV_vertex_program")) {
492 gl_info
->vs_nv_version
= max(gl_info
->vs_nv_version
, (0 == strcmp(ThisExtn
, "GL_NV_vertex_program1_1")) ? VS_VERSION_11
: VS_VERSION_10
);
493 gl_info
->vs_nv_version
= max(gl_info
->vs_nv_version
, (0 == strcmp(ThisExtn
, "GL_NV_vertex_program2")) ? VS_VERSION_20
: VS_VERSION_10
);
494 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info
->vs_nv_version
);
495 gl_info
->supported
[NV_VERTEX_PROGRAM
] = TRUE
;
501 } else if (strcmp(ThisExtn
, "GL_ATI_texture_env_combine3") == 0) {
502 TRACE_(d3d_caps
)(" FOUND: ATI Texture Env combine (3) support\n");
503 gl_info
->supported
[ATI_TEXTURE_ENV_COMBINE3
] = TRUE
;
504 } else if (strcmp(ThisExtn
, "GL_ATI_texture_mirror_once") == 0) {
505 TRACE_(d3d_caps
)(" FOUND: ATI Texture Mirror Once support\n");
506 gl_info
->supported
[ATI_TEXTURE_MIRROR_ONCE
] = TRUE
;
507 } else if (strcmp(ThisExtn
, "GL_EXT_vertex_shader") == 0) {
508 gl_info
->vs_ati_version
= VS_VERSION_11
;
509 TRACE_(d3d_caps
)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info
->vs_ati_version
);
510 gl_info
->supported
[EXT_VERTEX_SHADER
] = TRUE
;
514 if (*GL_Extensions
== ' ') GL_Extensions
++;
518 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB(#pfn);
522 if (display
!= NULL
) {
523 GLX_Extensions
= glXQueryExtensionsString(display
, DefaultScreen(display
));
524 TRACE_(d3d_caps
)("GLX_Extensions reported:\n");
526 if (NULL
== GLX_Extensions
) {
527 ERR(" GLX_Extensions returns NULL\n");
529 while (*GLX_Extensions
!= 0x00) {
530 const char *Start
= GLX_Extensions
;
533 memset(ThisExtn
, 0x00, sizeof(ThisExtn
));
534 while (*GLX_Extensions
!= ' ' && *GLX_Extensions
!= 0x00) {
537 memcpy(ThisExtn
, Start
, (GLX_Extensions
- Start
));
538 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
539 if (*GLX_Extensions
== ' ') GLX_Extensions
++;
544 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB(#pfn);
548 /* Only save the values obtained when a display is provided */
549 if (display
!= NULL
) {
556 /**********************************************************
557 * IWineD3D implementation follows
558 **********************************************************/
560 UINT WINAPI
IWineD3DImpl_GetAdapterCount (IWineD3D
*iface
) {
561 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
563 /* FIXME: Set to one for now to imply the display */
564 TRACE_(d3d_caps
)("(%p): Mostly stub, only returns primary display\n", This
);
568 HRESULT WINAPI
IWineD3DImpl_RegisterSoftwareDevice(IWineD3D
*iface
, void* pInitializeFunction
) {
569 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
570 FIXME("(%p)->(%p): stub\n", This
, pInitializeFunction
);
574 HMONITOR WINAPI
IWineD3DImpl_GetAdapterMonitor(IWineD3D
*iface
, UINT Adapter
) {
575 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
576 FIXME_(d3d_caps
)("(%p)->(Adptr:%d)\n", This
, Adapter
);
577 if (Adapter
>= IWineD3DImpl_GetAdapterCount(iface
)) {
583 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
584 of the same bpp but different resolutions */
586 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
587 UINT WINAPI
IWineD3DImpl_GetAdapterModeCount(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
) {
588 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
589 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Format: %s)\n", This
, Adapter
, debug_d3dformat(Format
));
591 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
595 if (Adapter
== 0) { /* Display */
598 #if !defined( DEBUG_SINGLE_MODE )
601 /* Work out the current screen bpp */
602 HDC hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
603 int bpp
= GetDeviceCaps(hdc
, BITSPIXEL
);
606 while (EnumDisplaySettingsExW(NULL
, j
, &DevModeW
, 0)) {
613 case D3DFMT_X8R8G8B8
:
614 case D3DFMT_A8R8G8B8
:
615 if (min(DevModeW
.dmBitsPerPel
, bpp
) == 32) i
++;
616 if (min(DevModeW
.dmBitsPerPel
, bpp
) == 24) i
++;
618 case D3DFMT_X1R5G5B5
:
619 case D3DFMT_A1R5G5B5
:
621 if (min(DevModeW
.dmBitsPerPel
, bpp
) == 16) i
++;
624 /* Skip other modes as they do not match requested format */
632 TRACE_(d3d_caps
)("(%p}->(Adapter: %d) => %d (out of %d)\n", This
, Adapter
, i
, j
);
635 FIXME_(d3d_caps
)("Adapter not primary display\n");
640 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
641 HRESULT WINAPI
IWineD3DImpl_EnumAdapterModes(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
, UINT Mode
, D3DDISPLAYMODE
* pMode
) {
642 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
643 TRACE_(d3d_caps
)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This
, Adapter
, Mode
, pMode
, debug_d3dformat(Format
));
645 /* Validate the parameters as much as possible */
647 Adapter
>= IWineD3DImpl_GetAdapterCount(iface
) ||
648 Mode
>= IWineD3DImpl_GetAdapterModeCount(iface
, Adapter
, Format
)) {
649 return D3DERR_INVALIDCALL
;
652 if (Adapter
== 0) { /* Display */
653 #if !defined( DEBUG_SINGLE_MODE )
657 /* Work out the current screen bpp */
658 HDC hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
659 int bpp
= GetDeviceCaps(hdc
, BITSPIXEL
);
662 /* If we are filtering to a specific format, then need to skip all unrelated
663 modes, but if mode is irrelevant, then we can use the index directly */
664 if (Format
== D3DFMT_UNKNOWN
)
670 DEVMODEW DevModeWtmp
;
673 while (i
<(Mode
+1) && EnumDisplaySettingsExW(NULL
, j
, &DevModeWtmp
, 0)) {
680 case D3DFMT_X8R8G8B8
:
681 case D3DFMT_A8R8G8B8
:
682 if (min(DevModeWtmp
.dmBitsPerPel
, bpp
) == 32) i
++;
683 if (min(DevModeWtmp
.dmBitsPerPel
, bpp
) == 24) i
++;
685 case D3DFMT_X1R5G5B5
:
686 case D3DFMT_A1R5G5B5
:
688 if (min(DevModeWtmp
.dmBitsPerPel
, bpp
) == 16) i
++;
691 /* Skip other modes as they do not match requested format */
698 /* Now get the display mode via the calculated index */
699 if (EnumDisplaySettingsExW(NULL
, ModeIdx
, &DevModeW
, 0))
701 pMode
->Width
= DevModeW
.dmPelsWidth
;
702 pMode
->Height
= DevModeW
.dmPelsHeight
;
703 bpp
= min(DevModeW
.dmBitsPerPel
, bpp
);
704 pMode
->RefreshRate
= D3DADAPTER_DEFAULT
;
705 if (DevModeW
.dmFields
&DM_DISPLAYFREQUENCY
)
707 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
710 if (Format
== D3DFMT_UNKNOWN
)
713 case 8: pMode
->Format
= D3DFMT_R3G3B2
; break;
714 case 16: pMode
->Format
= D3DFMT_R5G6B5
; break;
715 case 24: /* pMode->Format = D3DFMT_R5G6B5; break;*/ /* Make 24bit appear as 32 bit */
716 case 32: pMode
->Format
= D3DFMT_A8R8G8B8
; break;
717 default: pMode
->Format
= D3DFMT_UNKNOWN
;
720 pMode
->Format
= Format
;
725 TRACE_(d3d_caps
)("Requested mode out of range %d\n", Mode
);
726 return D3DERR_INVALIDCALL
;
730 /* Return one setting of the format requested */
731 if (Mode
> 0) return D3DERR_INVALIDCALL
;
734 pMode
->RefreshRate
= D3DADAPTER_DEFAULT
;
735 pMode
->Format
= (Format
==D3DFMT_UNKNOWN
)?D3DFMT_A8R8G8B8
:Format
;
738 TRACE_(d3d_caps
)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode
->Width
, pMode
->Height
,
739 pMode
->RefreshRate
, pMode
->Format
, debug_d3dformat(pMode
->Format
), bpp
);
742 FIXME_(d3d_caps
)("Adapter not primary display\n");
748 HRESULT WINAPI
IWineD3DImpl_GetAdapterDisplayMode(IWineD3D
*iface
, UINT Adapter
, D3DDISPLAYMODE
* pMode
) {
749 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
750 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, pMode: %p)\n", This
, Adapter
, pMode
);
753 Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
754 return D3DERR_INVALIDCALL
;
757 if (Adapter
== 0) { /* Display */
761 EnumDisplaySettingsExW(NULL
, (DWORD
)-1, &DevModeW
, 0);
762 pMode
->Width
= DevModeW
.dmPelsWidth
;
763 pMode
->Height
= DevModeW
.dmPelsHeight
;
764 bpp
= DevModeW
.dmBitsPerPel
;
765 pMode
->RefreshRate
= D3DADAPTER_DEFAULT
;
766 if (DevModeW
.dmFields
&DM_DISPLAYFREQUENCY
)
768 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
772 case 8: pMode
->Format
= D3DFMT_R3G3B2
; break;
773 case 16: pMode
->Format
= D3DFMT_R5G6B5
; break;
774 case 24: /*pMode->Format = D3DFMT_R5G6B5; break;*/ /* Make 24bit appear as 32 bit */
775 case 32: pMode
->Format
= D3DFMT_A8R8G8B8
; break;
776 default: pMode
->Format
= D3DFMT_UNKNOWN
;
780 FIXME_(d3d_caps
)("Adapter not primary display\n");
783 TRACE_(d3d_caps
)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode
->Width
,
784 pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
788 /* Note due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
789 and fields being inserted in the middle, a new structure is used in place */
790 HRESULT WINAPI
IWineD3DImpl_GetAdapterIdentifier(IWineD3D
*iface
, UINT Adapter
, DWORD Flags
,
791 WINED3DADAPTER_IDENTIFIER
* pIdentifier
) {
792 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
794 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This
, Adapter
, Flags
, pIdentifier
);
796 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
797 return D3DERR_INVALIDCALL
;
800 if (Adapter
== 0) { /* Display - only device supported for now */
802 BOOL isGLInfoValid
= This
->isGLInfoValid
;
804 /* FillGLCaps updates gl_info, but we only want to store and
805 reuse the values once we have a context which is valid. Values from
806 a temporary context may differ from the final ones */
807 if (isGLInfoValid
== FALSE
) {
809 /* If we don't know the device settings, go query them now via a
811 WineD3D_Context
* ctx
= WineD3D_CreateFakeGLContext();
813 isGLInfoValid
= IWineD3DImpl_FillGLCaps(&This
->gl_info
, ctx
->display
);
814 WineD3D_ReleaseFakeGLContext(ctx
);
818 /* If it worked, return the information requested */
820 TRACE_(d3d_caps
)("device/Vendor Name and Version detection using FillGLCaps\n");
821 strcpy(pIdentifier
->Driver
, "Display");
822 strcpy(pIdentifier
->Description
, "Direct3D HAL");
824 /* Note dx8 doesn't supply a DeviceName */
825 if (NULL
!= pIdentifier
->DeviceName
) strcpy(pIdentifier
->DeviceName
, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
826 pIdentifier
->DriverVersion
->u
.HighPart
= 0xa;
827 pIdentifier
->DriverVersion
->u
.LowPart
= This
->gl_info
.gl_driver_version
;
828 *(pIdentifier
->VendorId
) = This
->gl_info
.gl_vendor
;
829 *(pIdentifier
->DeviceId
) = This
->gl_info
.gl_card
;
830 *(pIdentifier
->SubSysId
) = 0;
831 *(pIdentifier
->Revision
) = 0;
835 /* If it failed, return dummy values from an NVidia driver */
836 WARN_(d3d_caps
)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
837 strcpy(pIdentifier
->Driver
, "Display");
838 strcpy(pIdentifier
->Description
, "Direct3D HAL");
839 if (NULL
!= pIdentifier
->DeviceName
) strcpy(pIdentifier
->DeviceName
, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
840 pIdentifier
->DriverVersion
->u
.HighPart
= 0xa;
841 pIdentifier
->DriverVersion
->u
.LowPart
= MAKEDWORD_VERSION(53, 96); /* last Linux Nvidia drivers */
842 *(pIdentifier
->VendorId
) = VENDOR_NVIDIA
;
843 *(pIdentifier
->DeviceId
) = CARD_NVIDIA_GEFORCE4_TI4600
;
844 *(pIdentifier
->SubSysId
) = 0;
845 *(pIdentifier
->Revision
) = 0;
848 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
849 if (Flags
& D3DENUM_NO_WHQL_LEVEL
) {
850 *(pIdentifier
->WHQLLevel
) = 0;
852 *(pIdentifier
->WHQLLevel
) = 1;
856 FIXME_(d3d_caps
)("Adapter not primary display\n");
862 static BOOL
IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context
* ctx
, GLXFBConfig cfgs
, WINED3DFORMAT Format
) {
864 int rb
, gb
, bb
, ab
, type
, buf_sz
;
866 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_RED_SIZE
, &rb
);
867 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_GREEN_SIZE
, &gb
);
868 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_BLUE_SIZE
, &bb
);
869 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_ALPHA_SIZE
, &ab
);
870 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_RENDER_TYPE
, &type
);
871 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_BUFFER_SIZE
, &buf_sz
);
874 case WINED3DFMT_X8R8G8B8
:
875 case WINED3DFMT_R8G8B8
:
876 if (8 == rb
&& 8 == gb
&& 8 == bb
) return TRUE
;
878 case WINED3DFMT_A8R8G8B8
:
879 if (8 == rb
&& 8 == gb
&& 8 == bb
&& 8 == ab
) return TRUE
;
881 case WINED3DFMT_X1R5G5B5
:
882 if (5 == rb
&& 5 == gb
&& 5 == bb
) return TRUE
;
884 case WINED3DFMT_A1R5G5B5
:
885 if (5 == rb
&& 5 == gb
&& 5 == bb
&& 1 == ab
) return TRUE
;
887 case WINED3DFMT_R5G6B5
:
888 if (5 == rb
&& 6 == gb
&& 5 == bb
) return TRUE
;
890 case WINED3DFMT_R3G3B2
:
891 if (3 == rb
&& 3 == gb
&& 2 == bb
) return TRUE
;
893 case WINED3DFMT_A8P8
:
894 if (type
& GLX_COLOR_INDEX_BIT
&& 8 == buf_sz
&& 8 == ab
) return TRUE
;
897 if (type
& GLX_COLOR_INDEX_BIT
&& 8 == buf_sz
) return TRUE
;
900 ERR("unsupported format %s\n", debug_d3dformat(Format
));
906 static BOOL
IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context
* ctx
, GLXFBConfig cfgs
, WINED3DFORMAT Format
) {
910 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_DEPTH_SIZE
, &db
);
911 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_STENCIL_SIZE
, &sb
);
915 case WINED3DFMT_D16_LOCKABLE
:
916 if (16 == db
) return TRUE
;
919 if (32 == db
) return TRUE
;
921 case WINED3DFMT_D15S1
:
922 if (15 == db
) return TRUE
;
924 case WINED3DFMT_D24S8
:
925 if (24 == db
&& 8 == sb
) return TRUE
;
927 case WINED3DFMT_D24X8
:
928 if (24 == db
) return TRUE
;
930 case WINED3DFMT_D24X4S4
:
931 if (24 == db
&& 4 == sb
) return TRUE
;
933 case WINED3DFMT_D32F_LOCKABLE
:
934 if (32 == db
) return TRUE
;
937 ERR("unsupported format %s\n", debug_d3dformat(Format
));
943 HRESULT WINAPI
IWineD3DImpl_CheckDepthStencilMatch(IWineD3D
*iface
, UINT Adapter
, D3DDEVTYPE DeviceType
,
944 WINED3DFORMAT AdapterFormat
,
945 WINED3DFORMAT RenderTargetFormat
,
946 WINED3DFORMAT DepthStencilFormat
) {
947 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
948 WARN_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
950 DeviceType
, debug_d3ddevicetype(DeviceType
),
951 AdapterFormat
, debug_d3dformat(AdapterFormat
),
952 RenderTargetFormat
, debug_d3dformat(RenderTargetFormat
),
953 DepthStencilFormat
, debug_d3dformat(DepthStencilFormat
));
955 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
956 return D3DERR_INVALIDCALL
;
960 GLXFBConfig
* cfgs
= NULL
;
963 HRESULT hr
= D3DERR_NOTAVAILABLE
;
965 WineD3D_Context
* ctx
= WineD3D_CreateFakeGLContext();
967 cfgs
= glXGetFBConfigs(ctx
->display
, DefaultScreen(ctx
->display
), &nCfgs
);
968 for (it
= 0; it
< nCfgs
; ++it
) {
969 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx
, cfgs
[it
], RenderTargetFormat
)) {
970 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx
, cfgs
[it
], DepthStencilFormat
)) {
978 WineD3D_ReleaseFakeGLContext(ctx
);
983 return D3DERR_NOTAVAILABLE
;
986 HRESULT WINAPI
IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D
*iface
, UINT Adapter
, D3DDEVTYPE DeviceType
,
987 WINED3DFORMAT SurfaceFormat
,
988 BOOL Windowed
, D3DMULTISAMPLE_TYPE MultiSampleType
, DWORD
* pQualityLevels
) {
990 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
991 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
994 DeviceType
, debug_d3ddevicetype(DeviceType
),
995 SurfaceFormat
, debug_d3dformat(SurfaceFormat
),
1000 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1001 return D3DERR_INVALIDCALL
;
1004 if (pQualityLevels
!= NULL
) {
1005 static int s_single_shot
= 0;
1006 if (!s_single_shot
) {
1007 FIXME("Quality levels unsupported at present\n");
1010 *pQualityLevels
= 1; /* Guess at a value! */
1013 if (D3DMULTISAMPLE_NONE
== MultiSampleType
) return D3D_OK
;
1014 return D3DERR_NOTAVAILABLE
;
1017 HRESULT WINAPI
IWineD3DImpl_CheckDeviceType(IWineD3D
*iface
, UINT Adapter
, D3DDEVTYPE CheckType
,
1018 WINED3DFORMAT DisplayFormat
, WINED3DFORMAT BackBufferFormat
, BOOL Windowed
) {
1020 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1021 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1024 CheckType
, debug_d3ddevicetype(CheckType
),
1025 DisplayFormat
, debug_d3dformat(DisplayFormat
),
1026 BackBufferFormat
, debug_d3dformat(BackBufferFormat
),
1029 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1030 return D3DERR_INVALIDCALL
;
1034 GLXFBConfig
* cfgs
= NULL
;
1037 HRESULT hr
= D3DERR_NOTAVAILABLE
;
1039 WineD3D_Context
* ctx
= WineD3D_CreateFakeGLContext();
1041 cfgs
= glXGetFBConfigs(ctx
->display
, DefaultScreen(ctx
->display
), &nCfgs
);
1042 for (it
= 0; it
< nCfgs
; ++it
) {
1043 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx
, cfgs
[it
], DisplayFormat
)) {
1050 WineD3D_ReleaseFakeGLContext(ctx
);
1055 return D3DERR_NOTAVAILABLE
;
1058 HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormat(IWineD3D
*iface
, UINT Adapter
, D3DDEVTYPE DeviceType
,
1059 WINED3DFORMAT AdapterFormat
, DWORD Usage
, D3DRESOURCETYPE RType
, WINED3DFORMAT CheckFormat
) {
1060 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1061 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
1064 DeviceType
, debug_d3ddevicetype(DeviceType
),
1065 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1066 Usage
, debug_d3dusage(Usage
),
1067 RType
, debug_d3dresourcetype(RType
),
1068 CheckFormat
, debug_d3dformat(CheckFormat
));
1070 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1071 return D3DERR_INVALIDCALL
;
1074 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
1075 switch (CheckFormat
) {
1079 TRACE_(d3d_caps
)("[OK]\n");
1082 break; /* Avoid compiler warnings */
1086 switch (CheckFormat
) {
1088 * check supported using GL_SUPPORT
1099 /*case D3DFMT_R5G6B5: */
1100 /*case D3DFMT_X1R5G5B5:*/
1101 /*case D3DFMT_A1R5G5B5: */
1102 /*case D3DFMT_A4R4G4B4:*/
1109 /*case D3DFMT_X8R8G8B8:*/
1110 case D3DFMT_A8R3G3B2
:
1127 case D3DFMT_X8L8V8U8
:
1128 case D3DFMT_Q8W8V8U8
:
1129 case D3DFMT_W11V11U10
:
1132 * currently hard to support
1137 /* Since we do not support these formats right now, don't pretend to. */
1138 TRACE_(d3d_caps
)("[FAILED]\n");
1139 return D3DERR_NOTAVAILABLE
;
1144 TRACE_(d3d_caps
)("[OK]\n");
1148 HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D
*iface
, UINT Adapter
, D3DDEVTYPE DeviceType
,
1149 WINED3DFORMAT SourceFormat
, WINED3DFORMAT TargetFormat
) {
1150 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1152 FIXME_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))",
1155 DeviceType
, debug_d3ddevicetype(DeviceType
),
1156 SourceFormat
, debug_d3dformat(SourceFormat
),
1157 TargetFormat
, debug_d3dformat(TargetFormat
));
1161 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1162 subset of a D3DCAPS9 structure. However, it has to come via a void *
1163 as the d3d8 interface cannot import the d3d9 header */
1164 HRESULT WINAPI
IWineD3DImpl_GetDeviceCaps(IWineD3D
*iface
, UINT Adapter
, D3DDEVTYPE DeviceType
, WINED3DCAPS
* pCaps
) {
1166 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1167 BOOL gotContext
= FALSE
;
1168 GLint gl_tex_size
= 0;
1169 WineD3D_Context
*fake_ctx
= NULL
;
1171 TRACE_(d3d_caps
)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This
, Adapter
, DeviceType
, pCaps
);
1173 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1174 return D3DERR_INVALIDCALL
;
1177 /* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
1178 ie there is no GL Context - Get a default rendering context to enable the
1179 function query some info from GL */
1180 if (glXGetCurrentContext() == NULL
) {
1181 fake_ctx
= WineD3D_CreateFakeGLContext();
1182 if (NULL
!= fake_ctx
) gotContext
= TRUE
;
1187 if (gotContext
== FALSE
) {
1189 FIXME_(d3d_caps
)("GetDeviceCaps called but no GL Context - Returning dummy values\n");
1191 *(pCaps
->MaxTextureBlendStages
) = 2;
1192 *pCaps
->MaxSimultaneousTextures
= 2;
1193 *pCaps
->MaxUserClipPlanes
= 8;
1194 *pCaps
->MaxActiveLights
= 8;
1195 *pCaps
->MaxVertexBlendMatrices
= 0;
1196 *pCaps
->MaxVertexBlendMatrixIndex
= 1;
1197 *pCaps
->MaxAnisotropy
= 0;
1198 *pCaps
->MaxPointSize
= 255.0;
1201 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &gl_tex_size
);
1204 /* If we don't know the device settings, go query them now */
1205 if (This
->isGLInfoValid
== FALSE
) {
1206 BOOL rc
= IWineD3DImpl_FillGLCaps(&This
->gl_info
, NULL
);
1208 /* If we are running off a real context, save the values */
1209 if (rc
&& ((NULL
!= fake_ctx
))) This
->isGLInfoValid
= TRUE
;
1212 /* ------------------------------------------------
1213 The following fields apply to both d3d8 and d3d9
1214 ------------------------------------------------ */
1215 *pCaps
->DeviceType
= (DeviceType
== D3DDEVTYPE_HAL
) ? D3DDEVTYPE_HAL
: D3DDEVTYPE_REF
; /* Not quite true, but use h/w supported by opengl I suppose */
1216 *pCaps
->AdapterOrdinal
= Adapter
;
1219 *pCaps
->Caps2
= D3DCAPS2_CANRENDERWINDOWED
;
1220 *pCaps
->Caps3
= D3DDEVCAPS_HWTRANSFORMANDLIGHT
;
1221 *pCaps
->PresentationIntervals
= D3DPRESENT_INTERVAL_IMMEDIATE
;
1223 *pCaps
->CursorCaps
= 0;
1226 *pCaps
->DevCaps
= D3DDEVCAPS_DRAWPRIMTLVERTEX
|
1227 D3DDEVCAPS_HWTRANSFORMANDLIGHT
|
1228 D3DDEVCAPS_PUREDEVICE
|
1229 D3DDEVCAPS_HWRASTERIZATION
;
1232 *pCaps
->PrimitiveMiscCaps
= D3DPMISCCAPS_CULLCCW
|
1233 D3DPMISCCAPS_CULLCW
|
1234 D3DPMISCCAPS_COLORWRITEENABLE
|
1235 D3DPMISCCAPS_CLIPTLVERTS
|
1236 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
|
1238 /*NOT: D3DPMISCCAPS_TSSARGTEMP*/
1240 *pCaps
->RasterCaps
= D3DPRASTERCAPS_DITHER
|
1241 D3DPRASTERCAPS_PAT
|
1242 D3DPRASTERCAPS_WFOG
|
1243 D3DPRASTERCAPS_ZFOG
|
1244 D3DPRASTERCAPS_FOGVERTEX
|
1245 D3DPRASTERCAPS_FOGTABLE
|
1246 D3DPRASTERCAPS_FOGRANGE
;
1248 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
1249 *pCaps
->RasterCaps
|= D3DPRASTERCAPS_ANISOTROPY
|
1250 D3DPRASTERCAPS_ZBIAS
|
1251 D3DPRASTERCAPS_MIPMAPLODBIAS
;
1254 D3DPRASTERCAPS_COLORPERSPECTIVE
1255 D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1256 D3DPRASTERCAPS_ANTIALIASEDGES
1257 D3DPRASTERCAPS_ZBUFFERLESSHSR
1258 D3DPRASTERCAPS_WBUFFER */
1260 *pCaps
->ZCmpCaps
= D3DPCMPCAPS_ALWAYS
|
1262 D3DPCMPCAPS_GREATER
|
1263 D3DPCMPCAPS_GREATEREQUAL
|
1265 D3DPCMPCAPS_LESSEQUAL
|
1267 D3DPCMPCAPS_NOTEQUAL
;
1269 *pCaps
->SrcBlendCaps
= 0xFFFFFFFF; /*FIXME: Tidy up later */
1270 *pCaps
->DestBlendCaps
= 0xFFFFFFFF; /*FIXME: Tidy up later */
1271 *pCaps
->AlphaCmpCaps
= 0xFFFFFFFF; /*FIXME: Tidy up later */
1273 *pCaps
->ShadeCaps
= D3DPSHADECAPS_SPECULARGOURAUDRGB
|
1274 D3DPSHADECAPS_COLORGOURAUDRGB
;
1276 *pCaps
->TextureCaps
= D3DPTEXTURECAPS_ALPHA
|
1277 D3DPTEXTURECAPS_ALPHAPALETTE
|
1278 D3DPTEXTURECAPS_VOLUMEMAP
|
1279 D3DPTEXTURECAPS_MIPMAP
|
1280 D3DPTEXTURECAPS_PROJECTED
|
1281 D3DPTEXTURECAPS_PERSPECTIVE
|
1282 D3DPTEXTURECAPS_VOLUMEMAP_POW2
;
1283 /* TODO: add support for NON-POW2 if avaialble
1286 if (This
->dxVersion
> 8) {
1287 *pCaps
->TextureCaps
|= D3DPTEXTURECAPS_NONPOW2CONDITIONAL
;
1289 } else { /* NONPOW2 isn't accessable by d3d8 yet */
1290 *pCaps
->TextureCaps
|= D3DPTEXTURECAPS_POW2
;
1293 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
1294 *pCaps
->TextureCaps
|= D3DPTEXTURECAPS_CUBEMAP
|
1295 D3DPTEXTURECAPS_MIPCUBEMAP
|
1296 D3DPTEXTURECAPS_CUBEMAP_POW2
;
1300 *pCaps
->TextureFilterCaps
= D3DPTFILTERCAPS_MAGFLINEAR
|
1301 D3DPTFILTERCAPS_MAGFPOINT
|
1302 D3DPTFILTERCAPS_MINFLINEAR
|
1303 D3DPTFILTERCAPS_MINFPOINT
|
1304 D3DPTFILTERCAPS_MIPFLINEAR
|
1305 D3DPTFILTERCAPS_MIPFPOINT
;
1307 *pCaps
->CubeTextureFilterCaps
= 0;
1308 *pCaps
->VolumeTextureFilterCaps
= 0;
1310 *pCaps
->TextureAddressCaps
= D3DPTADDRESSCAPS_BORDER
|
1311 D3DPTADDRESSCAPS_CLAMP
|
1312 D3DPTADDRESSCAPS_WRAP
;
1314 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
1315 *pCaps
->TextureAddressCaps
|= D3DPTADDRESSCAPS_BORDER
;
1317 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
1318 *pCaps
->TextureAddressCaps
|= D3DPTADDRESSCAPS_MIRROR
;
1320 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
1321 *pCaps
->TextureAddressCaps
|= D3DPTADDRESSCAPS_MIRRORONCE
;
1324 *pCaps
->VolumeTextureAddressCaps
= 0;
1326 *pCaps
->LineCaps
= D3DLINECAPS_TEXTURE
|
1330 D3DLINECAPS_ALPHACMP
1333 *pCaps
->MaxTextureWidth
= gl_tex_size
;
1334 *pCaps
->MaxTextureHeight
= gl_tex_size
;
1336 *pCaps
->MaxVolumeExtent
= 0;
1338 *pCaps
->MaxTextureRepeat
= 32768;
1339 *pCaps
->MaxTextureAspectRatio
= 32768;
1340 *pCaps
->MaxVertexW
= 1.0;
1342 *pCaps
->GuardBandLeft
= 0;
1343 *pCaps
->GuardBandTop
= 0;
1344 *pCaps
->GuardBandRight
= 0;
1345 *pCaps
->GuardBandBottom
= 0;
1347 *pCaps
->ExtentsAdjust
= 0;
1349 *pCaps
->StencilCaps
= D3DSTENCILCAPS_DECRSAT
|
1350 D3DSTENCILCAPS_INCRSAT
|
1351 D3DSTENCILCAPS_INVERT
|
1352 D3DSTENCILCAPS_KEEP
|
1353 D3DSTENCILCAPS_REPLACE
|
1354 D3DSTENCILCAPS_ZERO
;
1355 if (GL_SUPPORT(EXT_STENCIL_WRAP
)) {
1356 *pCaps
->StencilCaps
|= D3DSTENCILCAPS_DECR
|
1357 D3DSTENCILCAPS_INCR
;
1360 *pCaps
->FVFCaps
= D3DFVFCAPS_PSIZE
| 0x0008; /* 8 texture coords */
1362 *pCaps
->TextureOpCaps
= D3DTEXOPCAPS_ADD
|
1363 D3DTEXOPCAPS_ADDSIGNED
|
1364 D3DTEXOPCAPS_ADDSIGNED2X
|
1365 D3DTEXOPCAPS_MODULATE
|
1366 D3DTEXOPCAPS_MODULATE2X
|
1367 D3DTEXOPCAPS_MODULATE4X
|
1368 D3DTEXOPCAPS_SELECTARG1
|
1369 D3DTEXOPCAPS_SELECTARG2
|
1370 D3DTEXOPCAPS_DISABLE
;
1371 #if defined(GL_VERSION_1_3)
1372 *pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_DOTPRODUCT3
|
1373 D3DTEXOPCAPS_SUBTRACT
;
1375 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE
) ||
1376 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE
) ||
1377 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
1378 *pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_BLENDDIFFUSEALPHA
|
1379 D3DTEXOPCAPS_BLENDTEXTUREALPHA
|
1380 D3DTEXOPCAPS_BLENDFACTORALPHA
|
1381 D3DTEXOPCAPS_BLENDCURRENTALPHA
|
1384 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
1385 *pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_ADDSMOOTH
|
1386 D3DTEXOPCAPS_MULTIPLYADD
|
1387 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
|
1388 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
|
1389 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM
;
1393 pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_BUMPENVMAP
;
1395 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
1396 D3DTEXOPCAPS_PREMODULATE */
1402 #if defined(GL_VERSION_1_3)
1403 glGetIntegerv(GL_MAX_TEXTURE_UNITS
, &gl_max
);
1405 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB
, &gl_max
);
1407 TRACE_(d3d_caps
)("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max
);
1408 *pCaps
->MaxTextureBlendStages
= min(8, gl_max
);
1409 *pCaps
->MaxSimultaneousTextures
= min(8, gl_max
);
1411 glGetIntegerv(GL_MAX_CLIP_PLANES
, &gl_max
);
1412 *pCaps
->MaxUserClipPlanes
= min(D3DMAXUSERCLIPPLANES
, gl_max
);
1413 TRACE_(d3d_caps
)("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", *pCaps
->MaxUserClipPlanes
);
1415 glGetIntegerv(GL_MAX_LIGHTS
, &gl_max
);
1416 *pCaps
->MaxActiveLights
= gl_max
;
1417 TRACE_(d3d_caps
)("GLCaps: GL_MAX_LIGHTS=%ld\n", *pCaps
->MaxActiveLights
);
1419 if (GL_SUPPORT(ARB_VERTEX_BLEND
)) {
1420 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB
, &gl_max
);
1421 #if 0 /* TODO : add support for blends to drawprim */
1422 *pCaps
->MaxVertexBlendMatrices
= gl_max
;
1424 *pCaps
->MaxVertexBlendMatrices
= 0;
1426 *pCaps
->MaxVertexBlendMatrixIndex
= 1;
1428 *pCaps
->MaxVertexBlendMatrices
= 0;
1429 *pCaps
->MaxVertexBlendMatrixIndex
= 1;
1432 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
1433 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
, &gl_max
);
1434 *pCaps
->MaxAnisotropy
= gl_max
;
1436 *pCaps
->MaxAnisotropy
= 0;
1439 glGetFloatv(GL_POINT_SIZE_RANGE
, &gl_float
);
1440 *pCaps
->MaxPointSize
= gl_float
;
1443 *pCaps
->VertexProcessingCaps
= D3DVTXPCAPS_DIRECTIONALLIGHTS
|
1444 D3DVTXPCAPS_MATERIALSOURCE7
|
1445 D3DVTXPCAPS_POSITIONALLIGHTS
|
1446 D3DVTXPCAPS_LOCALVIEWER
|
1449 D3DVTXPCAPS_TWEENING */
1451 *pCaps
->MaxPrimitiveCount
= 0xFFFFFFFF;
1452 *pCaps
->MaxVertexIndex
= 0xFFFFFFFF;
1453 *pCaps
->MaxStreams
= MAX_STREAMS
;
1454 *pCaps
->MaxStreamStride
= 1024;
1456 if (((vs_mode
== VS_HW
) && GL_SUPPORT(ARB_VERTEX_PROGRAM
)) || (vs_mode
== VS_SW
) || (DeviceType
== D3DDEVTYPE_REF
)) {
1457 *pCaps
->VertexShaderVersion
= D3DVS_VERSION(1,1);
1459 if (This
->gl_info
.gl_vendor
== VENDOR_MESA
||
1460 This
->gl_info
.gl_vendor
== VENDOR_WINE
) {
1461 *pCaps
->MaxVertexShaderConst
= 95;
1463 *pCaps
->MaxVertexShaderConst
= WINED3D_VSHADER_MAX_CONSTANTS
;
1466 *pCaps
->VertexShaderVersion
= 0;
1467 *pCaps
->MaxVertexShaderConst
= 0;
1470 if ((ps_mode
== PS_HW
) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM
) && (DeviceType
!= D3DDEVTYPE_REF
)) {
1471 *pCaps
->PixelShaderVersion
= D3DPS_VERSION(1,4);
1472 *pCaps
->PixelShader1xMaxValue
= 1.0;
1474 *pCaps
->PixelShaderVersion
= 0;
1475 *pCaps
->PixelShader1xMaxValue
= 0.0;
1477 /* TODO: ARB_FRAGMENT_PROGRAM_100 */
1479 /* ------------------------------------------------
1480 The following fields apply to d3d9 only
1481 ------------------------------------------------ */
1482 if (This
->dxVersion
> 8) {
1483 GLint max_buffers
=1;
1484 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
1485 *pCaps
->DevCaps2
= 0;
1486 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES */
1487 *pCaps
->MaxNpatchTessellationLevel
= 0;
1488 *pCaps
->MasterAdapterOrdinal
= 0;
1489 *pCaps
->AdapterOrdinalInGroup
= 0;
1490 *pCaps
->NumberOfAdaptersInGroup
= 1;
1491 *pCaps
->DeclTypes
= 0;
1492 #if 0 /*FIXME: Simultaneous render targets*/
1493 GL_MAX_DRAW_BUFFERS_ATI
0x00008824
1494 if (GL_SUPPORT(GL_MAX_DRAW_BUFFERS_ATI
)) {
1496 glEnable(GL_MAX_DRAW_BUFFERS_ATI
);
1497 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI
, &max_buffers
);
1498 glDisable(GL_MAX_DRAW_BUFFERS_ATI
);
1502 *pCaps
->NumSimultaneousRTs
= max_buffers
;
1503 *pCaps
->StretchRectFilterCaps
= 0;
1505 D3DPTFILTERCAPS_MINFPOINT
1506 D3DPTFILTERCAPS_MAGFPOINT
1507 D3DPTFILTERCAPS_MINFLINEAR
1508 D3DPTFILTERCAPS_MAGFLINEAR
1510 *pCaps
->VS20Caps
.Caps
= 0;
1511 *pCaps
->PS20Caps
.Caps
= 0;
1512 *pCaps
->VertexTextureFilterCaps
= 0;
1513 *pCaps
->MaxVShaderInstructionsExecuted
= 0;
1514 *pCaps
->MaxPShaderInstructionsExecuted
= 0;
1515 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
1516 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
1519 /* If we created a dummy context, throw it away */
1520 if (NULL
!= fake_ctx
) WineD3D_ReleaseFakeGLContext(fake_ctx
);
1525 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
1526 and fields being inserted in the middle, a new structure is used in place */
1527 HRESULT WINAPI
IWineD3DImpl_CreateDevice(IWineD3D
*iface
, UINT Adapter
, D3DDEVTYPE DeviceType
, HWND hFocusWindow
,
1528 DWORD BehaviourFlags
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
,
1529 IWineD3DDevice
** ppReturnedDeviceInterface
, IUnknown
*parent
, D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget
) {
1533 IWineD3DDeviceImpl
*object
= NULL
;
1534 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1536 XVisualInfo
template;
1539 /* Validate the adapter number */
1540 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1541 return D3DERR_INVALIDCALL
;
1544 /* Create a WineD3DDevice object */
1545 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DDeviceImpl
));
1546 *ppReturnedDeviceInterface
= (IWineD3DDevice
*)object
;
1547 TRACE("Created WineD3DDevice object @ %p \n", object
);
1548 if (NULL
== object
) {
1549 return D3DERR_OUTOFVIDEOMEMORY
;
1552 /* Set up initial COM information */
1553 object
->lpVtbl
= &IWineD3DDevice_Vtbl
;
1555 object
->wineD3D
= iface
;
1556 IWineD3D_AddRef(object
->wineD3D
);
1557 object
->parent
= parent
;
1559 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This
, Adapter
, DeviceType
,
1560 hFocusWindow
, BehaviourFlags
, pPresentationParameters
, ppReturnedDeviceInterface
);
1561 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This
,
1562 *(pPresentationParameters
->AutoDepthStencilFormat
), debug_d3dformat(*(pPresentationParameters
->AutoDepthStencilFormat
)),
1563 *(pPresentationParameters
->BackBufferFormat
), debug_d3dformat(*(pPresentationParameters
->BackBufferFormat
)));
1565 /* Save the creation parameters */
1566 object
->createParms
.AdapterOrdinal
= Adapter
;
1567 object
->createParms
.DeviceType
= DeviceType
;
1568 object
->createParms
.hFocusWindow
= hFocusWindow
;
1569 object
->createParms
.BehaviorFlags
= BehaviourFlags
;
1571 /* Initialize other useful values */
1572 object
->presentParms
.BackBufferCount
= 1; /* Opengl only supports one? */
1573 object
->adapterNo
= Adapter
;
1574 object
->devType
= DeviceType
;
1576 /* Setup hwnd we are using, plus which display this equates to */
1577 whichHWND
= *(pPresentationParameters
->hDeviceWindow
);
1579 whichHWND
= hFocusWindow
;
1581 object
->win_handle
= whichHWND
;
1582 object
->win
= (Window
)GetPropA( whichHWND
, "__wine_x11_whole_window" );
1583 hDc
= GetDC(whichHWND
);
1584 object
->display
= get_display(hDc
);
1585 ReleaseDC(whichHWND
, hDc
);
1587 /* FIXME: Use for dx8 code eventually too! */
1588 /* Deliberately no indentation here, as this if will be removed when dx8 support merged in */
1589 if (This
->dxVersion
> 8) {
1591 /* Create a context based off the properties of the existing visual */
1592 /* Note the visual is chosen as the window is created and the glcontext cannot
1593 use different properties after that point in time. FIXME: How to handle when requested format
1594 doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1595 it chooses is identical to the one already being used! */
1596 /* FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat */
1598 template.visualid
= (VisualID
)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1599 object
->visInfo
= XGetVisualInfo(object
->display
, VisualIDMask
, &template, &num
);
1600 if (NULL
== object
->visInfo
) {
1601 ERR("cannot really get XVisual\n");
1603 return D3DERR_NOTAVAILABLE
;
1605 object
->glCtx
= glXCreateContext(object
->display
, object
->visInfo
, NULL
, GL_TRUE
);
1606 if (NULL
== object
->glCtx
) {
1607 ERR("cannot create glxContext\n");
1609 return D3DERR_NOTAVAILABLE
;
1613 if (object
->glCtx
== NULL
) {
1614 ERR("Error in context creation !\n");
1615 return D3DERR_INVALIDCALL
;
1617 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1618 whichHWND
, object
->glCtx
, object
->win
, object
->visInfo
);
1621 /* If not windowed, need to go fullscreen, and resize the HWND to the appropriate */
1623 if (!*(pPresentationParameters
->Windowed
)) {
1629 /* Get info on the current display setup */
1630 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1631 bpp
= GetDeviceCaps(hdc
, BITSPIXEL
);
1634 /* Change the display settings */
1635 memset(&devmode
, 0, sizeof(DEVMODEW
));
1636 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
1637 devmode
.dmBitsPerPel
= (bpp
>= 24) ? 32 : bpp
; /*Stupid XVidMode cannot change bpp D3DFmtGetBpp(object, pPresentationParameters->BackBufferFormat);*/
1638 devmode
.dmPelsWidth
= *(pPresentationParameters
->BackBufferWidth
);
1639 devmode
.dmPelsHeight
= *(pPresentationParameters
->BackBufferHeight
);
1640 MultiByteToWideChar(CP_ACP
, 0, "Gamers CG", -1, devmode
.dmDeviceName
, CCHDEVICENAME
);
1641 ChangeDisplaySettingsExW(devmode
.dmDeviceName
, &devmode
, object
->win_handle
, CDS_FULLSCREEN
, NULL
);
1643 /* Make popup window */
1644 SetWindowLongA(whichHWND
, GWL_STYLE
, WS_POPUP
);
1645 SetWindowPos(object
->win_handle
, HWND_TOP
, 0, 0,
1646 *(pPresentationParameters
->BackBufferWidth
),
1647 *(pPresentationParameters
->BackBufferHeight
), SWP_SHOWWINDOW
| SWP_FRAMECHANGED
);
1650 /* MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1651 then the corresponding dimension of the client area of the hDeviceWindow
1652 (or the focus window, if hDeviceWindow is NULL) is taken. */
1653 if (*(pPresentationParameters
->Windowed
) &&
1654 ((*(pPresentationParameters
->BackBufferWidth
) == 0) ||
1655 (*(pPresentationParameters
->BackBufferHeight
) == 0))) {
1658 GetClientRect(whichHWND
, &Rect
);
1660 if (*(pPresentationParameters
->BackBufferWidth
) == 0) {
1661 *(pPresentationParameters
->BackBufferWidth
) = Rect
.right
;
1662 TRACE("Updating width to %d\n", *(pPresentationParameters
->BackBufferWidth
));
1664 if (*(pPresentationParameters
->BackBufferHeight
) == 0) {
1665 *(pPresentationParameters
->BackBufferHeight
) = Rect
.bottom
;
1666 TRACE("Updating height to %d\n", *(pPresentationParameters
->BackBufferHeight
));
1670 /* Save the presentation parms now filled in correctly */
1671 object
->presentParms
.BackBufferWidth
= *(pPresentationParameters
->BackBufferWidth
);
1672 object
->presentParms
.BackBufferHeight
= *(pPresentationParameters
->BackBufferHeight
);
1673 object
->presentParms
.BackBufferFormat
= *(pPresentationParameters
->BackBufferFormat
);
1674 object
->presentParms
.BackBufferCount
= *(pPresentationParameters
->BackBufferCount
);
1675 object
->presentParms
.MultiSampleType
= *(pPresentationParameters
->MultiSampleType
);
1676 object
->presentParms
.MultiSampleQuality
= *(pPresentationParameters
->MultiSampleQuality
);
1677 object
->presentParms
.SwapEffect
= *(pPresentationParameters
->SwapEffect
);
1678 object
->presentParms
.hDeviceWindow
= *(pPresentationParameters
->hDeviceWindow
);
1679 object
->presentParms
.Windowed
= *(pPresentationParameters
->Windowed
);
1680 object
->presentParms
.EnableAutoDepthStencil
= *(pPresentationParameters
->EnableAutoDepthStencil
);
1681 object
->presentParms
.AutoDepthStencilFormat
= *(pPresentationParameters
->AutoDepthStencilFormat
);
1682 object
->presentParms
.Flags
= *(pPresentationParameters
->Flags
);
1683 object
->presentParms
.FullScreen_RefreshRateInHz
= *(pPresentationParameters
->FullScreen_RefreshRateInHz
);
1684 object
->presentParms
.PresentationInterval
= *(pPresentationParameters
->PresentationInterval
);
1686 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
1687 IWineD3DDevice_CreateStateBlock((IWineD3DDevice
*)object
,
1688 (D3DSTATEBLOCKTYPE
) 0,
1689 (IWineD3DStateBlock
**)&object
->stateBlock
,
1690 NULL
); /* Note: No parent needed for initial internal stateblock */
1691 object
->updateStateBlock
= object
->stateBlock
;
1693 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
1694 TRACE("Creating initial device surfaces\n");
1696 /* We need to 'magic' either d3d8 or d3d9 surfaces for the front and backbuuffer
1697 but the respective CreateRenderTarget functions take a differing number of
1698 parms. Fix this by passing in a function to call which takes identical parms
1699 and handles the differences at the d3dx layer, and returns the IWineD3DSurface
1700 pointer rather than the created D3D8/9 one */
1701 if ((res
= D3DCB_CreateRenderTarget((IUnknown
*) parent
,
1702 *(pPresentationParameters
->BackBufferWidth
),
1703 *(pPresentationParameters
->BackBufferHeight
),
1704 *(pPresentationParameters
->BackBufferFormat
),
1705 *(pPresentationParameters
->MultiSampleType
),
1706 *(pPresentationParameters
->MultiSampleQuality
),
1708 (IWineD3DSurface
**) &object
->frontBuffer
,
1710 (res
= D3DCB_CreateRenderTarget((IUnknown
*) parent
,
1711 *(pPresentationParameters
->BackBufferWidth
),
1712 *(pPresentationParameters
->BackBufferHeight
),
1713 *(pPresentationParameters
->BackBufferFormat
),
1714 *(pPresentationParameters
->MultiSampleType
),
1715 *(pPresentationParameters
->MultiSampleQuality
),
1717 (IWineD3DSurface
**) &object
->backBuffer
,
1720 ERR("D3DCB_CreateRenderTarget() failed\n");
1725 if (*(pPresentationParameters->EnableAutoDepthStencil)) {
1726 IWineD3DDevice_CreateDepthStencilSurface((IWineD3DDevice *) object,
1727 *(pPresentationParameters->BackBufferWidth),
1728 *(pPresentationParameters->BackBufferHeight),
1729 *(pPresentationParameters->AutoDepthStencilFormat,
1730 D3DMULTISAMPLE_NONE,
1731 (IWineD3DSurface *) &object->depthStencilBuffer);
1733 object->depthStencilBuffer = NULL;
1735 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil @ %p\n",object->frontBuffer, object->backBuffer, object->depthStencilBuffer);
1738 /* init the default renderTarget management */
1739 object
->drawable
= object
->win
;
1740 object
->render_ctx
= object
->glCtx
;
1741 object
->renderTarget
= object
->backBuffer
;
1743 IWineD3DSurface_AddRef((IWineD3DSurface
*) object
->renderTarget
);
1744 /* TODO: Depth Stencil support
1745 object->stencilBufferTarget = object->depthStencilBuffer;
1746 if (NULL != object->stencilBufferTarget) {
1747 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->stencilBufferTarget);
1751 /* Set up some starting GL setup */
1754 if (glXMakeCurrent(object
->display
, object
->win
, object
->glCtx
) == False
) {
1755 ERR("Error in setting current context (context %p drawable %ld)!\n", object
->glCtx
, object
->win
);
1757 checkGLcall("glXMakeCurrent");
1759 /* Clear the screen */
1760 glClearColor(1.0, 0.0, 0.0, 0.0);
1761 checkGLcall("glClearColor");
1762 glColor3f(1.0, 1.0, 1.0);
1763 checkGLcall("glColor3f");
1765 glEnable(GL_LIGHTING
);
1766 checkGLcall("glEnable");
1768 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, GL_TRUE
);
1769 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1771 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1772 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1774 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL
, GL_SEPARATE_SPECULAR_COLOR
);
1775 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1778 * Initialize openGL extension related variables
1779 * with Default values
1781 This
->isGLInfoValid
= IWineD3DImpl_FillGLCaps(&This
->gl_info
, object
->display
);
1783 /* Setup all the devices defaults */
1784 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*)object
->stateBlock
);
1788 { /* Set a default viewport */
1792 vp
.Width
= *(pPresentationParameters
->BackBufferWidth
);
1793 vp
.Height
= *(pPresentationParameters
->BackBufferHeight
);
1796 IWineD3DDevice_SetViewport((IWineD3DDevice
*)object
, &vp
);
1799 /* Initialize the current view state */
1800 object
->modelview_valid
= 1;
1801 object
->proj_valid
= 0;
1802 object
->view_ident
= 1;
1803 object
->last_was_rhw
= 0;
1804 glGetIntegerv(GL_MAX_LIGHTS
, &object
->maxConcurrentLights
);
1805 TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This
, Adapter
, object
);
1807 /* Clear the screen */
1808 IWineD3DDevice_Clear((IWineD3DDevice
*) object
, 0, NULL
, D3DCLEAR_STENCIL
|D3DCLEAR_ZBUFFER
|D3DCLEAR_TARGET
, 0x00, 1.0, 0);
1810 } /* End of FIXME: remove when dx8 merged in */
1815 HRESULT WINAPI
IWineD3DImpl_GetParent(IWineD3D
*iface
, IUnknown
**pParent
) {
1816 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1817 IUnknown_AddRef(This
->parent
);
1818 *pParent
= This
->parent
;
1822 /**********************************************************
1823 * IWineD3D VTbl follows
1824 **********************************************************/
1826 const IWineD3DVtbl IWineD3D_Vtbl
=
1828 IWineD3DImpl_QueryInterface
,
1829 IWineD3DImpl_AddRef
,
1830 IWineD3DImpl_Release
,
1831 IWineD3DImpl_GetParent
,
1832 IWineD3DImpl_GetAdapterCount
,
1833 IWineD3DImpl_RegisterSoftwareDevice
,
1834 IWineD3DImpl_GetAdapterMonitor
,
1835 IWineD3DImpl_GetAdapterModeCount
,
1836 IWineD3DImpl_EnumAdapterModes
,
1837 IWineD3DImpl_GetAdapterDisplayMode
,
1838 IWineD3DImpl_GetAdapterIdentifier
,
1839 IWineD3DImpl_CheckDeviceMultiSampleType
,
1840 IWineD3DImpl_CheckDepthStencilMatch
,
1841 IWineD3DImpl_CheckDeviceType
,
1842 IWineD3DImpl_CheckDeviceFormat
,
1843 IWineD3DImpl_CheckDeviceFormatConversion
,
1844 IWineD3DImpl_GetDeviceCaps
,
1845 IWineD3DImpl_CreateDevice