2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps
);
39 /* Extension detection */
41 const char *extension_string
;
42 GL_SupportedExt extension
;
46 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE
, 0 },
47 {"GL_APPLE_fence", APPLE_FENCE
, 0 },
48 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER
, 0 },
49 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422
, 0 },
52 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL
, 0 },
53 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3
, 0 },
54 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE
, 0 },
55 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP
, 0 },
58 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS
, 0 },
59 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM
, 0 },
60 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER
, 0 },
61 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL
, 0 },
62 {"GL_ARB_imaging", ARB_IMAGING
, 0 },
63 {"GL_ARB_multisample", ARB_MULTISAMPLE
, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
64 {"GL_ARB_multitexture", ARB_MULTITEXTURE
, 0 },
65 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY
, 0 },
66 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT
, 0 },
67 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS
, 0 },
68 {"GL_ARB_point_sprite", ARB_POINT_SPRITE
, 0 },
69 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP
, 0 },
70 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION
, 0 },
71 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP
, 0 },
72 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD
, 0 },
73 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE
, 0 },
74 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3
, 0 },
75 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT
, 0 },
76 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT
, 0 },
77 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO
, 0 },
78 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND
, 0 },
79 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT
, 0 },
80 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM
, 0 },
81 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER
, 0 },
82 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS
, 0 },
85 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX
, 0 },
86 {"GL_EXT_fog_coord", EXT_FOG_COORD
, 0 },
87 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT
, 0 },
88 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT
, 0 },
89 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE
, 0 },
90 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS
, 0 },
91 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR
, 0 },
92 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE
, 0 },
93 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP
, 0 },
94 {"GL_EXT_texture3D", EXT_TEXTURE3D
, MAKEDWORD_VERSION(1, 2) },
95 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC
, 0 },
96 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD
, 0 },
97 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE
, 0 },
98 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3
, 0 },
99 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB
, 0 },
100 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC
, 0 },
101 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD
, 0 },
102 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS
, 0 },
103 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER
, 0 },
104 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING
, 0 },
107 {"GL_NV_half_float", NV_HALF_FLOAT
, 0 },
108 {"GL_NV_fence", NV_FENCE
, 0 },
109 {"GL_NV_fog_distance", NV_FOG_DISTANCE
, 0 },
110 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM
, 0 },
111 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2
, 0 },
112 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS
, 0 },
113 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2
, 0 },
114 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION
, 0 },
115 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4
, 0 },
116 {"GL_NV_texture_shader", NV_TEXTURE_SHADER
, 0 },
117 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2
, 0 },
118 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3
, 0 },
119 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY
, 0 },
120 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM
, 0 },
121 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1
, 0 },
122 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2
, 0 },
123 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3
, 0 },
124 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP
, 0 },
127 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP
, 0 },
130 /**********************************************************
131 * Utility functions follow
132 **********************************************************/
135 static int numAdapters
= 0;
136 static struct WineD3DAdapter Adapters
[1];
139 int minLookup
[MAX_LOOKUPS
];
140 int maxLookup
[MAX_LOOKUPS
];
141 DWORD
*stateLookup
[MAX_LOOKUPS
];
143 DWORD minMipLookup
[WINED3DTEXF_ANISOTROPIC
+ 1][WINED3DTEXF_LINEAR
+ 1];
147 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
148 * ie there is no GL Context - Get a default rendering context to enable the
149 * function query some info from GL
152 static int wined3d_fake_gl_context_ref
= 0;
153 static BOOL wined3d_fake_gl_context_foreign
;
154 static BOOL wined3d_fake_gl_context_available
= FALSE
;
155 static HDC wined3d_fake_gl_context_hdc
= NULL
;
156 static HWND wined3d_fake_gl_context_hwnd
= NULL
;
158 static CRITICAL_SECTION wined3d_fake_gl_context_cs
;
159 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug
=
161 0, 0, &wined3d_fake_gl_context_cs
,
162 { &wined3d_fake_gl_context_cs_debug
.ProcessLocksList
,
163 &wined3d_fake_gl_context_cs_debug
.ProcessLocksList
},
164 0, 0, { (DWORD_PTR
)(__FILE__
": wined3d_fake_gl_context_cs") }
166 static CRITICAL_SECTION wined3d_fake_gl_context_cs
= { &wined3d_fake_gl_context_cs_debug
, -1, 0, 0, 0, 0 };
168 static void WineD3D_ReleaseFakeGLContext(void) {
171 EnterCriticalSection(&wined3d_fake_gl_context_cs
);
173 if(!wined3d_fake_gl_context_available
) {
174 TRACE_(d3d_caps
)("context not available\n");
175 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
179 glCtx
= pwglGetCurrentContext();
181 TRACE_(d3d_caps
)("decrementing ref from %i\n", wined3d_fake_gl_context_ref
);
182 if (0 == (--wined3d_fake_gl_context_ref
) ) {
183 if(!wined3d_fake_gl_context_foreign
&& glCtx
) {
184 TRACE_(d3d_caps
)("destroying fake GL context\n");
185 pwglMakeCurrent(NULL
, NULL
);
186 //ros hack, this line does destire the real icd interface in windows and reactos
187 // pwglDeleteContext(glCtx);
189 if(wined3d_fake_gl_context_hdc
)
190 ReleaseDC(wined3d_fake_gl_context_hwnd
, wined3d_fake_gl_context_hdc
);
191 wined3d_fake_gl_context_hdc
= NULL
; /* Make sure we don't think that it is still around */
192 if(wined3d_fake_gl_context_hwnd
)
193 DestroyWindow(wined3d_fake_gl_context_hwnd
);
194 wined3d_fake_gl_context_hwnd
= NULL
;
195 wined3d_fake_gl_context_available
= FALSE
;
197 assert(wined3d_fake_gl_context_ref
>= 0);
199 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
202 static BOOL
WineD3D_CreateFakeGLContext(void) {
205 EnterCriticalSection(&wined3d_fake_gl_context_cs
);
207 TRACE("getting context...\n");
208 if(wined3d_fake_gl_context_ref
> 0) goto ret
;
209 assert(0 == wined3d_fake_gl_context_ref
);
211 wined3d_fake_gl_context_foreign
= TRUE
;
213 glCtx
= pwglGetCurrentContext();
215 PIXELFORMATDESCRIPTOR pfd
;
218 wined3d_fake_gl_context_foreign
= FALSE
;
220 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
221 wined3d_fake_gl_context_hwnd
= CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW
, 10, 10, 10, 10, NULL
, NULL
, NULL
, NULL
);
222 if(!wined3d_fake_gl_context_hwnd
) {
223 ERR("HWND creation failed!\n");
226 wined3d_fake_gl_context_hdc
= GetDC(wined3d_fake_gl_context_hwnd
);
227 if(!wined3d_fake_gl_context_hdc
) {
228 ERR("GetDC failed!\n");
232 /* PixelFormat selection */
233 ZeroMemory(&pfd
, sizeof(pfd
));
234 pfd
.nSize
= sizeof(pfd
);
236 pfd
.dwFlags
= PFD_SUPPORT_OPENGL
| PFD_DOUBLEBUFFER
| PFD_DRAW_TO_WINDOW
;/*PFD_GENERIC_ACCELERATED*/
237 pfd
.iPixelType
= PFD_TYPE_RGBA
;
239 pfd
.iLayerType
= PFD_MAIN_PLANE
;
241 iPixelFormat
= ChoosePixelFormat(wined3d_fake_gl_context_hdc
, &pfd
);
243 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
244 ERR("Can't find a suitable iPixelFormat\n");
247 DescribePixelFormat(wined3d_fake_gl_context_hdc
, iPixelFormat
, sizeof(pfd
), &pfd
);
248 SetPixelFormat(wined3d_fake_gl_context_hdc
, iPixelFormat
, &pfd
);
250 /* Create a GL context */
251 glCtx
= pwglCreateContext(wined3d_fake_gl_context_hdc
);
253 WARN_(d3d_caps
)("Error creating default context for capabilities initialization\n");
257 /* Make it the current GL context */
258 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc
, glCtx
)) {
259 WARN_(d3d_caps
)("Error setting default context as current for capabilities initialization\n");
265 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref
);
266 wined3d_fake_gl_context_ref
++;
267 wined3d_fake_gl_context_available
= TRUE
;
268 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
271 if(wined3d_fake_gl_context_hdc
)
272 ReleaseDC(wined3d_fake_gl_context_hwnd
, wined3d_fake_gl_context_hdc
);
273 wined3d_fake_gl_context_hdc
= NULL
;
274 if(wined3d_fake_gl_context_hwnd
)
275 DestroyWindow(wined3d_fake_gl_context_hwnd
);
276 wined3d_fake_gl_context_hwnd
= NULL
;
277 if(glCtx
) pwglDeleteContext(glCtx
);
278 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
282 /* Adjust the amount of used texture memory */
283 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl
*D3DDevice
, long glram
){
284 UINT Adapter
= D3DDevice
->adapterNo
;
286 Adapters
[Adapter
].UsedTextureRam
+= glram
;
287 TRACE("Adjusted gl ram by %ld to %d\n", glram
, Adapters
[Adapter
].UsedTextureRam
);
288 return Adapters
[Adapter
].UsedTextureRam
;
291 /**********************************************************
292 * IUnknown parts follows
293 **********************************************************/
295 static HRESULT WINAPI
IWineD3DImpl_QueryInterface(IWineD3D
*iface
,REFIID riid
,LPVOID
*ppobj
)
297 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
299 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
300 if (IsEqualGUID(riid
, &IID_IUnknown
)
301 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
302 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
303 IUnknown_AddRef(iface
);
308 return E_NOINTERFACE
;
311 static ULONG WINAPI
IWineD3DImpl_AddRef(IWineD3D
*iface
) {
312 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
313 ULONG refCount
= InterlockedIncrement(&This
->ref
);
315 TRACE("(%p) : AddRef increasing from %d\n", This
, refCount
- 1);
319 static ULONG WINAPI
IWineD3DImpl_Release(IWineD3D
*iface
) {
320 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
322 TRACE("(%p) : Releasing from %d\n", This
, This
->ref
);
323 ref
= InterlockedDecrement(&This
->ref
);
325 HeapFree(GetProcessHeap(), 0, This
);
331 /* Set the shader type for this device, depending on the given capabilities,
332 * the device type, and the user preferences in wined3d_settings */
334 static void select_shader_mode(
335 WineD3D_GL_Info
*gl_info
,
336 WINED3DDEVTYPE DeviceType
,
340 if (wined3d_settings
.vs_mode
== VS_NONE
) {
341 *vs_selected
= SHADER_NONE
;
342 } else if (gl_info
->supported
[ARB_VERTEX_SHADER
] && wined3d_settings
.glslRequested
) {
343 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
344 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
345 * shaders only on this card. */
346 if(gl_info
->vs_nv_version
&& gl_info
->vs_nv_version
< VS_VERSION_20
)
347 *vs_selected
= SHADER_ARB
;
349 *vs_selected
= SHADER_GLSL
;
350 } else if (gl_info
->supported
[ARB_VERTEX_PROGRAM
]) {
351 *vs_selected
= SHADER_ARB
;
353 *vs_selected
= SHADER_NONE
;
356 if (wined3d_settings
.ps_mode
== PS_NONE
) {
357 *ps_selected
= SHADER_NONE
;
358 } else if (gl_info
->supported
[ARB_FRAGMENT_SHADER
] && wined3d_settings
.glslRequested
) {
359 *ps_selected
= SHADER_GLSL
;
360 } else if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
]) {
361 *ps_selected
= SHADER_ARB
;
363 *ps_selected
= SHADER_NONE
;
367 /** Select the number of report maximum shader constants based on the selected shader modes */
368 static void select_shader_max_constants(
369 int ps_selected_mode
,
370 int vs_selected_mode
,
371 WineD3D_GL_Info
*gl_info
) {
373 switch (vs_selected_mode
) {
375 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
376 gl_info
->max_vshader_constantsF
= gl_info
->vs_glsl_constantsF
- (MAX_CONST_B
/ 4) - MAX_CONST_I
- 1;
379 /* We have to subtract any other PARAMs that we might use in our shader programs.
380 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
381 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
382 gl_info
->max_vshader_constantsF
= gl_info
->vs_arb_constantsF
- 3;
385 gl_info
->max_vshader_constantsF
= 0;
389 switch (ps_selected_mode
) {
391 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
392 * In theory the texbem instruction may need one more shader constant too. But lets assume
393 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
394 * and lets not take away a uniform needlessly from all other shaders.
396 gl_info
->max_pshader_constantsF
= gl_info
->ps_glsl_constantsF
- (MAX_CONST_B
/ 4) - MAX_CONST_I
- 2;
399 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
400 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
402 gl_info
->max_pshader_constantsF
= gl_info
->ps_arb_constantsF
- 2;
405 gl_info
->max_pshader_constantsF
= 0;
410 /**********************************************************
411 * IWineD3D parts follows
412 **********************************************************/
414 #define GLINFO_LOCATION (*gl_info)
415 static inline BOOL
test_arb_vs_offset_limit(WineD3D_GL_Info
*gl_info
) {
418 const char *testcode
=
420 "PARAM C[66] = { program.env[0..65] };\n"
423 "MOV result.position, C[A0.x + 65];\n"
427 GL_EXTCALL(glGenProgramsARB(1, &prog
));
429 ERR("Failed to create an ARB offset limit test program\n");
431 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, prog
));
432 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
,
433 strlen(testcode
), testcode
));
434 if(glGetError() != 0) {
435 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
436 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB
)));
438 } else TRACE("OpenGL implementation allows offsets > 63\n");
440 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, 0));
441 GL_EXTCALL(glDeleteProgramsARB(1, &prog
));
442 checkGLcall("ARB vp offset limit test cleanup\n");
447 static DWORD
ver_for_ext(GL_SupportedExt ext
)
450 for (i
= 0; i
< (sizeof(EXTENSION_MAP
) / sizeof(*EXTENSION_MAP
)); ++i
) {
451 if(EXTENSION_MAP
[i
].extension
== ext
) {
452 return EXTENSION_MAP
[i
].version
;
458 BOOL
IWineD3DImpl_FillGLCaps(WineD3D_GL_Info
*gl_info
) {
459 const char *GL_Extensions
= NULL
;
460 const char *WGL_Extensions
= NULL
;
461 const char *gl_string
= NULL
;
462 const char *gl_string_cursor
= NULL
;
464 GLfloat gl_floatv
[2];
465 int major
= 1, minor
= 0;
466 BOOL return_value
= TRUE
;
469 unsigned int vidmem
=0;
471 TRACE_(d3d_caps
)("(%p)\n", gl_info
);
475 gl_string
= (const char *) glGetString(GL_RENDERER
);
476 if (NULL
== gl_string
)
478 strcpy(gl_info
->gl_renderer
, gl_string
);
480 gl_string
= (const char *) glGetString(GL_VENDOR
);
481 TRACE_(d3d_caps
)("Filling vendor string %s\n", gl_string
);
482 if (gl_string
!= NULL
) {
483 /* Fill in the GL vendor */
484 if (strstr(gl_string
, "NVIDIA")) {
485 gl_info
->gl_vendor
= VENDOR_NVIDIA
;
486 } else if (strstr(gl_string
, "ATI")) {
487 gl_info
->gl_vendor
= VENDOR_ATI
;
488 } else if (strstr(gl_string
, "Intel(R)") ||
489 strstr(gl_info
->gl_renderer
, "Intel(R)")) {
490 gl_info
->gl_vendor
= VENDOR_INTEL
;
491 } else if (strstr(gl_string
, "Mesa")) {
492 gl_info
->gl_vendor
= VENDOR_MESA
;
494 gl_info
->gl_vendor
= VENDOR_WINE
;
497 gl_info
->gl_vendor
= VENDOR_WINE
;
501 TRACE_(d3d_caps
)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string
), gl_info
->gl_vendor
);
503 /* Parse the GL_VERSION field into major and minor information */
504 gl_string
= (const char *) glGetString(GL_VERSION
);
505 if (gl_string
!= NULL
) {
507 switch (gl_info
->gl_vendor
) {
509 gl_string_cursor
= strstr(gl_string
, "NVIDIA");
510 if (!gl_string_cursor
) {
511 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
515 gl_string_cursor
= strstr(gl_string_cursor
, " ");
516 if (!gl_string_cursor
) {
517 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
521 while (*gl_string_cursor
== ' ') {
525 if (!*gl_string_cursor
) {
526 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
530 major
= atoi(gl_string_cursor
);
531 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
535 if (*gl_string_cursor
++ != '.') {
536 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
540 minor
= atoi(gl_string_cursor
);
541 minor
= major
*100+minor
;
548 gl_string_cursor
= strchr(gl_string
, '-');
549 if (gl_string_cursor
) {
553 /* Check if version number is of the form x.y.z */
554 if (*gl_string_cursor
> '9' && *gl_string_cursor
< '0')
556 if (!error
&& *(gl_string_cursor
+2) > '9' && *(gl_string_cursor
+2) < '0')
558 if (!error
&& *(gl_string_cursor
+4) > '9' && *(gl_string_cursor
+4) < '0')
560 if (!error
&& *(gl_string_cursor
+1) != '.' && *(gl_string_cursor
+3) != '.')
563 /* Mark version number as malformed */
565 gl_string_cursor
= 0;
568 if (!gl_string_cursor
)
569 WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
571 major
= *gl_string_cursor
- '0';
572 minor
= (*(gl_string_cursor
+2) - '0') * 256 + (*(gl_string_cursor
+4) - '0');
578 gl_string_cursor
= strstr(gl_string
, "Mesa");
579 gl_string_cursor
= strstr(gl_string_cursor
, " ");
580 while (*gl_string_cursor
&& ' ' == *gl_string_cursor
) ++gl_string_cursor
;
581 if (*gl_string_cursor
) {
585 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
586 tmp
[cursor
++] = *gl_string_cursor
;
592 if (*gl_string_cursor
!= '.') WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
596 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
597 tmp
[cursor
++] = *gl_string_cursor
;
609 gl_info
->gl_driver_version
= MAKEDWORD_VERSION(major
, minor
);
610 TRACE_(d3d_caps
)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string
), major
, minor
, gl_info
->gl_driver_version
);
613 TRACE_(d3d_caps
)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info
->gl_renderer
), gl_info
->gl_card
);
616 * Initialize openGL extension related variables
617 * with Default values
619 memset(&gl_info
->supported
, 0, sizeof(gl_info
->supported
));
620 gl_info
->max_buffers
= 1;
621 gl_info
->max_textures
= 1;
622 gl_info
->max_texture_stages
= 1;
623 gl_info
->max_fragment_samplers
= 1;
624 gl_info
->max_vertex_samplers
= 0;
625 gl_info
->max_combined_samplers
= 0;
626 gl_info
->max_sampler_stages
= 1;
627 gl_info
->ps_arb_version
= PS_VERSION_NOT_SUPPORTED
;
628 gl_info
->ps_arb_max_temps
= 0;
629 gl_info
->ps_arb_max_instructions
= 0;
630 gl_info
->vs_arb_version
= VS_VERSION_NOT_SUPPORTED
;
631 gl_info
->vs_arb_max_temps
= 0;
632 gl_info
->vs_arb_max_instructions
= 0;
633 gl_info
->vs_nv_version
= VS_VERSION_NOT_SUPPORTED
;
634 gl_info
->vs_ati_version
= VS_VERSION_NOT_SUPPORTED
;
635 gl_info
->vs_glsl_constantsF
= 0;
636 gl_info
->ps_glsl_constantsF
= 0;
637 gl_info
->vs_arb_constantsF
= 0;
638 gl_info
->ps_arb_constantsF
= 0;
640 /* Retrieve opengl defaults */
641 glGetIntegerv(GL_MAX_CLIP_PLANES
, &gl_max
);
642 gl_info
->max_clipplanes
= min(WINED3DMAXUSERCLIPPLANES
, gl_max
);
643 TRACE_(d3d_caps
)("ClipPlanes support - num Planes=%d\n", gl_max
);
645 glGetIntegerv(GL_MAX_LIGHTS
, &gl_max
);
646 gl_info
->max_lights
= gl_max
;
647 TRACE_(d3d_caps
)("Lights support - max lights=%d\n", gl_max
);
649 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &gl_max
);
650 gl_info
->max_texture_size
= gl_max
;
651 TRACE_(d3d_caps
)("Maximum texture size support - max texture size=%d\n", gl_max
);
653 glGetFloatv(GL_POINT_SIZE_RANGE
, gl_floatv
);
654 gl_info
->max_pointsizemin
= gl_floatv
[0];
655 gl_info
->max_pointsize
= gl_floatv
[1];
656 TRACE_(d3d_caps
)("Maximum point size support - max point size=%f\n", gl_floatv
[1]);
658 glGetIntegerv(GL_AUX_BUFFERS
, &gl_max
);
659 gl_info
->max_aux_buffers
= gl_max
;
660 TRACE_(d3d_caps
)("Offscreen rendering support - number of aux buffers=%d\n", gl_max
);
662 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
663 GL_Extensions
= (const char *) glGetString(GL_EXTENSIONS
);
664 TRACE_(d3d_caps
)("GL_Extensions reported:\n");
666 if (NULL
== GL_Extensions
) {
667 ERR(" GL_Extensions returns NULL\n");
669 while (*GL_Extensions
!= 0x00) {
674 while (isspace(*GL_Extensions
)) GL_Extensions
++;
675 Start
= GL_Extensions
;
676 while (!isspace(*GL_Extensions
) && *GL_Extensions
!= 0x00) {
680 len
= GL_Extensions
- Start
;
681 if (len
== 0 || len
>= sizeof(ThisExtn
))
684 memcpy(ThisExtn
, Start
, len
);
685 ThisExtn
[len
] = '\0';
686 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
688 for (i
= 0; i
< (sizeof(EXTENSION_MAP
) / sizeof(*EXTENSION_MAP
)); ++i
) {
689 if (!strcmp(ThisExtn
, EXTENSION_MAP
[i
].extension_string
)) {
690 TRACE_(d3d_caps
)(" FOUND: %s support\n", EXTENSION_MAP
[i
].extension_string
);
691 gl_info
->supported
[EXTENSION_MAP
[i
].extension
] = TRUE
;
696 /* Now work out what GL support this card really has */
697 #define USE_GL_FUNC(type, pfn, ext, replace) { \
698 DWORD ver = ver_for_ext(ext); \
699 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
700 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
701 else gl_info->pfn = NULL; \
706 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
710 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
711 * loading the functions, otherwise the code above will load the extension entry points instead of the
712 * core functions, which may not work
714 for (i
= 0; i
< (sizeof(EXTENSION_MAP
) / sizeof(*EXTENSION_MAP
)); ++i
) {
715 if (gl_info
->supported
[EXTENSION_MAP
[i
].extension
] == FALSE
&&
716 EXTENSION_MAP
[i
].version
<= gl_info
->gl_driver_version
&& EXTENSION_MAP
[i
].version
) {
717 TRACE_(d3d_caps
)(" GL CORE: %s support\n", EXTENSION_MAP
[i
].extension_string
);
718 gl_info
->supported
[EXTENSION_MAP
[i
].extension
] = TRUE
;
722 if (gl_info
->supported
[APPLE_FENCE
]) {
723 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
724 * The apple extension interacts with some other apple exts. Disable the NV
725 * extension if the apple one is support to prevent confusion in other parts
728 gl_info
->supported
[NV_FENCE
] = FALSE
;
730 if (gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
]) {
731 TRACE_(d3d_caps
)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
732 gl_info
->supported
[NV_TEXGEN_REFLECTION
] = TRUE
;
734 if (gl_info
->supported
[NV_TEXTURE_SHADER2
]) {
735 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
736 * Won't occur in any real world situation though
738 gl_info
->supported
[ATI_ENVMAP_BUMPMAP
] = FALSE
;
740 if (gl_info
->supported
[ARB_DRAW_BUFFERS
]) {
741 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB
, &gl_max
);
742 gl_info
->max_buffers
= gl_max
;
743 TRACE_(d3d_caps
)("Max draw buffers: %u\n", gl_max
);
745 if (gl_info
->supported
[ARB_MULTITEXTURE
]) {
746 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB
, &gl_max
);
747 gl_info
->max_textures
= min(MAX_TEXTURES
, gl_max
);
748 TRACE_(d3d_caps
)("Max textures: %d\n", gl_info
->max_textures
);
750 if (gl_info
->supported
[NV_REGISTER_COMBINERS
]) {
752 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV
, &tmp
);
753 gl_info
->max_texture_stages
= min(MAX_TEXTURES
, tmp
);
755 gl_info
->max_texture_stages
= min(MAX_TEXTURES
, gl_max
);
757 TRACE_(d3d_caps
)("Max texture stages: %d\n", gl_info
->max_texture_stages
);
759 if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
]) {
761 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB
, &tmp
);
762 gl_info
->max_fragment_samplers
= min(MAX_FRAGMENT_SAMPLERS
, tmp
);
764 gl_info
->max_fragment_samplers
= max(gl_info
->max_fragment_samplers
, gl_max
);
766 TRACE_(d3d_caps
)("Max fragment samplers: %d\n", gl_info
->max_fragment_samplers
);
768 if (gl_info
->supported
[ARB_VERTEX_SHADER
]) {
770 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB
, &tmp
);
771 gl_info
->max_vertex_samplers
= tmp
;
772 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB
, &tmp
);
773 gl_info
->max_combined_samplers
= tmp
;
775 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
776 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
777 * an issue because then the sampler setup only depends on the two shaders. If a pixel
778 * shader is used with fixed function vertex processing we're fine too because fixed function
779 * vertex processing doesn't use any samplers. If fixed function fragment processing is
780 * used we have to make sure that all vertex sampler setups are valid together with all
781 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
782 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
783 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
784 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
785 * a fixed function pipeline anymore.
787 * So this is just a check to check that our assumption holds true. If not, write a warning
788 * and reduce the number of vertex samplers or propably disable vertex texture fetch.
790 if(gl_info
->max_vertex_samplers
&&
791 MAX_TEXTURES
+ gl_info
->max_vertex_samplers
> gl_info
->max_combined_samplers
) {
792 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
793 gl_info
->max_vertex_samplers
, gl_info
->max_combined_samplers
);
794 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
795 gl_info
->max_vertex_samplers
= max(0, gl_info
->max_combined_samplers
- MAX_TEXTURES
);
798 gl_info
->max_combined_samplers
= gl_info
->max_fragment_samplers
;
800 TRACE_(d3d_caps
)("Max vertex samplers: %u\n", gl_info
->max_vertex_samplers
);
801 TRACE_(d3d_caps
)("Max combined samplers: %u\n", gl_info
->max_combined_samplers
);
803 if (gl_info
->supported
[ARB_VERTEX_BLEND
]) {
804 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB
, &gl_max
);
805 gl_info
->max_blends
= gl_max
;
806 TRACE_(d3d_caps
)("Max blends: %u\n", gl_info
->max_blends
);
808 if (gl_info
->supported
[EXT_TEXTURE3D
]) {
809 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT
, &gl_max
);
810 gl_info
->max_texture3d_size
= gl_max
;
811 TRACE_(d3d_caps
)("Max texture3D size: %d\n", gl_info
->max_texture3d_size
);
813 if (gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
]) {
814 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
, &gl_max
);
815 gl_info
->max_anisotropy
= gl_max
;
816 TRACE_(d3d_caps
)("Max anisotropy: %d\n", gl_info
->max_anisotropy
);
818 if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
]) {
819 gl_info
->ps_arb_version
= PS_VERSION_11
;
820 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
, &gl_max
));
821 gl_info
->ps_arb_constantsF
= gl_max
;
822 TRACE_(d3d_caps
)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info
->ps_arb_constantsF
);
823 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
, &gl_max
));
824 gl_info
->ps_arb_max_temps
= gl_max
;
825 TRACE_(d3d_caps
)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info
->ps_arb_max_temps
);
826 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
, &gl_max
));
827 gl_info
->ps_arb_max_instructions
= gl_max
;
828 TRACE_(d3d_caps
)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info
->ps_arb_max_instructions
);
830 if (gl_info
->supported
[ARB_VERTEX_PROGRAM
]) {
831 gl_info
->vs_arb_version
= VS_VERSION_11
;
832 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
, &gl_max
));
833 gl_info
->vs_arb_constantsF
= gl_max
;
834 TRACE_(d3d_caps
)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info
->vs_arb_constantsF
);
835 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
, &gl_max
));
836 gl_info
->vs_arb_max_temps
= gl_max
;
837 TRACE_(d3d_caps
)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info
->vs_arb_max_temps
);
838 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
, &gl_max
));
839 gl_info
->vs_arb_max_instructions
= gl_max
;
840 TRACE_(d3d_caps
)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info
->vs_arb_max_instructions
);
842 gl_info
->arb_vs_offset_limit
= test_arb_vs_offset_limit(gl_info
);
844 if (gl_info
->supported
[ARB_VERTEX_SHADER
]) {
845 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB
, &gl_max
);
846 gl_info
->vs_glsl_constantsF
= gl_max
/ 4;
847 TRACE_(d3d_caps
)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info
->vs_glsl_constantsF
);
849 if (gl_info
->supported
[ARB_FRAGMENT_SHADER
]) {
850 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB
, &gl_max
);
851 gl_info
->ps_glsl_constantsF
= gl_max
/ 4;
852 TRACE_(d3d_caps
)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info
->ps_glsl_constantsF
);
853 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB
, &gl_max
);
854 gl_info
->max_glsl_varyings
= gl_max
;
855 TRACE_(d3d_caps
)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max
, gl_max
/ 4);
857 if (gl_info
->supported
[EXT_VERTEX_SHADER
]) {
858 gl_info
->vs_ati_version
= VS_VERSION_11
;
860 if (gl_info
->supported
[NV_VERTEX_PROGRAM3
]) {
861 gl_info
->vs_nv_version
= VS_VERSION_30
;
862 } else if (gl_info
->supported
[NV_VERTEX_PROGRAM2
]) {
863 gl_info
->vs_nv_version
= VS_VERSION_20
;
864 } else if (gl_info
->supported
[NV_VERTEX_PROGRAM1_1
]) {
865 gl_info
->vs_nv_version
= VS_VERSION_11
;
866 } else if (gl_info
->supported
[NV_VERTEX_PROGRAM
]) {
867 gl_info
->vs_nv_version
= VS_VERSION_10
;
869 if (gl_info
->supported
[NV_FRAGMENT_PROGRAM2
]) {
870 gl_info
->ps_nv_version
= PS_VERSION_30
;
871 } else if (gl_info
->supported
[NV_FRAGMENT_PROGRAM
]) {
872 gl_info
->ps_nv_version
= PS_VERSION_20
;
876 checkGLcall("extension detection\n");
878 /* In some cases the number of texture stages can be larger than the number
879 * of samplers. The GF4 for example can use only 2 samplers (no fragment
880 * shaders), but 8 texture stages (register combiners). */
881 gl_info
->max_sampler_stages
= max(gl_info
->max_fragment_samplers
, gl_info
->max_texture_stages
);
883 /* We can only use ORM_FBO when the hardware supports it. */
884 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
&& !gl_info
->supported
[EXT_FRAMEBUFFER_OBJECT
]) {
885 WARN_(d3d_caps
)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
886 wined3d_settings
.offscreen_rendering_mode
= ORM_PBUFFER
;
889 /* MRTs are currently only supported when FBOs are used. */
890 if (wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
) {
891 gl_info
->max_buffers
= 1;
894 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
895 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
896 * in case of the latest videocards in the number of pixel/vertex pipelines.
898 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
899 * rendering. Various games use this information to get a rough estimation of the features of the card
900 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
901 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
902 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
905 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
906 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
907 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
908 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
909 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
910 * is used for rendering which is not always the case). This would work but it is not very portable. Second
911 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
914 * As said most games only use the PCI id to get an indication of the capabilities of the card.
915 * It doesn't really matter if the given id is the correct one if we return the id of a card with
916 * similar 3d features.
918 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
919 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
920 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
921 * won't pass we return a default card. This way is better than maintaining a full card database as even
922 * without a full database we can return a card with similar features. Second the size of the database
923 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
924 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
925 * to distinguishes between different models from that family.
927 * The code also selects a default amount of video memory which we will use for an estimation of the amount
928 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
929 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
930 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
931 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
932 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
933 * memory behind our backs if really needed.
934 * Note that the amout of video memory can be overruled using a registry setting.
936 switch (gl_info
->gl_vendor
) {
938 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
939 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
941 if(WINE_D3D9_CAPABLE(gl_info
) && (gl_info
->vs_nv_version
== VS_VERSION_30
)) {
942 /* Geforce8 - highend */
943 if (strstr(gl_info
->gl_renderer
, "8800")) {
944 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_8800GTS
;
945 vidmem
= 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
947 /* Geforce8 - midend */
948 else if(strstr(gl_info
->gl_renderer
, "8600") ||
949 strstr(gl_info
->gl_renderer
, "8700"))
951 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_8600GT
;
954 /* Geforce8 - lowend */
955 else if(strstr(gl_info
->gl_renderer
, "8300") ||
956 strstr(gl_info
->gl_renderer
, "8400") ||
957 strstr(gl_info
->gl_renderer
, "8500"))
959 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_8300GS
;
960 vidmem
= 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
962 /* Geforce7 - highend */
963 else if(strstr(gl_info
->gl_renderer
, "7800") ||
964 strstr(gl_info
->gl_renderer
, "7900") ||
965 strstr(gl_info
->gl_renderer
, "7950") ||
966 strstr(gl_info
->gl_renderer
, "Quadro FX 4") ||
967 strstr(gl_info
->gl_renderer
, "Quadro FX 5"))
969 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_7800GT
;
970 vidmem
= 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
972 /* Geforce7 midend / Geforce6 highend */
973 else if(strstr(gl_info
->gl_renderer
, "6800") ||
974 strstr(gl_info
->gl_renderer
, "7600") ||
975 strstr(gl_info
->gl_renderer
, "7700"))
977 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6800
;
978 vidmem
= 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
980 /* Geforce6 - midend */
981 else if(strstr(gl_info
->gl_renderer
, "6600") ||
982 strstr(gl_info
->gl_renderer
, "6610") ||
983 strstr(gl_info
->gl_renderer
, "6700"))
985 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6600GT
;
986 vidmem
= 128; /* A 6600GT has 128-256MB */
988 /* Geforce6/7 lowend */
990 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6200
; /* Geforce 6100/6150/6200/7300/7400/7500 */
993 } else if(WINE_D3D9_CAPABLE(gl_info
)) {
994 /* GeforceFX - highend */
995 if (strstr(gl_info
->gl_renderer
, "5800") ||
996 strstr(gl_info
->gl_renderer
, "5900") ||
997 strstr(gl_info
->gl_renderer
, "5950") ||
998 strstr(gl_info
->gl_renderer
, "Quadro FX"))
1000 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5800
;
1001 vidmem
= 256; /* 5800-5900 cards use 256MB */
1003 /* GeforceFX - midend */
1004 else if(strstr(gl_info
->gl_renderer
, "5600") ||
1005 strstr(gl_info
->gl_renderer
, "5650") ||
1006 strstr(gl_info
->gl_renderer
, "5700") ||
1007 strstr(gl_info
->gl_renderer
, "5750"))
1009 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5600
;
1010 vidmem
= 128; /* A 5600 uses 128-256MB */
1012 /* GeforceFX - lowend */
1014 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5200
; /* GeforceFX 5100/5200/5250/5300/5500 */
1015 vidmem
= 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1017 } else if(WINE_D3D8_CAPABLE(gl_info
)) {
1018 if (strstr(gl_info
->gl_renderer
, "GeForce4 Ti") || strstr(gl_info
->gl_renderer
, "Quadro4")) {
1019 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_TI4200
; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1020 vidmem
= 64; /* Geforce4 Ti cards have 64-128MB */
1023 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE3
; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1024 vidmem
= 64; /* Geforce3 cards have 64-128MB */
1026 } else if(WINE_D3D7_CAPABLE(gl_info
)) {
1027 if (strstr(gl_info
->gl_renderer
, "GeForce4 MX")) {
1028 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_MX
; /* MX420/MX440/MX460/MX4000 */
1029 vidmem
= 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1031 else if(strstr(gl_info
->gl_renderer
, "GeForce2 MX") || strstr(gl_info
->gl_renderer
, "Quadro2 MXR")) {
1032 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE2_MX
; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1033 vidmem
= 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1035 else if(strstr(gl_info
->gl_renderer
, "GeForce2") || strstr(gl_info
->gl_renderer
, "Quadro2")) {
1036 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE2
; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1037 vidmem
= 32; /* Geforce2 GPUs have 32-64MB of video memory */
1040 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE
; /* Geforce 256/DDR, Quadro */
1041 vidmem
= 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1044 if (strstr(gl_info
->gl_renderer
, "TNT2")) {
1045 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT2
; /* Riva TNT2 standard/M64/Pro/Ultra */
1046 vidmem
= 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1049 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT
; /* Riva TNT, Vanta */
1050 vidmem
= 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1055 if(WINE_D3D9_CAPABLE(gl_info
)) {
1056 /* Radeon R6xx HD2900 - highend */
1057 if (strstr(gl_info
->gl_renderer
, "HD 2900")) {
1058 gl_info
->gl_card
= CARD_ATI_RADEON_HD2900
;
1059 vidmem
= 512; /* HD2900 uses 512-1024MB */
1061 /* Radeon R6xx HD2600- midend */
1062 else if (strstr(gl_info
->gl_renderer
, "HD 2600")) {
1063 gl_info
->gl_card
= CARD_ATI_RADEON_HD2600
;
1064 vidmem
= 256; /* HD2600 uses 256-512MB */
1066 /* Radeon R6xx HD2300/HD2400 - lowend */
1067 else if (strstr(gl_info
->gl_renderer
, "HD 2300") ||
1068 strstr(gl_info
->gl_renderer
, "HD 2400"))
1070 gl_info
->gl_card
= CARD_ATI_RADEON_HD2300
;
1071 vidmem
= 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1074 else if (strstr(gl_info
->gl_renderer
, "X1600") ||
1075 strstr(gl_info
->gl_renderer
, "X1650") ||
1076 strstr(gl_info
->gl_renderer
, "X1800") ||
1077 strstr(gl_info
->gl_renderer
, "X1900") ||
1078 strstr(gl_info
->gl_renderer
, "X1950"))
1080 gl_info
->gl_card
= CARD_ATI_RADEON_X1600
;
1081 vidmem
= 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1083 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1084 else if(strstr(gl_info
->gl_renderer
, "X700") ||
1085 strstr(gl_info
->gl_renderer
, "X800") ||
1086 strstr(gl_info
->gl_renderer
, "X850") ||
1087 strstr(gl_info
->gl_renderer
, "X1300") ||
1088 strstr(gl_info
->gl_renderer
, "X1400") ||
1089 strstr(gl_info
->gl_renderer
, "X1450") ||
1090 strstr(gl_info
->gl_renderer
, "X1550"))
1092 gl_info
->gl_card
= CARD_ATI_RADEON_X700
;
1093 vidmem
= 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1097 gl_info
->gl_card
= CARD_ATI_RADEON_9500
; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1098 vidmem
= 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1100 } else if(WINE_D3D8_CAPABLE(gl_info
)) {
1101 gl_info
->gl_card
= CARD_ATI_RADEON_8500
; /* Radeon 8500/9000/9100/9200/9300 */
1102 vidmem
= 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1103 } else if(WINE_D3D7_CAPABLE(gl_info
)) {
1104 gl_info
->gl_card
= CARD_ATI_RADEON_7200
; /* Radeon 7000/7100/7200/7500 */
1105 vidmem
= 32; /* There are models with up to 64MB */
1107 gl_info
->gl_card
= CARD_ATI_RAGE_128PRO
;
1108 vidmem
= 16; /* There are 16-32MB models */
1112 if (strstr(gl_info
->gl_renderer
, "915GM")) {
1113 gl_info
->gl_card
= CARD_INTEL_I915GM
;
1114 } else if (strstr(gl_info
->gl_renderer
, "915G")) {
1115 gl_info
->gl_card
= CARD_INTEL_I915G
;
1116 } else if (strstr(gl_info
->gl_renderer
, "865G")) {
1117 gl_info
->gl_card
= CARD_INTEL_I865G
;
1118 } else if (strstr(gl_info
->gl_renderer
, "855G")) {
1119 gl_info
->gl_card
= CARD_INTEL_I855G
;
1120 } else if (strstr(gl_info
->gl_renderer
, "830G")) {
1121 gl_info
->gl_card
= CARD_INTEL_I830G
;
1123 gl_info
->gl_card
= CARD_INTEL_I915G
;
1129 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1130 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1131 * them a good generic choice.
1133 gl_info
->gl_vendor
= VENDOR_NVIDIA
;
1134 if(WINE_D3D9_CAPABLE(gl_info
))
1135 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5600
;
1136 else if(WINE_D3D8_CAPABLE(gl_info
))
1137 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE3
;
1138 else if(WINE_D3D7_CAPABLE(gl_info
))
1139 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE
;
1140 else if(WINE_D3D6_CAPABLE(gl_info
))
1141 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT
;
1143 gl_info
->gl_card
= CARD_NVIDIA_RIVA_128
;
1145 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info
->gl_vendor
, gl_info
->gl_card
);
1147 /* If we have an estimate use it, else default to 64MB; */
1149 gl_info
->vidmem
= vidmem
*1024*1024; /* convert from MBs to bytes */
1151 gl_info
->vidmem
= WINE_DEFAULT_VIDMEM
;
1153 /* Load all the lookup tables
1154 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1155 minLookup
[WINELOOKUP_WARPPARAM
] = WINED3DTADDRESS_WRAP
;
1156 maxLookup
[WINELOOKUP_WARPPARAM
] = WINED3DTADDRESS_MIRRORONCE
;
1158 minLookup
[WINELOOKUP_MAGFILTER
] = WINED3DTEXF_NONE
;
1159 maxLookup
[WINELOOKUP_MAGFILTER
] = WINED3DTEXF_ANISOTROPIC
;
1162 for (i
= 0; i
< MAX_LOOKUPS
; i
++) {
1163 stateLookup
[i
] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup
[i
]) * (1 + maxLookup
[i
] - minLookup
[i
]) );
1166 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_WRAP
- minLookup
[WINELOOKUP_WARPPARAM
]] = GL_REPEAT
;
1167 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_CLAMP
- minLookup
[WINELOOKUP_WARPPARAM
]] = GL_CLAMP_TO_EDGE
;
1168 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_BORDER
- minLookup
[WINELOOKUP_WARPPARAM
]] =
1169 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] ? GL_CLAMP_TO_BORDER_ARB
: GL_REPEAT
;
1170 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_BORDER
- minLookup
[WINELOOKUP_WARPPARAM
]] =
1171 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] ? GL_CLAMP_TO_BORDER_ARB
: GL_REPEAT
;
1172 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_MIRROR
- minLookup
[WINELOOKUP_WARPPARAM
]] =
1173 gl_info
->supported
[ARB_TEXTURE_MIRRORED_REPEAT
] ? GL_MIRRORED_REPEAT_ARB
: GL_REPEAT
;
1174 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_MIRRORONCE
- minLookup
[WINELOOKUP_WARPPARAM
]] =
1175 gl_info
->supported
[ATI_TEXTURE_MIRROR_ONCE
] ? GL_MIRROR_CLAMP_TO_EDGE_ATI
: GL_REPEAT
;
1177 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_NONE
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_NEAREST
;
1178 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_POINT
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_NEAREST
;
1179 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_LINEAR
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_LINEAR
;
1180 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_ANISOTROPIC
- minLookup
[WINELOOKUP_MAGFILTER
]] =
1181 gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR
: GL_NEAREST
;
1184 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_NONE
] = GL_LINEAR
;
1185 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_POINT
] = GL_LINEAR
;
1186 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_LINEAR
] = GL_LINEAR
;
1187 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_NONE
] = GL_NEAREST
;
1188 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_POINT
] = GL_NEAREST_MIPMAP_NEAREST
;
1189 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_LINEAR
] = GL_NEAREST_MIPMAP_LINEAR
;
1190 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_NONE
] = GL_LINEAR
;
1191 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_POINT
] = GL_LINEAR_MIPMAP_NEAREST
;
1192 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_LINEAR
] = GL_LINEAR_MIPMAP_LINEAR
;
1193 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_NONE
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ?
1194 GL_LINEAR_MIPMAP_LINEAR
: GL_LINEAR
;
1195 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_POINT
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR_MIPMAP_NEAREST
: GL_LINEAR
;
1196 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_LINEAR
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR_MIPMAP_LINEAR
: GL_LINEAR
;
1198 /* TODO: config lookups */
1200 /* Make sure there's an active HDC else the WGL extensions will fail */
1201 hdc
= pwglGetCurrentDC();
1203 WGL_Extensions
= GL_EXTCALL(wglGetExtensionsStringARB(hdc
));
1204 TRACE_(d3d_caps
)("WGL_Extensions reported:\n");
1206 if (NULL
== WGL_Extensions
) {
1207 ERR(" WGL_Extensions returns NULL\n");
1209 while (*WGL_Extensions
!= 0x00) {
1214 while (isspace(*WGL_Extensions
)) WGL_Extensions
++;
1215 Start
= WGL_Extensions
;
1216 while (!isspace(*WGL_Extensions
) && *WGL_Extensions
!= 0x00) {
1220 len
= WGL_Extensions
- Start
;
1221 if (len
== 0 || len
>= sizeof(ThisExtn
))
1224 memcpy(ThisExtn
, Start
, len
);
1225 ThisExtn
[len
] = '\0';
1226 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
1228 if (!strcmp(ThisExtn
, "WGL_ARB_pbuffer")) {
1229 gl_info
->supported
[WGL_ARB_PBUFFER
] = TRUE
;
1230 TRACE_(d3d_caps
)("FOUND: WGL_ARB_pbuffer support\n");
1237 return return_value
;
1239 #undef GLINFO_LOCATION
1241 /**********************************************************
1242 * IWineD3D implementation follows
1243 **********************************************************/
1245 static UINT WINAPI
IWineD3DImpl_GetAdapterCount (IWineD3D
*iface
) {
1246 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1248 TRACE_(d3d_caps
)("(%p): Reporting %d adapters\n", This
, numAdapters
);
1252 static HRESULT WINAPI
IWineD3DImpl_RegisterSoftwareDevice(IWineD3D
*iface
, void* pInitializeFunction
) {
1253 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1254 FIXME("(%p)->(%p): stub\n", This
, pInitializeFunction
);
1258 static HMONITOR WINAPI
IWineD3DImpl_GetAdapterMonitor(IWineD3D
*iface
, UINT Adapter
) {
1259 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1261 if (Adapter
>= IWineD3DImpl_GetAdapterCount(iface
)) {
1265 TRACE_(d3d_caps
)("(%p)->(%d)\n", This
, Adapter
);
1266 return MonitorFromPoint(Adapters
[Adapter
].monitorPoint
, MONITOR_DEFAULTTOPRIMARY
);
1269 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1270 of the same bpp but different resolutions */
1272 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1273 static UINT WINAPI
IWineD3DImpl_GetAdapterModeCount(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
) {
1274 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1275 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Format: %s)\n", This
, Adapter
, debug_d3dformat(Format
));
1277 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1281 /* TODO: Store modes per adapter and read it from the adapter structure */
1282 if (Adapter
== 0) { /* Display */
1286 if (!DEBUG_SINGLE_MODE
) {
1289 ZeroMemory(&DevModeW
, sizeof(DevModeW
));
1290 DevModeW
.dmSize
= sizeof(DevModeW
);
1291 while (EnumDisplaySettingsExW(NULL
, j
, &DevModeW
, 0)) {
1295 case WINED3DFMT_UNKNOWN
:
1296 /* This is for D3D8, do not enumerate P8 here */
1297 if (DevModeW
.dmBitsPerPel
== 32 ||
1298 DevModeW
.dmBitsPerPel
== 16) i
++;
1300 case WINED3DFMT_X8R8G8B8
:
1301 if (DevModeW
.dmBitsPerPel
== 32) i
++;
1303 case WINED3DFMT_R5G6B5
:
1304 if (DevModeW
.dmBitsPerPel
== 16) i
++;
1307 if (DevModeW
.dmBitsPerPel
== 8) i
++;
1310 /* Skip other modes as they do not match the requested format */
1319 TRACE_(d3d_caps
)("(%p}->(Adapter: %d) => %d (out of %d)\n", This
, Adapter
, i
, j
);
1322 FIXME_(d3d_caps
)("Adapter not primary display\n");
1327 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1328 static HRESULT WINAPI
IWineD3DImpl_EnumAdapterModes(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
, UINT Mode
, WINED3DDISPLAYMODE
* pMode
) {
1329 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1330 TRACE_(d3d_caps
)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This
, Adapter
, Mode
, pMode
, debug_d3dformat(Format
));
1332 /* Validate the parameters as much as possible */
1333 if (NULL
== pMode
||
1334 Adapter
>= IWineD3DImpl_GetAdapterCount(iface
) ||
1335 Mode
>= IWineD3DImpl_GetAdapterModeCount(iface
, Adapter
, Format
)) {
1336 return WINED3DERR_INVALIDCALL
;
1339 /* TODO: Store modes per adapter and read it from the adapter structure */
1340 if (Adapter
== 0 && !DEBUG_SINGLE_MODE
) { /* Display */
1346 ZeroMemory(&DevModeW
, sizeof(DevModeW
));
1347 DevModeW
.dmSize
= sizeof(DevModeW
);
1349 /* If we are filtering to a specific format (D3D9), then need to skip
1350 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1351 just count through the ones with valid bit depths */
1352 while ((i
<=Mode
) && EnumDisplaySettingsExW(NULL
, j
++, &DevModeW
, 0)) {
1355 case WINED3DFMT_UNKNOWN
:
1356 /* This is D3D8. Do not enumerate P8 here */
1357 if (DevModeW
.dmBitsPerPel
== 32 ||
1358 DevModeW
.dmBitsPerPel
== 16) i
++;
1360 case WINED3DFMT_X8R8G8B8
:
1361 if (DevModeW
.dmBitsPerPel
== 32) i
++;
1363 case WINED3DFMT_R5G6B5
:
1364 if (DevModeW
.dmBitsPerPel
== 16) i
++;
1367 if (DevModeW
.dmBitsPerPel
== 8) i
++;
1370 /* Modes that don't match what we support can get an early-out */
1371 TRACE_(d3d_caps
)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format
));
1372 return WINED3DERR_INVALIDCALL
;
1377 TRACE_(d3d_caps
)("No modes found for format (%x - %s)\n", Format
, debug_d3dformat(Format
));
1378 return WINED3DERR_INVALIDCALL
;
1382 /* Now get the display mode via the calculated index */
1383 if (EnumDisplaySettingsExW(NULL
, ModeIdx
, &DevModeW
, 0)) {
1384 pMode
->Width
= DevModeW
.dmPelsWidth
;
1385 pMode
->Height
= DevModeW
.dmPelsHeight
;
1386 pMode
->RefreshRate
= WINED3DADAPTER_DEFAULT
;
1387 if (DevModeW
.dmFields
& DM_DISPLAYFREQUENCY
)
1388 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
1390 if (Format
== WINED3DFMT_UNKNOWN
)
1392 switch (DevModeW
.dmBitsPerPel
)
1395 pMode
->Format
= WINED3DFMT_P8
;
1398 pMode
->Format
= WINED3DFMT_R5G6B5
;
1401 pMode
->Format
= WINED3DFMT_X8R8G8B8
;
1404 pMode
->Format
= WINED3DFMT_UNKNOWN
;
1405 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW
.dmBitsPerPel
);
1408 pMode
->Format
= Format
;
1411 TRACE_(d3d_caps
)("Requested mode out of range %d\n", Mode
);
1412 return WINED3DERR_INVALIDCALL
;
1415 TRACE_(d3d_caps
)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode
->Width
, pMode
->Height
,
1416 pMode
->RefreshRate
, pMode
->Format
, debug_d3dformat(pMode
->Format
),
1417 DevModeW
.dmBitsPerPel
);
1419 } else if (DEBUG_SINGLE_MODE
) {
1420 /* Return one setting of the format requested */
1421 if (Mode
> 0) return WINED3DERR_INVALIDCALL
;
1423 pMode
->Height
= 600;
1424 pMode
->RefreshRate
= 60;
1425 pMode
->Format
= (Format
== WINED3DFMT_UNKNOWN
) ? WINED3DFMT_X8R8G8B8
: Format
;
1427 FIXME_(d3d_caps
)("Adapter not primary display\n");
1433 static HRESULT WINAPI
IWineD3DImpl_GetAdapterDisplayMode(IWineD3D
*iface
, UINT Adapter
, WINED3DDISPLAYMODE
* pMode
) {
1434 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1435 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, pMode: %p)\n", This
, Adapter
, pMode
);
1437 if (NULL
== pMode
||
1438 Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1439 return WINED3DERR_INVALIDCALL
;
1442 if (Adapter
== 0) { /* Display */
1446 ZeroMemory(&DevModeW
, sizeof(DevModeW
));
1447 DevModeW
.dmSize
= sizeof(DevModeW
);
1449 EnumDisplaySettingsExW(NULL
, ENUM_CURRENT_SETTINGS
, &DevModeW
, 0);
1450 pMode
->Width
= DevModeW
.dmPelsWidth
;
1451 pMode
->Height
= DevModeW
.dmPelsHeight
;
1452 bpp
= DevModeW
.dmBitsPerPel
;
1453 pMode
->RefreshRate
= WINED3DADAPTER_DEFAULT
;
1454 if (DevModeW
.dmFields
&DM_DISPLAYFREQUENCY
)
1456 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
1460 case 8: pMode
->Format
= WINED3DFMT_R3G3B2
; break;
1461 case 16: pMode
->Format
= WINED3DFMT_R5G6B5
; break;
1462 case 24: pMode
->Format
= WINED3DFMT_X8R8G8B8
; break; /* Robots needs 24bit to be X8R8G8B8 */
1463 case 32: pMode
->Format
= WINED3DFMT_X8R8G8B8
; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1464 default: pMode
->Format
= WINED3DFMT_UNKNOWN
;
1468 FIXME_(d3d_caps
)("Adapter not primary display\n");
1471 TRACE_(d3d_caps
)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode
->Width
,
1472 pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
1476 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1477 and fields being inserted in the middle, a new structure is used in place */
1478 static HRESULT WINAPI
IWineD3DImpl_GetAdapterIdentifier(IWineD3D
*iface
, UINT Adapter
, DWORD Flags
,
1479 WINED3DADAPTER_IDENTIFIER
* pIdentifier
) {
1480 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1482 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This
, Adapter
, Flags
, pIdentifier
);
1484 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1485 return WINED3DERR_INVALIDCALL
;
1488 /* Return the information requested */
1489 TRACE_(d3d_caps
)("device/Vendor Name and Version detection using FillGLCaps\n");
1490 strcpy(pIdentifier
->Driver
, Adapters
[Adapter
].driver
);
1491 strcpy(pIdentifier
->Description
, Adapters
[Adapter
].description
);
1493 /* Note dx8 doesn't supply a DeviceName */
1494 if (NULL
!= pIdentifier
->DeviceName
) strcpy(pIdentifier
->DeviceName
, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1495 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1496 pIdentifier
->DriverVersion
->u
.HighPart
= MAKEDWORD_VERSION(6, 14);
1497 pIdentifier
->DriverVersion
->u
.LowPart
= Adapters
[Adapter
].gl_info
.gl_driver_version
;
1498 *(pIdentifier
->VendorId
) = Adapters
[Adapter
].gl_info
.gl_vendor
;
1499 *(pIdentifier
->DeviceId
) = Adapters
[Adapter
].gl_info
.gl_card
;
1500 *(pIdentifier
->SubSysId
) = 0;
1501 *(pIdentifier
->Revision
) = 0;
1503 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1504 if (Flags
& WINED3DENUM_NO_WHQL_LEVEL
) {
1505 *(pIdentifier
->WHQLLevel
) = 0;
1507 *(pIdentifier
->WHQLLevel
) = 1;
1513 static BOOL
IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat
*cfg
, WINED3DFORMAT Format
) {
1514 short redSize
, greenSize
, blueSize
, alphaSize
, colorBits
;
1519 if(!getColorBits(Format
, &redSize
, &greenSize
, &blueSize
, &alphaSize
, &colorBits
)) {
1520 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format
));
1524 if(cfg
->redSize
< redSize
)
1527 if(cfg
->greenSize
< greenSize
)
1530 if(cfg
->blueSize
< blueSize
)
1533 if(cfg
->alphaSize
< alphaSize
)
1539 static BOOL
IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat
*cfg
, WINED3DFORMAT Format
) {
1540 short depthSize
, stencilSize
;
1545 if(!getDepthStencilBits(Format
, &depthSize
, &stencilSize
)) {
1546 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format
));
1550 if(cfg
->depthSize
< depthSize
)
1553 if(cfg
->stencilSize
< stencilSize
)
1559 static HRESULT WINAPI
IWineD3DImpl_CheckDepthStencilMatch(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1560 WINED3DFORMAT AdapterFormat
,
1561 WINED3DFORMAT RenderTargetFormat
,
1562 WINED3DFORMAT DepthStencilFormat
) {
1563 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1565 WineD3D_PixelFormat
*cfgs
;
1568 WARN_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1570 DeviceType
, debug_d3ddevicetype(DeviceType
),
1571 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1572 RenderTargetFormat
, debug_d3dformat(RenderTargetFormat
),
1573 DepthStencilFormat
, debug_d3dformat(DepthStencilFormat
));
1575 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1576 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This
, Adapter
, IWineD3D_GetAdapterCount(iface
));
1577 return WINED3DERR_INVALIDCALL
;
1580 cfgs
= Adapters
[Adapter
].cfgs
;
1581 nCfgs
= Adapters
[Adapter
].nCfgs
;
1582 for (it
= 0; it
< nCfgs
; ++it
) {
1583 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs
[it
], RenderTargetFormat
)) {
1584 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs
[it
], DepthStencilFormat
)) {
1585 TRACE_(d3d_caps
)("(%p) : Formats matched\n", This
);
1590 WARN_(d3d_caps
)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat
), debug_d3dformat(DepthStencilFormat
));
1592 return WINED3DERR_NOTAVAILABLE
;
1595 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1596 WINED3DFORMAT SurfaceFormat
,
1597 BOOL Windowed
, WINED3DMULTISAMPLE_TYPE MultiSampleType
, DWORD
* pQualityLevels
) {
1599 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1600 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1603 DeviceType
, debug_d3ddevicetype(DeviceType
),
1604 SurfaceFormat
, debug_d3dformat(SurfaceFormat
),
1609 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1610 return WINED3DERR_INVALIDCALL
;
1613 /* TODO: Store in Adapter structure */
1614 if (pQualityLevels
!= NULL
) {
1615 static int s_single_shot
= 0;
1616 if (!s_single_shot
) {
1617 FIXME("Quality levels unsupported at present\n");
1620 *pQualityLevels
= 1; /* Guess at a value! */
1623 if (WINED3DMULTISAMPLE_NONE
== MultiSampleType
) return WINED3D_OK
;
1624 return WINED3DERR_NOTAVAILABLE
;
1627 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceType(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE CheckType
,
1628 WINED3DFORMAT DisplayFormat
, WINED3DFORMAT BackBufferFormat
, BOOL Windowed
) {
1630 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1632 WineD3D_PixelFormat
*cfgs
;
1634 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1636 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1639 CheckType
, debug_d3ddevicetype(CheckType
),
1640 DisplayFormat
, debug_d3dformat(DisplayFormat
),
1641 BackBufferFormat
, debug_d3dformat(BackBufferFormat
),
1644 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1645 WARN_(d3d_caps
)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1646 return WINED3DERR_INVALIDCALL
;
1649 cfgs
= Adapters
[Adapter
].cfgs
;
1650 nCfgs
= Adapters
[Adapter
].nCfgs
;
1651 for (it
= 0; it
< nCfgs
; ++it
) {
1652 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs
[it
], DisplayFormat
)) {
1654 TRACE_(d3d_caps
)("OK\n");
1659 if(hr
!= WINED3D_OK
)
1660 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat
));
1662 if(hr
!= WINED3D_OK
)
1663 TRACE_(d3d_caps
)("returning something different from WINED3D_OK\n");
1668 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1669 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormat(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1670 WINED3DFORMAT AdapterFormat
, DWORD Usage
, WINED3DRESOURCETYPE RType
, WINED3DFORMAT CheckFormat
) {
1671 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1672 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1675 DeviceType
, debug_d3ddevicetype(DeviceType
),
1676 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1677 Usage
, debug_d3dusage(Usage
), debug_d3dusagequery(Usage
),
1678 RType
, debug_d3dresourcetype(RType
),
1679 CheckFormat
, debug_d3dformat(CheckFormat
));
1681 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1682 return WINED3DERR_INVALIDCALL
;
1685 if (Usage
& WINED3DUSAGE_QUERY_FILTER
) {
1686 switch (CheckFormat
) {
1687 /* Filtering not supported */
1688 case WINED3DFMT_R32F
:
1689 case WINED3DFMT_A32B32G32R32F
:
1690 TRACE_(d3d_caps
)("[FAILED]\n");
1691 return WINED3DERR_NOTAVAILABLE
;
1697 if (Usage
& WINED3DUSAGE_AUTOGENMIPMAP
) {
1698 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP
)) {
1699 TRACE_(d3d_caps
)("[FAILED] - No mipmap generation support\n");
1700 return WINED3DERR_NOTAVAILABLE
;
1704 if(RType
== WINED3DRTYPE_VOLUMETEXTURE
) {
1705 if(!GL_SUPPORT(EXT_TEXTURE3D
)) {
1706 TRACE_(d3d_caps
)("[FAILED] - No volume texture support\n");
1707 return WINED3DERR_NOTAVAILABLE
;
1709 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1710 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1711 * app needing one of those formats, don't advertize them to avoid leading apps into
1712 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1715 switch(CheckFormat
) {
1717 case WINED3DFMT_A4L4
:
1718 case WINED3DFMT_R32F
:
1719 case WINED3DFMT_R16F
:
1720 case WINED3DFMT_X8L8V8U8
:
1721 case WINED3DFMT_L6V5U5
:
1722 TRACE_(d3d_caps
)("[FAILED] - No converted formats on volumes\n");
1723 return WINED3DERR_NOTAVAILABLE
;
1725 case WINED3DFMT_Q8W8V8U8
:
1726 case WINED3DFMT_V16U16
:
1727 if(!GL_SUPPORT(NV_TEXTURE_SHADER
)) {
1728 TRACE_(d3d_caps
)("[FAILED] - No converted formats on volumes\n");
1729 return WINED3DERR_NOTAVAILABLE
;
1733 case WINED3DFMT_V8U8
:
1734 if(!GL_SUPPORT(NV_TEXTURE_SHADER
) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP
)) {
1735 TRACE_(d3d_caps
)("[FAILED] - No converted formats on volumes\n");
1736 return WINED3DERR_NOTAVAILABLE
;
1740 case WINED3DFMT_DXT1
:
1741 case WINED3DFMT_DXT2
:
1742 case WINED3DFMT_DXT3
:
1743 case WINED3DFMT_DXT4
:
1744 case WINED3DFMT_DXT5
:
1745 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1746 * compressed texture results in an error. While the D3D refrast does
1747 * support s3tc volumes, at least the nvidia windows driver does not, so
1748 * we're free not to support this format.
1750 TRACE_(d3d_caps
)("[FAILED] - DXTn does not support 3D textures\n");
1751 return WINED3DERR_NOTAVAILABLE
;
1754 /* Do nothing, continue with checking the format below */
1758 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1759 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1760 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1761 if (Usage
& WINED3DUSAGE_QUERY_VERTEXTEXTURE
) {
1762 if (!GL_LIMITS(vertex_samplers
)) {
1763 TRACE_(d3d_caps
)("[FAILED]\n");
1764 return WINED3DERR_NOTAVAILABLE
;
1767 switch (CheckFormat
) {
1768 case WINED3DFMT_A32B32G32R32F
:
1769 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1770 TRACE_(d3d_caps
)("[FAILED]\n");
1771 return WINED3DERR_NOTAVAILABLE
;
1773 TRACE_(d3d_caps
)("[OK]\n");
1777 TRACE_(d3d_caps
)("[FAILED]\n");
1778 return WINED3DERR_NOTAVAILABLE
;
1782 if(Usage
& WINED3DUSAGE_DEPTHSTENCIL
) {
1783 switch (CheckFormat
) {
1784 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1785 * Windows supports only those 3, and enumerating the other formats confuses applications
1787 case WINED3DFMT_D24S8
:
1788 case WINED3DFMT_D24X8
:
1789 case WINED3DFMT_D16
:
1790 TRACE_(d3d_caps
)("[OK]\n");
1792 case WINED3DFMT_D16_LOCKABLE
:
1793 case WINED3DFMT_D24FS8
:
1794 case WINED3DFMT_D32F_LOCKABLE
:
1795 case WINED3DFMT_D24X4S4
:
1796 case WINED3DFMT_D15S1
:
1797 case WINED3DFMT_D32
:
1798 TRACE_(d3d_caps
)("[FAILED]. Disabled because not enumerated on windows\n");
1799 return WINED3DERR_NOTAVAILABLE
;
1801 TRACE_(d3d_caps
)("[FAILED]\n");
1802 return WINED3DERR_NOTAVAILABLE
;
1804 } else if(Usage
& WINED3DUSAGE_RENDERTARGET
) {
1805 switch (CheckFormat
) {
1806 case WINED3DFMT_R8G8B8
:
1807 case WINED3DFMT_A8R8G8B8
:
1808 case WINED3DFMT_X8R8G8B8
:
1809 case WINED3DFMT_R5G6B5
:
1810 case WINED3DFMT_X1R5G5B5
:
1811 case WINED3DFMT_A1R5G5B5
:
1812 case WINED3DFMT_A4R4G4B4
:
1813 case WINED3DFMT_R3G3B2
:
1814 case WINED3DFMT_X4R4G4B4
:
1815 case WINED3DFMT_A8B8G8R8
:
1816 case WINED3DFMT_X8B8G8R8
:
1818 TRACE_(d3d_caps
)("[OK]\n");
1820 case WINED3DFMT_R16F
:
1821 case WINED3DFMT_A16B16G16R16F
:
1822 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL
) || !GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1823 TRACE_(d3d_caps
)("[FAILED]\n");
1824 return WINED3DERR_NOTAVAILABLE
;
1826 TRACE_(d3d_caps
)("[OK]\n");
1828 case WINED3DFMT_A32B32G32R32F
:
1829 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1830 TRACE_(d3d_caps
)("[FAILED]\n");
1831 return WINED3DERR_NOTAVAILABLE
;
1833 TRACE_(d3d_caps
)("[OK]\n");
1836 TRACE_(d3d_caps
)("[FAILED]\n");
1837 return WINED3DERR_NOTAVAILABLE
;
1839 } else if(Usage
& WINED3DUSAGE_QUERY_LEGACYBUMPMAP
) {
1840 if(GL_SUPPORT(NV_REGISTER_COMBINERS
) && GL_SUPPORT(NV_TEXTURE_SHADER2
)) {
1841 switch (CheckFormat
) {
1842 case WINED3DFMT_V8U8
:
1843 TRACE_(d3d_caps
)("[OK]\n");
1845 /* TODO: Other bump map formats */
1847 TRACE_(d3d_caps
)("[FAILED]\n");
1848 return WINED3DERR_NOTAVAILABLE
;
1851 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP
)) {
1852 switch (CheckFormat
) {
1853 case WINED3DFMT_V8U8
:
1854 TRACE_(d3d_caps
)("[OK]\n");
1857 TRACE_(d3d_caps
)("[FAILED]\n");
1858 return WINED3DERR_NOTAVAILABLE
;
1861 TRACE_(d3d_caps
)("[FAILED]\n");
1862 return WINED3DERR_NOTAVAILABLE
;
1865 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
1866 switch (CheckFormat
) {
1867 case WINED3DFMT_DXT1
:
1868 case WINED3DFMT_DXT2
:
1869 case WINED3DFMT_DXT3
:
1870 case WINED3DFMT_DXT4
:
1871 case WINED3DFMT_DXT5
:
1872 TRACE_(d3d_caps
)("[OK]\n");
1875 break; /* Avoid compiler warnings */
1879 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1880 if (GL_SUPPORT(EXT_TEXTURE_SRGB
) && (Usage
& WINED3DUSAGE_QUERY_SRGBREAD
)) {
1881 switch (CheckFormat
) {
1882 case WINED3DFMT_A8R8G8B8
:
1883 case WINED3DFMT_X8R8G8B8
:
1884 case WINED3DFMT_A4R4G4B4
:
1886 case WINED3DFMT_A8L8
:
1887 case WINED3DFMT_DXT1
:
1888 case WINED3DFMT_DXT2
:
1889 case WINED3DFMT_DXT3
:
1890 case WINED3DFMT_DXT4
:
1891 case WINED3DFMT_DXT5
:
1892 TRACE_(d3d_caps
)("[OK]\n");
1896 TRACE_(d3d_caps
)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat
));
1897 return WINED3DERR_NOTAVAILABLE
;
1901 if (GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1903 BOOL half_pixel_support
= GL_SUPPORT(ARB_HALF_FLOAT_PIXEL
);
1905 switch (CheckFormat
) {
1906 case WINED3DFMT_R16F
:
1907 case WINED3DFMT_A16B16G16R16F
:
1908 if (!half_pixel_support
) break;
1909 case WINED3DFMT_R32F
:
1910 case WINED3DFMT_A32B32G32R32F
:
1911 TRACE_(d3d_caps
)("[OK]\n");
1914 break; /* Avoid compiler warnings */
1918 /* This format is nothing special and it is supported perfectly.
1919 * However, ati and nvidia driver on windows do not mark this format as
1920 * supported (tested with the dxCapsViewer) and pretending to
1921 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1922 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1923 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1925 if(This
->dxVersion
> 7 && CheckFormat
== WINED3DFMT_R8G8B8
) {
1926 TRACE_(d3d_caps
)("[FAILED]\n");
1927 return WINED3DERR_NOTAVAILABLE
;
1930 switch (CheckFormat
) {
1933 * supported: RGB(A) formats
1935 case WINED3DFMT_R8G8B8
: /* Enable for dx7, blacklisted for 8 and 9 above */
1936 case WINED3DFMT_A8R8G8B8
:
1937 case WINED3DFMT_X8R8G8B8
:
1938 case WINED3DFMT_R5G6B5
:
1939 case WINED3DFMT_X1R5G5B5
:
1940 case WINED3DFMT_A1R5G5B5
:
1941 case WINED3DFMT_A4R4G4B4
:
1942 case WINED3DFMT_R3G3B2
:
1944 case WINED3DFMT_X4R4G4B4
:
1945 case WINED3DFMT_A8B8G8R8
:
1946 case WINED3DFMT_X8B8G8R8
:
1947 case WINED3DFMT_A2R10G10B10
:
1948 case WINED3DFMT_A2B10G10R10
:
1949 TRACE_(d3d_caps
)("[OK]\n");
1953 * supported: Palettized
1956 TRACE_(d3d_caps
)("[OK]\n");
1960 * Supported: (Alpha)-Luminance
1963 case WINED3DFMT_A8L8
:
1964 case WINED3DFMT_A4L4
:
1965 TRACE_(d3d_caps
)("[OK]\n");
1969 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1970 * GL_NV_texture_shader), but advertized to make apps happy.
1971 * Enable some because games often fail when they are not available
1972 * and are still playable even without bump mapping
1974 case WINED3DFMT_V8U8
:
1975 case WINED3DFMT_V16U16
:
1976 case WINED3DFMT_L6V5U5
:
1977 case WINED3DFMT_X8L8V8U8
:
1978 case WINED3DFMT_Q8W8V8U8
:
1979 WARN_(d3d_caps
)("[Not supported, but pretended to do]\n");
1982 /* Those are not advertized by the nvidia windows driver, and not
1983 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1984 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1985 * ARGB format if needed
1987 case WINED3DFMT_W11V11U10
:
1988 case WINED3DFMT_A2W10V10U10
:
1989 WARN_(d3d_caps
)("[FAILED]\n");
1990 return WINED3DERR_NOTAVAILABLE
;
1993 * DXTN Formats: Handled above
2002 * Odd formats - not supported
2004 case WINED3DFMT_VERTEXDATA
:
2005 case WINED3DFMT_INDEX16
:
2006 case WINED3DFMT_INDEX32
:
2007 case WINED3DFMT_Q16W16V16U16
:
2008 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
2009 return WINED3DERR_NOTAVAILABLE
;
2012 * Float formats: Not supported right now
2014 case WINED3DFMT_G16R16F
:
2015 case WINED3DFMT_G32R32F
:
2016 case WINED3DFMT_CxV8U8
:
2017 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
2018 return WINED3DERR_NOTAVAILABLE
;
2021 case WINED3DFMT_G16R16
:
2022 case WINED3DFMT_A16B16G16R16
:
2023 case WINED3DFMT_A8R3G3B2
:
2024 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
2025 return WINED3DERR_NOTAVAILABLE
;
2027 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2028 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2029 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2030 * We can do instancing with all shader versions, but we need vertex shaders.
2032 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2033 * to enable instancing. WineD3D doesn't need that and just ignores it.
2035 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2037 case WINEMAKEFOURCC('I','N','S','T'):
2038 TRACE("ATI Instancing check hack\n");
2039 if(GL_SUPPORT(ARB_VERTEX_PROGRAM
) || GL_SUPPORT(ARB_VERTEX_SHADER
)) {
2040 TRACE_(d3d_caps
)("[OK]\n");
2043 TRACE_(d3d_caps
)("[FAILED]\n");
2044 return WINED3DERR_NOTAVAILABLE
;
2051 TRACE_(d3d_caps
)("[FAILED]\n");
2052 return WINED3DERR_NOTAVAILABLE
;
2055 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
2056 WINED3DFORMAT SourceFormat
, WINED3DFORMAT TargetFormat
) {
2057 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2059 FIXME_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2062 DeviceType
, debug_d3ddevicetype(DeviceType
),
2063 SourceFormat
, debug_d3dformat(SourceFormat
),
2064 TargetFormat
, debug_d3dformat(TargetFormat
));
2068 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2069 subset of a D3DCAPS9 structure. However, it has to come via a void *
2070 as the d3d8 interface cannot import the d3d9 header */
2071 static HRESULT WINAPI
IWineD3DImpl_GetDeviceCaps(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
, WINED3DCAPS
* pCaps
) {
2073 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2074 int vs_selected_mode
;
2075 int ps_selected_mode
;
2077 TRACE_(d3d_caps
)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This
, Adapter
, DeviceType
, pCaps
);
2079 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
2080 return WINED3DERR_INVALIDCALL
;
2083 select_shader_mode(&Adapters
[Adapter
].gl_info
, DeviceType
, &ps_selected_mode
, &vs_selected_mode
);
2085 /* This function should *not* be modifying GL caps
2086 * TODO: move the functionality where it belongs */
2087 select_shader_max_constants(ps_selected_mode
, vs_selected_mode
, &Adapters
[Adapter
].gl_info
);
2089 /* ------------------------------------------------
2090 The following fields apply to both d3d8 and d3d9
2091 ------------------------------------------------ */
2092 *pCaps
->DeviceType
= (DeviceType
== WINED3DDEVTYPE_HAL
) ? WINED3DDEVTYPE_HAL
: WINED3DDEVTYPE_REF
; /* Not quite true, but use h/w supported by opengl I suppose */
2093 *pCaps
->AdapterOrdinal
= Adapter
;
2096 *pCaps
->Caps2
= WINED3DCAPS2_CANRENDERWINDOWED
|
2097 WINED3DCAPS2_FULLSCREENGAMMA
|
2098 WINED3DCAPS2_DYNAMICTEXTURES
;
2099 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP
)) {
2100 *pCaps
->Caps2
|= WINED3DCAPS2_CANAUTOGENMIPMAP
;
2102 *pCaps
->Caps3
= WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD
;
2103 *pCaps
->PresentationIntervals
= WINED3DPRESENT_INTERVAL_IMMEDIATE
|
2104 WINED3DPRESENT_INTERVAL_ONE
;
2106 *pCaps
->CursorCaps
= WINED3DCURSORCAPS_COLOR
|
2107 WINED3DCURSORCAPS_LOWRES
;
2109 *pCaps
->DevCaps
= WINED3DDEVCAPS_FLOATTLVERTEX
|
2110 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY
|
2111 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY
|
2112 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
2113 WINED3DDEVCAPS_DRAWPRIMTLVERTEX
|
2114 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT
|
2115 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY
|
2116 WINED3DDEVCAPS_PUREDEVICE
|
2117 WINED3DDEVCAPS_HWRASTERIZATION
|
2118 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY
|
2119 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY
|
2120 WINED3DDEVCAPS_CANRENDERAFTERFLIP
|
2121 WINED3DDEVCAPS_DRAWPRIMITIVES2
|
2122 WINED3DDEVCAPS_DRAWPRIMITIVES2EX
|
2123 WINED3DDEVCAPS_RTPATCHES
;
2125 *pCaps
->PrimitiveMiscCaps
= WINED3DPMISCCAPS_CULLNONE
|
2126 WINED3DPMISCCAPS_CULLCCW
|
2127 WINED3DPMISCCAPS_CULLCW
|
2128 WINED3DPMISCCAPS_COLORWRITEENABLE
|
2129 WINED3DPMISCCAPS_CLIPTLVERTS
|
2130 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS
|
2131 WINED3DPMISCCAPS_MASKZ
|
2132 WINED3DPMISCCAPS_BLENDOP
;
2134 WINED3DPMISCCAPS_NULLREFERENCE
2135 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2136 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2137 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2138 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2139 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2140 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2142 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2144 if (GL_SUPPORT(NV_REGISTER_COMBINERS
))
2145 *pCaps
->PrimitiveMiscCaps
|= WINED3DPMISCCAPS_TSSARGTEMP
;
2146 if (GL_SUPPORT(NV_REGISTER_COMBINERS2
))
2147 *pCaps
->PrimitiveMiscCaps
|= WINED3DPMISCCAPS_PERSTAGECONSTANT
;
2150 *pCaps
->RasterCaps
= WINED3DPRASTERCAPS_DITHER
|
2151 WINED3DPRASTERCAPS_PAT
|
2152 WINED3DPRASTERCAPS_WFOG
|
2153 WINED3DPRASTERCAPS_ZFOG
|
2154 WINED3DPRASTERCAPS_FOGVERTEX
|
2155 WINED3DPRASTERCAPS_FOGTABLE
|
2156 WINED3DPRASTERCAPS_STIPPLE
|
2157 WINED3DPRASTERCAPS_SUBPIXEL
|
2158 WINED3DPRASTERCAPS_ZTEST
|
2159 WINED3DPRASTERCAPS_SCISSORTEST
|
2160 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
|
2161 WINED3DPRASTERCAPS_DEPTHBIAS
;
2163 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
2164 *pCaps
->RasterCaps
|= WINED3DPRASTERCAPS_ANISOTROPY
|
2165 WINED3DPRASTERCAPS_ZBIAS
|
2166 WINED3DPRASTERCAPS_MIPMAPLODBIAS
;
2168 if(GL_SUPPORT(NV_FOG_DISTANCE
)) {
2169 *pCaps
->RasterCaps
|= WINED3DPRASTERCAPS_FOGRANGE
;
2172 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2173 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2174 WINED3DPRASTERCAPS_ANTIALIASEDGES
2175 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2176 WINED3DPRASTERCAPS_WBUFFER */
2178 *pCaps
->ZCmpCaps
= WINED3DPCMPCAPS_ALWAYS
|
2179 WINED3DPCMPCAPS_EQUAL
|
2180 WINED3DPCMPCAPS_GREATER
|
2181 WINED3DPCMPCAPS_GREATEREQUAL
|
2182 WINED3DPCMPCAPS_LESS
|
2183 WINED3DPCMPCAPS_LESSEQUAL
|
2184 WINED3DPCMPCAPS_NEVER
|
2185 WINED3DPCMPCAPS_NOTEQUAL
;
2187 *pCaps
->SrcBlendCaps
= WINED3DPBLENDCAPS_BLENDFACTOR
|
2188 WINED3DPBLENDCAPS_BOTHINVSRCALPHA
|
2189 WINED3DPBLENDCAPS_BOTHSRCALPHA
|
2190 WINED3DPBLENDCAPS_DESTALPHA
|
2191 WINED3DPBLENDCAPS_DESTCOLOR
|
2192 WINED3DPBLENDCAPS_INVDESTALPHA
|
2193 WINED3DPBLENDCAPS_INVDESTCOLOR
|
2194 WINED3DPBLENDCAPS_INVSRCALPHA
|
2195 WINED3DPBLENDCAPS_INVSRCCOLOR
|
2196 WINED3DPBLENDCAPS_ONE
|
2197 WINED3DPBLENDCAPS_SRCALPHA
|
2198 WINED3DPBLENDCAPS_SRCALPHASAT
|
2199 WINED3DPBLENDCAPS_SRCCOLOR
|
2200 WINED3DPBLENDCAPS_ZERO
;
2202 *pCaps
->DestBlendCaps
= WINED3DPBLENDCAPS_BLENDFACTOR
|
2203 WINED3DPBLENDCAPS_DESTALPHA
|
2204 WINED3DPBLENDCAPS_DESTCOLOR
|
2205 WINED3DPBLENDCAPS_INVDESTALPHA
|
2206 WINED3DPBLENDCAPS_INVDESTCOLOR
|
2207 WINED3DPBLENDCAPS_INVSRCALPHA
|
2208 WINED3DPBLENDCAPS_INVSRCCOLOR
|
2209 WINED3DPBLENDCAPS_ONE
|
2210 WINED3DPBLENDCAPS_SRCALPHA
|
2211 WINED3DPBLENDCAPS_SRCCOLOR
|
2212 WINED3DPBLENDCAPS_ZERO
;
2213 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2214 * according to the glBlendFunc manpage
2216 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2217 * legacy settings for srcblend only
2220 *pCaps
->AlphaCmpCaps
= WINED3DPCMPCAPS_ALWAYS
|
2221 WINED3DPCMPCAPS_EQUAL
|
2222 WINED3DPCMPCAPS_GREATER
|
2223 WINED3DPCMPCAPS_GREATEREQUAL
|
2224 WINED3DPCMPCAPS_LESS
|
2225 WINED3DPCMPCAPS_LESSEQUAL
|
2226 WINED3DPCMPCAPS_NEVER
|
2227 WINED3DPCMPCAPS_NOTEQUAL
;
2229 *pCaps
->ShadeCaps
= WINED3DPSHADECAPS_SPECULARGOURAUDRGB
|
2230 WINED3DPSHADECAPS_COLORGOURAUDRGB
|
2231 WINED3DPSHADECAPS_ALPHAFLATBLEND
|
2232 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND
|
2233 WINED3DPSHADECAPS_COLORFLATRGB
|
2234 WINED3DPSHADECAPS_FOGFLAT
|
2235 WINED3DPSHADECAPS_FOGGOURAUD
|
2236 WINED3DPSHADECAPS_SPECULARFLATRGB
;
2238 *pCaps
->TextureCaps
= WINED3DPTEXTURECAPS_ALPHA
|
2239 WINED3DPTEXTURECAPS_ALPHAPALETTE
|
2240 WINED3DPTEXTURECAPS_BORDER
|
2241 WINED3DPTEXTURECAPS_MIPMAP
|
2242 WINED3DPTEXTURECAPS_PROJECTED
|
2243 WINED3DPTEXTURECAPS_PERSPECTIVE
;
2245 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO
)) {
2246 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_POW2
|
2247 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL
;
2250 if( GL_SUPPORT(EXT_TEXTURE3D
)) {
2251 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_VOLUMEMAP
|
2252 WINED3DPTEXTURECAPS_MIPVOLUMEMAP
|
2253 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2
;
2256 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
2257 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_CUBEMAP
|
2258 WINED3DPTEXTURECAPS_MIPCUBEMAP
|
2259 WINED3DPTEXTURECAPS_CUBEMAP_POW2
;
2263 *pCaps
->TextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2264 WINED3DPTFILTERCAPS_MAGFPOINT
|
2265 WINED3DPTFILTERCAPS_MINFLINEAR
|
2266 WINED3DPTFILTERCAPS_MINFPOINT
|
2267 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2268 WINED3DPTFILTERCAPS_MIPFPOINT
|
2269 WINED3DPTFILTERCAPS_LINEAR
|
2270 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2271 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2272 WINED3DPTFILTERCAPS_MIPLINEAR
|
2273 WINED3DPTFILTERCAPS_MIPNEAREST
|
2274 WINED3DPTFILTERCAPS_NEAREST
;
2276 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
2277 *pCaps
->TextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
|
2278 WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
2281 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
2282 *pCaps
->CubeTextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2283 WINED3DPTFILTERCAPS_MAGFPOINT
|
2284 WINED3DPTFILTERCAPS_MINFLINEAR
|
2285 WINED3DPTFILTERCAPS_MINFPOINT
|
2286 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2287 WINED3DPTFILTERCAPS_MIPFPOINT
|
2288 WINED3DPTFILTERCAPS_LINEAR
|
2289 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2290 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2291 WINED3DPTFILTERCAPS_MIPLINEAR
|
2292 WINED3DPTFILTERCAPS_MIPNEAREST
|
2293 WINED3DPTFILTERCAPS_NEAREST
;
2295 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
2296 *pCaps
->CubeTextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
|
2297 WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
2300 *pCaps
->CubeTextureFilterCaps
= 0;
2302 if (GL_SUPPORT(EXT_TEXTURE3D
)) {
2303 *pCaps
->VolumeTextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2304 WINED3DPTFILTERCAPS_MAGFPOINT
|
2305 WINED3DPTFILTERCAPS_MINFLINEAR
|
2306 WINED3DPTFILTERCAPS_MINFPOINT
|
2307 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2308 WINED3DPTFILTERCAPS_MIPFPOINT
|
2309 WINED3DPTFILTERCAPS_LINEAR
|
2310 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2311 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2312 WINED3DPTFILTERCAPS_MIPLINEAR
|
2313 WINED3DPTFILTERCAPS_MIPNEAREST
|
2314 WINED3DPTFILTERCAPS_NEAREST
;
2316 *pCaps
->VolumeTextureFilterCaps
= 0;
2318 *pCaps
->TextureAddressCaps
= WINED3DPTADDRESSCAPS_INDEPENDENTUV
|
2319 WINED3DPTADDRESSCAPS_CLAMP
|
2320 WINED3DPTADDRESSCAPS_WRAP
;
2322 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
2323 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_BORDER
;
2325 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
2326 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRROR
;
2328 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
2329 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRRORONCE
;
2332 if (GL_SUPPORT(EXT_TEXTURE3D
)) {
2333 *pCaps
->VolumeTextureAddressCaps
= WINED3DPTADDRESSCAPS_INDEPENDENTUV
|
2334 WINED3DPTADDRESSCAPS_CLAMP
|
2335 WINED3DPTADDRESSCAPS_WRAP
;
2336 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
2337 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_BORDER
;
2339 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
2340 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRROR
;
2342 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
2343 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRRORONCE
;
2346 *pCaps
->VolumeTextureAddressCaps
= 0;
2348 *pCaps
->LineCaps
= WINED3DLINECAPS_TEXTURE
|
2349 WINED3DLINECAPS_ZTEST
;
2351 WINED3DLINECAPS_BLEND
2352 WINED3DLINECAPS_ALPHACMP
2353 WINED3DLINECAPS_FOG */
2355 *pCaps
->MaxTextureWidth
= GL_LIMITS(texture_size
);
2356 *pCaps
->MaxTextureHeight
= GL_LIMITS(texture_size
);
2358 if(GL_SUPPORT(EXT_TEXTURE3D
))
2359 *pCaps
->MaxVolumeExtent
= GL_LIMITS(texture3d_size
);
2361 *pCaps
->MaxVolumeExtent
= 0;
2363 *pCaps
->MaxTextureRepeat
= 32768;
2364 *pCaps
->MaxTextureAspectRatio
= GL_LIMITS(texture_size
);
2365 *pCaps
->MaxVertexW
= 1.0;
2367 *pCaps
->GuardBandLeft
= 0;
2368 *pCaps
->GuardBandTop
= 0;
2369 *pCaps
->GuardBandRight
= 0;
2370 *pCaps
->GuardBandBottom
= 0;
2372 *pCaps
->ExtentsAdjust
= 0;
2374 *pCaps
->StencilCaps
= WINED3DSTENCILCAPS_DECRSAT
|
2375 WINED3DSTENCILCAPS_INCRSAT
|
2376 WINED3DSTENCILCAPS_INVERT
|
2377 WINED3DSTENCILCAPS_KEEP
|
2378 WINED3DSTENCILCAPS_REPLACE
|
2379 WINED3DSTENCILCAPS_ZERO
;
2380 if (GL_SUPPORT(EXT_STENCIL_WRAP
)) {
2381 *pCaps
->StencilCaps
|= WINED3DSTENCILCAPS_DECR
|
2382 WINED3DSTENCILCAPS_INCR
;
2384 if ( This
->dxVersion
> 8 &&
2385 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE
) ||
2386 GL_SUPPORT(ATI_SEPARATE_STENCIL
) ) ) {
2387 *pCaps
->StencilCaps
|= WINED3DSTENCILCAPS_TWOSIDED
;
2390 *pCaps
->FVFCaps
= WINED3DFVFCAPS_PSIZE
| 0x0008; /* 8 texture coords */
2392 *pCaps
->TextureOpCaps
= WINED3DTEXOPCAPS_ADD
|
2393 WINED3DTEXOPCAPS_ADDSIGNED
|
2394 WINED3DTEXOPCAPS_ADDSIGNED2X
|
2395 WINED3DTEXOPCAPS_MODULATE
|
2396 WINED3DTEXOPCAPS_MODULATE2X
|
2397 WINED3DTEXOPCAPS_MODULATE4X
|
2398 WINED3DTEXOPCAPS_SELECTARG1
|
2399 WINED3DTEXOPCAPS_SELECTARG2
|
2400 WINED3DTEXOPCAPS_DISABLE
;
2402 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE
) ||
2403 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE
) ||
2404 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
2405 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
|
2406 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
|
2407 WINED3DTEXOPCAPS_BLENDFACTORALPHA
|
2408 WINED3DTEXOPCAPS_BLENDCURRENTALPHA
|
2409 WINED3DTEXOPCAPS_LERP
|
2410 WINED3DTEXOPCAPS_SUBTRACT
;
2412 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3
) ||
2413 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
2414 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_ADDSMOOTH
|
2415 WINED3DTEXOPCAPS_MULTIPLYADD
|
2416 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
|
2417 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
|
2418 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM
;
2420 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3
))
2421 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_DOTPRODUCT3
;
2423 if (GL_SUPPORT(NV_REGISTER_COMBINERS
)) {
2424 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
|
2425 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
;
2428 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP
)) {
2429 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BUMPENVMAP
;
2430 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2
)) {
2431 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2432 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2433 * and 3D textures. It also allows us to keep the code simpler by having texture
2434 * shaders constantly enabled.
2436 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BUMPENVMAP
;
2437 /* TODO: Luminance bump map? */
2441 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2442 WINED3DTEXOPCAPS_PREMODULATE */
2445 *pCaps
->MaxTextureBlendStages
= GL_LIMITS(texture_stages
);
2446 *pCaps
->MaxSimultaneousTextures
= GL_LIMITS(textures
);
2447 *pCaps
->MaxUserClipPlanes
= GL_LIMITS(clipplanes
);
2448 *pCaps
->MaxActiveLights
= GL_LIMITS(lights
);
2450 *pCaps
->MaxVertexBlendMatrices
= GL_LIMITS(blends
);
2451 *pCaps
->MaxVertexBlendMatrixIndex
= 0;
2453 *pCaps
->MaxAnisotropy
= GL_LIMITS(anisotropy
);
2454 *pCaps
->MaxPointSize
= GL_LIMITS(pointsize
);
2457 *pCaps
->VertexProcessingCaps
= WINED3DVTXPCAPS_DIRECTIONALLIGHTS
|
2458 WINED3DVTXPCAPS_MATERIALSOURCE7
|
2459 WINED3DVTXPCAPS_POSITIONALLIGHTS
|
2460 WINED3DVTXPCAPS_LOCALVIEWER
|
2461 WINED3DVTXPCAPS_VERTEXFOG
|
2462 WINED3DVTXPCAPS_TEXGEN
;
2464 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2466 *pCaps
->MaxPrimitiveCount
= 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2467 *pCaps
->MaxVertexIndex
= 0xFFFFF;
2468 *pCaps
->MaxStreams
= MAX_STREAMS
;
2469 *pCaps
->MaxStreamStride
= 1024;
2471 if (vs_selected_mode
== SHADER_GLSL
) {
2472 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2473 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2474 * vs_nv_version which is based on NV_vertex_program.
2475 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2476 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2477 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2478 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2479 if((GLINFO_LOCATION
.vs_nv_version
== VS_VERSION_20
) || (GLINFO_LOCATION
.ps_arb_max_instructions
<= 512))
2480 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(2,0);
2482 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(3,0);
2483 TRACE_(d3d_caps
)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps
->VertexShaderVersion
>> 8) & 0xff, *pCaps
->VertexShaderVersion
& 0xff);
2484 } else if (vs_selected_mode
== SHADER_ARB
) {
2485 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(1,1);
2486 TRACE_(d3d_caps
)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2488 *pCaps
->VertexShaderVersion
= 0;
2489 TRACE_(d3d_caps
)("Vertex shader functionality not available\n");
2492 *pCaps
->MaxVertexShaderConst
= GL_LIMITS(vshader_constantsF
);
2494 if (ps_selected_mode
== SHADER_GLSL
) {
2495 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2496 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2497 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2498 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2499 * in max native instructions. Intel and others also offer the info in this extension but they
2500 * don't support GLSL (at least on Windows).
2502 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number
2503 * of instructions is 512 or less we have to do with ps2.0 hardware.
2504 * NOTE: ps3.0 hardware requires 512 or more instructions but ati and nvidia offer 'enough' (1024 vs 4096) on their most basic ps3.0 hardware.
2506 if((GLINFO_LOCATION
.ps_nv_version
== PS_VERSION_20
) || (GLINFO_LOCATION
.ps_arb_max_instructions
<= 512))
2507 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(2,0);
2509 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(3,0);
2510 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2511 * Direct3D minimum requirement.
2513 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2514 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2516 * The problem is that the refrast clamps temporary results in the shader to
2517 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2518 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2519 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2520 * offer a way to query this.
2522 *pCaps
->PixelShader1xMaxValue
= 8.0;
2523 TRACE_(d3d_caps
)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps
->PixelShaderVersion
>> 8) & 0xff, *pCaps
->PixelShaderVersion
& 0xff);
2524 } else if (ps_selected_mode
== SHADER_ARB
) {
2525 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(1,4);
2526 *pCaps
->PixelShader1xMaxValue
= 8.0;
2527 TRACE_(d3d_caps
)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2529 *pCaps
->PixelShaderVersion
= 0;
2530 *pCaps
->PixelShader1xMaxValue
= 0.0;
2531 TRACE_(d3d_caps
)("Pixel shader functionality not available\n");
2534 /* ------------------------------------------------
2535 The following fields apply to d3d9 only
2536 ------------------------------------------------ */
2537 if (This
->dxVersion
> 8) {
2538 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2539 *pCaps
->DevCaps2
= WINED3DDEVCAPS2_STREAMOFFSET
;
2540 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2541 *pCaps
->MaxNpatchTessellationLevel
= 0;
2542 *pCaps
->MasterAdapterOrdinal
= 0;
2543 *pCaps
->AdapterOrdinalInGroup
= 0;
2544 *pCaps
->NumberOfAdaptersInGroup
= 1;
2546 if(*pCaps
->VertexShaderVersion
>= WINED3DVS_VERSION(2,0)) {
2547 /* OpenGL supports all the formats below, perhaps not always
2548 * without conversion, but it supports them.
2549 * Further GLSL doesn't seem to have an official unsigned type so
2550 * don't advertise it yet as I'm not sure how we handle it.
2551 * We might need to add some clamping in the shader engine to
2553 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2554 *pCaps
->DeclTypes
= WINED3DDTCAPS_UBYTE4
|
2555 WINED3DDTCAPS_UBYTE4N
|
2556 WINED3DDTCAPS_SHORT2N
|
2557 WINED3DDTCAPS_SHORT4N
;
2558 if (GL_SUPPORT(NV_HALF_FLOAT
)) {
2559 *pCaps
->DeclTypes
|=
2560 WINED3DDTCAPS_FLOAT16_2
|
2561 WINED3DDTCAPS_FLOAT16_4
;
2564 *pCaps
->DeclTypes
= 0;
2566 *pCaps
->NumSimultaneousRTs
= GL_LIMITS(buffers
);
2569 *pCaps
->StretchRectFilterCaps
= WINED3DPTFILTERCAPS_MINFPOINT
|
2570 WINED3DPTFILTERCAPS_MAGFPOINT
|
2571 WINED3DPTFILTERCAPS_MINFLINEAR
|
2572 WINED3DPTFILTERCAPS_MAGFLINEAR
;
2573 *pCaps
->VertexTextureFilterCaps
= 0;
2575 if(*pCaps
->VertexShaderVersion
== WINED3DVS_VERSION(3,0)) {
2576 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2577 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2578 *pCaps
->VS20Caps
.Caps
= WINED3DVS20CAPS_PREDICATION
;
2579 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH
; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2580 *pCaps
->VS20Caps
.NumTemps
= max(32, GLINFO_LOCATION
.vs_arb_max_temps
);
2581 *pCaps
->VS20Caps
.StaticFlowControlDepth
= WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH
; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2583 *pCaps
->MaxVShaderInstructionsExecuted
= 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2584 *pCaps
->MaxVertexShader30InstructionSlots
= max(512, GLINFO_LOCATION
.vs_arb_max_instructions
);
2585 } else if(*pCaps
->VertexShaderVersion
== WINED3DVS_VERSION(2,0)) {
2586 *pCaps
->VS20Caps
.Caps
= 0;
2587 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH
;
2588 *pCaps
->VS20Caps
.NumTemps
= max(12, GLINFO_LOCATION
.vs_arb_max_temps
);
2589 *pCaps
->VS20Caps
.StaticFlowControlDepth
= 1;
2591 *pCaps
->MaxVShaderInstructionsExecuted
= 65535;
2592 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
2593 } else { /* VS 1.x */
2594 *pCaps
->VS20Caps
.Caps
= 0;
2595 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= 0;
2596 *pCaps
->VS20Caps
.NumTemps
= 0;
2597 *pCaps
->VS20Caps
.StaticFlowControlDepth
= 0;
2599 *pCaps
->MaxVShaderInstructionsExecuted
= 0;
2600 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
2603 if(*pCaps
->PixelShaderVersion
== WINED3DPS_VERSION(3,0)) {
2604 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2605 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2607 /* Caps is more or less undocumented on MSDN but it appears to be used for PS20Caps based on results from R9600/FX5900/Geforce6800 cards from Windows */
2608 *pCaps
->PS20Caps
.Caps
= WINED3DPS20CAPS_ARBITRARYSWIZZLE
|
2609 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS
|
2610 WINED3DPS20CAPS_PREDICATION
|
2611 WINED3DPS20CAPS_NODEPENDENTREADLIMIT
|
2612 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
;
2613 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH
; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2614 *pCaps
->PS20Caps
.NumTemps
= max(32, GLINFO_LOCATION
.ps_arb_max_temps
);
2615 *pCaps
->PS20Caps
.StaticFlowControlDepth
= WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH
; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2616 *pCaps
->PS20Caps
.NumInstructionSlots
= WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS
; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2618 *pCaps
->MaxPShaderInstructionsExecuted
= 65535;
2619 *pCaps
->MaxPixelShader30InstructionSlots
= max(WINED3DMIN30SHADERINSTRUCTIONS
, GLINFO_LOCATION
.ps_arb_max_instructions
);
2620 } else if(*pCaps
->PixelShaderVersion
== WINED3DPS_VERSION(2,0)) {
2621 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2622 *pCaps
->PS20Caps
.Caps
= 0;
2623 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2624 *pCaps
->PS20Caps
.NumTemps
= max(12, GLINFO_LOCATION
.ps_arb_max_temps
);
2625 *pCaps
->PS20Caps
.StaticFlowControlDepth
= WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH
; /* Minumum: 1 */
2626 *pCaps
->PS20Caps
.NumInstructionSlots
= WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS
; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2628 *pCaps
->MaxPShaderInstructionsExecuted
= 512; /* Minimum value, a GeforceFX uses 1024 */
2629 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
2630 } else { /* PS 1.x */
2631 *pCaps
->PS20Caps
.Caps
= 0;
2632 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= 0;
2633 *pCaps
->PS20Caps
.NumTemps
= 0;
2634 *pCaps
->PS20Caps
.StaticFlowControlDepth
= 0;
2635 *pCaps
->PS20Caps
.NumInstructionSlots
= 0;
2637 *pCaps
->MaxPShaderInstructionsExecuted
= 0;
2638 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
2645 static unsigned int glsl_program_key_hash(void *key
) {
2646 glsl_program_key_t
*k
= (glsl_program_key_t
*)key
;
2648 unsigned int hash
= k
->vshader
| k
->pshader
<< 16;
2649 hash
+= ~(hash
<< 15);
2650 hash
^= (hash
>> 10);
2651 hash
+= (hash
<< 3);
2652 hash
^= (hash
>> 6);
2653 hash
+= ~(hash
<< 11);
2654 hash
^= (hash
>> 16);
2659 static BOOL
glsl_program_key_compare(void *keya
, void *keyb
) {
2660 glsl_program_key_t
*ka
= (glsl_program_key_t
*)keya
;
2661 glsl_program_key_t
*kb
= (glsl_program_key_t
*)keyb
;
2663 return ka
->vshader
== kb
->vshader
&& ka
->pshader
== kb
->pshader
;
2666 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2667 and fields being inserted in the middle, a new structure is used in place */
2668 static HRESULT WINAPI
IWineD3DImpl_CreateDevice(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
, HWND hFocusWindow
,
2669 DWORD BehaviourFlags
, IWineD3DDevice
** ppReturnedDeviceInterface
,
2672 IWineD3DDeviceImpl
*object
= NULL
;
2673 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2677 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2678 * number and create a device without a 3D adapter for 2D only operation.
2680 if (IWineD3D_GetAdapterCount(iface
) && Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
2681 return WINED3DERR_INVALIDCALL
;
2684 /* Create a WineD3DDevice object */
2685 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DDeviceImpl
));
2686 *ppReturnedDeviceInterface
= (IWineD3DDevice
*)object
;
2687 TRACE("Created WineD3DDevice object @ %p\n", object
);
2688 if (NULL
== object
) {
2689 return WINED3DERR_OUTOFVIDEOMEMORY
;
2692 /* Set up initial COM information */
2693 object
->lpVtbl
= &IWineD3DDevice_Vtbl
;
2695 object
->wineD3D
= iface
;
2696 object
->adapter
= numAdapters
? &Adapters
[Adapter
] : NULL
;
2697 IWineD3D_AddRef(object
->wineD3D
);
2698 object
->parent
= parent
;
2699 list_init(&object
->resources
);
2701 if(This
->dxVersion
== 7) {
2702 object
->surface_alignment
= 8;
2704 object
->surface_alignment
= 4;
2706 object
->posFixup
[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2708 /* Set the state up as invalid until the device is fully created */
2709 object
->state
= WINED3DERR_DRIVERINTERNALERROR
;
2711 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This
, Adapter
, DeviceType
,
2712 hFocusWindow
, BehaviourFlags
, ppReturnedDeviceInterface
);
2714 /* Save the creation parameters */
2715 object
->createParms
.AdapterOrdinal
= Adapter
;
2716 object
->createParms
.DeviceType
= DeviceType
;
2717 object
->createParms
.hFocusWindow
= hFocusWindow
;
2718 object
->createParms
.BehaviorFlags
= BehaviourFlags
;
2720 /* Initialize other useful values */
2721 object
->adapterNo
= Adapter
;
2722 object
->devType
= DeviceType
;
2724 select_shader_mode(&GLINFO_LOCATION
, DeviceType
, &object
->ps_selected_mode
, &object
->vs_selected_mode
);
2725 if (object
->ps_selected_mode
== SHADER_GLSL
|| object
->vs_selected_mode
== SHADER_GLSL
) {
2726 object
->shader_backend
= &glsl_shader_backend
;
2727 object
->glsl_program_lookup
= hash_table_create(&glsl_program_key_hash
, &glsl_program_key_compare
);
2728 } else if (object
->ps_selected_mode
== SHADER_ARB
|| object
->vs_selected_mode
== SHADER_ARB
) {
2729 object
->shader_backend
= &arb_program_shader_backend
;
2731 object
->shader_backend
= &none_shader_backend
;
2734 /* set the state of the device to valid */
2735 object
->state
= WINED3D_OK
;
2737 /* Get the initial screen setup for ddraw */
2738 object
->ddraw_width
= GetSystemMetrics(SM_CXSCREEN
);
2739 object
->ddraw_height
= GetSystemMetrics(SM_CYSCREEN
);
2741 object
->ddraw_format
= pixelformat_for_depth(GetDeviceCaps(hDC
, BITSPIXEL
) * GetDeviceCaps(hDC
, PLANES
));
2744 for(i
= 0; i
< PATCHMAP_SIZE
; i
++) {
2745 list_init(&object
->patches
[i
]);
2749 #undef GLINFO_LOCATION
2751 static HRESULT WINAPI
IWineD3DImpl_GetParent(IWineD3D
*iface
, IUnknown
**pParent
) {
2752 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2753 IUnknown_AddRef(This
->parent
);
2754 *pParent
= This
->parent
;
2758 ULONG WINAPI
D3DCB_DefaultDestroySurface(IWineD3DSurface
*pSurface
) {
2759 IUnknown
* surfaceParent
;
2760 TRACE("(%p) call back\n", pSurface
);
2762 /* Now, release the parent, which will take care of cleaning up the surface for us */
2763 IWineD3DSurface_GetParent(pSurface
, &surfaceParent
);
2764 IUnknown_Release(surfaceParent
);
2765 return IUnknown_Release(surfaceParent
);
2768 ULONG WINAPI
D3DCB_DefaultDestroyVolume(IWineD3DVolume
*pVolume
) {
2769 IUnknown
* volumeParent
;
2770 TRACE("(%p) call back\n", pVolume
);
2772 /* Now, release the parent, which will take care of cleaning up the volume for us */
2773 IWineD3DVolume_GetParent(pVolume
, &volumeParent
);
2774 IUnknown_Release(volumeParent
);
2775 return IUnknown_Release(volumeParent
);
2778 static BOOL
implementation_is_apple(WineD3D_GL_Info
*gl_info
) {
2779 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2780 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2781 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2783 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2784 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2785 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2786 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2787 * is specific to the MacOS window management, and GL_APPLE_ycbcr_422 is a Quicktime specific, so
2788 * it the chance that other implementations support it is rather rare since Win32 Quicktime uses
2789 * DirectDraw, not OpenGL.
2791 if(gl_info
->supported
[APPLE_FENCE
] &&
2792 gl_info
->supported
[APPLE_CLIENT_STORAGE
] &&
2793 gl_info
->supported
[APPLE_FLUSH_RENDER
] &&
2794 gl_info
->supported
[APPLE_YCBCR_422
]) {
2795 TRACE_(d3d_caps
)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2796 TRACE_(d3d_caps
)("Activating MacOS fixups\n");
2799 TRACE_(d3d_caps
)("Apple extensions are not supported\n");
2800 TRACE_(d3d_caps
)("Not activating MacOS fixups\n");
2805 static void fixup_extensions(WineD3D_GL_Info
*gl_info
) {
2806 if(implementation_is_apple(gl_info
)) {
2807 /* MacOS advertises more GLSL vertex shader uniforms than support on hardware, and if more are
2808 * used it falls back to software. While the compiler can detect if the shader uses all declared
2809 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2810 * using relative addressing falls back to software.
2812 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2814 if(gl_info
->vs_glsl_constantsF
<= gl_info
->vs_arb_constantsF
) {
2815 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2817 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2818 gl_info
->vs_glsl_constantsF
, gl_info
->vs_arb_constantsF
);
2819 gl_info
->vs_glsl_constantsF
= gl_info
->vs_arb_constantsF
;
2822 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2823 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2824 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2825 * flag for this extension
2827 if(gl_info
->supported
[ARB_TEXTURE_NON_POWER_OF_TWO
] && gl_info
->gl_vendor
== VENDOR_ATI
) {
2828 if(gl_info
->gl_card
== CARD_ATI_RADEON_X700
|| gl_info
->gl_card
== CARD_ATI_RADEON_X1600
||
2829 gl_info
->gl_card
== CARD_ATI_RADEON_9500
|| gl_info
->gl_card
== CARD_ATI_RADEON_8500
||
2830 gl_info
->gl_card
== CARD_ATI_RADEON_7200
|| gl_info
->gl_card
== CARD_ATI_RAGE_128PRO
) {
2831 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2832 gl_info
->supported
[ARB_TEXTURE_NON_POWER_OF_TWO
] = FALSE
;
2838 #define PUSH1(att) attribs[nAttribs++] = (att);
2839 #define GLINFO_LOCATION (Adapters[0].gl_info)
2840 BOOL
InitAdapters(void) {
2841 static HMODULE mod_gl
;
2843 int ps_selected_mode
, vs_selected_mode
;
2845 /* No need to hold any lock. The calling library makes sure only one thread calls
2846 * wined3d simultaneously
2848 if(numAdapters
> 0) return TRUE
;
2850 TRACE("Initializing adapters\n");
2853 #ifdef USE_WIN32_OPENGL
2854 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2855 mod_gl
= LoadLibraryA("opengl32.dll");
2857 ERR("Can't load opengl32.dll!\n");
2861 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2862 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2863 mod_gl
= GetModuleHandleA("opengl32.dll");
2867 /* Load WGL core functions from opengl32.dll */
2868 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2872 if(!pwglGetProcAddress
) {
2873 ERR("Unable to load wglGetProcAddress!\n");
2877 /* Dynamically load all GL core functions */
2881 /* For now only one default adapter */
2888 WineD3D_PixelFormat
*cfgs
;
2890 DISPLAY_DEVICEW DisplayDevice
;
2893 TRACE("Initializing default adapter\n");
2894 Adapters
[0].monitorPoint
.x
= -1;
2895 Adapters
[0].monitorPoint
.y
= -1;
2897 if (!WineD3D_CreateFakeGLContext()) {
2898 ERR("Failed to get a gl context for default adapter\n");
2899 HeapFree(GetProcessHeap(), 0, Adapters
);
2900 WineD3D_ReleaseFakeGLContext();
2904 ret
= IWineD3DImpl_FillGLCaps(&Adapters
[0].gl_info
);
2906 ERR("Failed to initialize gl caps for default adapter\n");
2907 HeapFree(GetProcessHeap(), 0, Adapters
);
2908 WineD3D_ReleaseFakeGLContext();
2911 ret
= initPixelFormats(&Adapters
[0].gl_info
);
2913 ERR("Failed to init gl formats\n");
2914 HeapFree(GetProcessHeap(), 0, Adapters
);
2915 WineD3D_ReleaseFakeGLContext();
2919 hdc
= pwglGetCurrentDC();
2921 ERR("Failed to get gl HDC\n");
2922 HeapFree(GetProcessHeap(), 0, Adapters
);
2923 WineD3D_ReleaseFakeGLContext();
2927 Adapters
[0].driver
= "Display";
2928 Adapters
[0].description
= "Direct3D HAL";
2930 /* Use the VideoRamSize registry setting when set */
2931 if(wined3d_settings
.emulated_textureram
)
2932 Adapters
[0].TextureRam
= wined3d_settings
.emulated_textureram
;
2934 Adapters
[0].TextureRam
= Adapters
[0].gl_info
.vidmem
;
2935 Adapters
[0].UsedTextureRam
= 0;
2936 TRACE("Emulating %dMB of texture ram\n", Adapters
[0].TextureRam
/(1024*1024));
2938 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2939 DisplayDevice
.cb
= sizeof(DisplayDevice
);
2940 EnumDisplayDevicesW(NULL
, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice
, 0);
2941 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice
.DeviceName
));
2942 strcpyW(Adapters
[0].DeviceName
, DisplayDevice
.DeviceName
);
2944 attribute
= WGL_NUMBER_PIXEL_FORMATS_ARB
;
2945 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc
, 0, 0, 1, &attribute
, &Adapters
[0].nCfgs
));
2947 Adapters
[0].cfgs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, Adapters
[0].nCfgs
*sizeof(WineD3D_PixelFormat
));
2948 cfgs
= Adapters
[0].cfgs
;
2949 PUSH1(WGL_RED_BITS_ARB
)
2950 PUSH1(WGL_GREEN_BITS_ARB
)
2951 PUSH1(WGL_BLUE_BITS_ARB
)
2952 PUSH1(WGL_ALPHA_BITS_ARB
)
2953 PUSH1(WGL_DEPTH_BITS_ARB
)
2954 PUSH1(WGL_STENCIL_BITS_ARB
)
2956 for(iPixelFormat
=1; iPixelFormat
<=Adapters
[0].nCfgs
; iPixelFormat
++) {
2957 res
= GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, 0, nAttribs
, attribs
, values
));
2962 /* Cache the pixel format */
2963 cfgs
->iPixelFormat
= iPixelFormat
;
2964 cfgs
->redSize
= values
[0];
2965 cfgs
->greenSize
= values
[1];
2966 cfgs
->blueSize
= values
[2];
2967 cfgs
->alphaSize
= values
[3];
2968 cfgs
->depthSize
= values
[4];
2969 cfgs
->stencilSize
= values
[5];
2971 TRACE("iPixelFormat=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d\n", cfgs
->iPixelFormat
, cfgs
->redSize
, cfgs
->greenSize
, cfgs
->blueSize
, cfgs
->alphaSize
, cfgs
->depthSize
, cfgs
->stencilSize
);
2974 WineD3D_ReleaseFakeGLContext();
2976 fixup_extensions(&Adapters
[0].gl_info
);
2978 select_shader_mode(&Adapters
[0].gl_info
, WINED3DDEVTYPE_HAL
, &ps_selected_mode
, &vs_selected_mode
);
2979 select_shader_max_constants(ps_selected_mode
, vs_selected_mode
, &Adapters
[0].gl_info
);
2983 TRACE("%d adapters successfully initialized\n", numAdapters
);
2988 #undef GLINFO_LOCATION
2990 /**********************************************************
2991 * IWineD3D VTbl follows
2992 **********************************************************/
2994 const IWineD3DVtbl IWineD3D_Vtbl
=
2997 IWineD3DImpl_QueryInterface
,
2998 IWineD3DImpl_AddRef
,
2999 IWineD3DImpl_Release
,
3001 IWineD3DImpl_GetParent
,
3002 IWineD3DImpl_GetAdapterCount
,
3003 IWineD3DImpl_RegisterSoftwareDevice
,
3004 IWineD3DImpl_GetAdapterMonitor
,
3005 IWineD3DImpl_GetAdapterModeCount
,
3006 IWineD3DImpl_EnumAdapterModes
,
3007 IWineD3DImpl_GetAdapterDisplayMode
,
3008 IWineD3DImpl_GetAdapterIdentifier
,
3009 IWineD3DImpl_CheckDeviceMultiSampleType
,
3010 IWineD3DImpl_CheckDepthStencilMatch
,
3011 IWineD3DImpl_CheckDeviceType
,
3012 IWineD3DImpl_CheckDeviceFormat
,
3013 IWineD3DImpl_CheckDeviceFormatConversion
,
3014 IWineD3DImpl_GetDeviceCaps
,
3015 IWineD3DImpl_CreateDevice