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
;
45 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE
},
46 {"GL_APPLE_fence", APPLE_FENCE
},
49 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL
},
50 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3
},
51 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE
},
52 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP
},
55 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS
},
56 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM
},
57 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER
},
58 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL
},
59 {"GL_ARB_imaging", ARB_IMAGING
},
60 {"GL_ARB_multisample", ARB_MULTISAMPLE
}, /* needs GLX_ARB_MULTISAMPLE as well */
61 {"GL_ARB_multitexture", ARB_MULTITEXTURE
},
62 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY
},
63 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT
},
64 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS
},
65 {"GL_ARB_point_sprite", ARB_POINT_SPRITE
},
66 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP
},
67 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION
},
68 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP
},
69 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD
},
70 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE
},
71 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3
},
72 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT
},
73 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT
},
74 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO
},
75 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND
},
76 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT
},
77 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM
},
78 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER
},
81 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX
},
82 {"GL_EXT_fog_coord", EXT_FOG_COORD
},
83 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT
},
84 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT
},
85 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE
},
86 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS
},
87 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR
},
88 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE
},
89 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP
},
90 {"GL_EXT_texture3D", EXT_TEXTURE3D
},
91 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC
},
92 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD
},
93 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE
},
94 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3
},
95 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB
},
96 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC
},
97 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD
},
98 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS
},
99 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER
},
100 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING
},
103 {"GL_NV_half_float", NV_HALF_FLOAT
},
104 {"GL_NV_fence", NV_FENCE
},
105 {"GL_NV_fog_distance", NV_FOG_DISTANCE
},
106 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM
},
107 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2
},
108 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS
},
109 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2
},
110 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION
},
111 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4
},
112 {"GL_NV_texture_shader", NV_TEXTURE_SHADER
},
113 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2
},
114 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3
},
115 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY
},
116 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM
},
117 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1
},
118 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2
},
119 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3
},
120 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP
},
123 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP
},
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
131 static int numAdapters
= 0;
132 static struct WineD3DAdapter Adapters
[1];
135 int minLookup
[MAX_LOOKUPS
];
136 int maxLookup
[MAX_LOOKUPS
];
137 DWORD
*stateLookup
[MAX_LOOKUPS
];
139 DWORD minMipLookup
[WINED3DTEXF_ANISOTROPIC
+ 1][WINED3DTEXF_LINEAR
+ 1];
143 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
144 * ie there is no GL Context - Get a default rendering context to enable the
145 * function query some info from GL
148 static int wined3d_fake_gl_context_ref
= 0;
149 static BOOL wined3d_fake_gl_context_foreign
;
150 static BOOL wined3d_fake_gl_context_available
= FALSE
;
151 static HDC wined3d_fake_gl_context_hdc
= NULL
;
152 static HWND wined3d_fake_gl_context_hwnd
= NULL
;
154 static CRITICAL_SECTION wined3d_fake_gl_context_cs
;
155 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug
=
157 0, 0, &wined3d_fake_gl_context_cs
,
158 { &wined3d_fake_gl_context_cs_debug
.ProcessLocksList
,
159 &wined3d_fake_gl_context_cs_debug
.ProcessLocksList
},
160 0, 0, { (DWORD_PTR
)(__FILE__
": wined3d_fake_gl_context_cs") }
162 static CRITICAL_SECTION wined3d_fake_gl_context_cs
= { &wined3d_fake_gl_context_cs_debug
, -1, 0, 0, 0, 0 };
164 static void WineD3D_ReleaseFakeGLContext(void) {
167 EnterCriticalSection(&wined3d_fake_gl_context_cs
);
169 if(!wined3d_fake_gl_context_available
) {
170 TRACE_(d3d_caps
)("context not available\n");
171 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
175 glCtx
= pwglGetCurrentContext();
177 TRACE_(d3d_caps
)("decrementing ref from %i\n", wined3d_fake_gl_context_ref
);
178 if (0 == (--wined3d_fake_gl_context_ref
) ) {
179 if(!wined3d_fake_gl_context_foreign
&& glCtx
) {
180 TRACE_(d3d_caps
)("destroying fake GL context\n");
181 pwglMakeCurrent(NULL
, NULL
);
182 pwglDeleteContext(glCtx
);
184 if(wined3d_fake_gl_context_hdc
)
185 ReleaseDC(wined3d_fake_gl_context_hwnd
, wined3d_fake_gl_context_hdc
);
186 wined3d_fake_gl_context_hdc
= NULL
; /* Make sure we don't think that it is still around */
187 if(wined3d_fake_gl_context_hwnd
)
188 DestroyWindow(wined3d_fake_gl_context_hwnd
);
189 wined3d_fake_gl_context_hwnd
= NULL
;
190 wined3d_fake_gl_context_available
= FALSE
;
192 assert(wined3d_fake_gl_context_ref
>= 0);
194 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
198 static BOOL
WineD3D_CreateFakeGLContext(void) {
202 EnterCriticalSection(&wined3d_fake_gl_context_cs
);
204 TRACE("getting context...\n");
205 if(wined3d_fake_gl_context_ref
> 0) goto ret
;
206 assert(0 == wined3d_fake_gl_context_ref
);
208 wined3d_fake_gl_context_foreign
= TRUE
;
210 glCtx
= pwglGetCurrentContext();
212 PIXELFORMATDESCRIPTOR pfd
;
215 wined3d_fake_gl_context_foreign
= FALSE
;
217 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
218 wined3d_fake_gl_context_hwnd
= CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW
, 10, 10, 10, 10, NULL
, NULL
, NULL
, NULL
);
219 if(!wined3d_fake_gl_context_hwnd
) {
220 ERR("HWND creation failed!\n");
223 wined3d_fake_gl_context_hdc
= GetDC(wined3d_fake_gl_context_hwnd
);
224 if(!wined3d_fake_gl_context_hdc
) {
225 ERR("GetDC failed!\n");
229 /* PixelFormat selection */
230 ZeroMemory(&pfd
, sizeof(pfd
));
231 pfd
.nSize
= sizeof(pfd
);
233 pfd
.dwFlags
= PFD_SUPPORT_OPENGL
| PFD_DOUBLEBUFFER
| PFD_DRAW_TO_WINDOW
;/*PFD_GENERIC_ACCELERATED*/
234 pfd
.iPixelType
= PFD_TYPE_RGBA
;
236 pfd
.iLayerType
= PFD_MAIN_PLANE
;
238 iPixelFormat
= ChoosePixelFormat(wined3d_fake_gl_context_hdc
, &pfd
);
240 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
241 ERR("Can't find a suitable iPixelFormat\n");
244 DescribePixelFormat(wined3d_fake_gl_context_hdc
, iPixelFormat
, sizeof(pfd
), &pfd
);
245 SetPixelFormat(wined3d_fake_gl_context_hdc
, iPixelFormat
, &pfd
);
247 /* Create a GL context */
248 glCtx
= pwglCreateContext(wined3d_fake_gl_context_hdc
);
250 WARN_(d3d_caps
)("Error creating default context for capabilities initialization\n");
254 /* Make it the current GL context */
255 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc
, glCtx
)) {
256 WARN_(d3d_caps
)("Error setting default context as current for capabilities initialization\n");
262 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref
);
263 wined3d_fake_gl_context_ref
++;
264 wined3d_fake_gl_context_available
= TRUE
;
265 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
268 if(wined3d_fake_gl_context_hdc
)
269 ReleaseDC(wined3d_fake_gl_context_hwnd
, wined3d_fake_gl_context_hdc
);
270 wined3d_fake_gl_context_hdc
= NULL
;
271 if(wined3d_fake_gl_context_hwnd
)
272 DestroyWindow(wined3d_fake_gl_context_hwnd
);
273 wined3d_fake_gl_context_hwnd
= NULL
;
274 if(glCtx
) pwglDeleteContext(glCtx
);
275 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
281 /**********************************************************
282 * IUnknown parts follows
283 **********************************************************/
285 static HRESULT WINAPI
IWineD3DImpl_QueryInterface(IWineD3D
*iface
,REFIID riid
,LPVOID
*ppobj
)
287 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
289 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
290 if (IsEqualGUID(riid
, &IID_IUnknown
)
291 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
292 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
293 IUnknown_AddRef(iface
);
298 return E_NOINTERFACE
;
301 static ULONG WINAPI
IWineD3DImpl_AddRef(IWineD3D
*iface
) {
302 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
303 ULONG refCount
= InterlockedIncrement(&This
->ref
);
305 TRACE("(%p) : AddRef increasing from %d\n", This
, refCount
- 1);
309 static ULONG WINAPI
IWineD3DImpl_Release(IWineD3D
*iface
) {
310 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
312 TRACE("(%p) : Releasing from %d\n", This
, This
->ref
);
313 ref
= InterlockedDecrement(&This
->ref
);
315 HeapFree(GetProcessHeap(), 0, This
);
321 /* Set the shader type for this device, depending on the given capabilities,
322 * the device type, and the user preferences in wined3d_settings */
324 static void select_shader_mode(
325 WineD3D_GL_Info
*gl_info
,
326 WINED3DDEVTYPE DeviceType
,
330 if (wined3d_settings
.vs_mode
== VS_NONE
) {
331 *vs_selected
= SHADER_NONE
;
332 } else if (gl_info
->supported
[ARB_VERTEX_SHADER
] && wined3d_settings
.glslRequested
) {
333 *vs_selected
= SHADER_GLSL
;
334 } else if (gl_info
->supported
[ARB_VERTEX_PROGRAM
]) {
335 *vs_selected
= SHADER_ARB
;
337 *vs_selected
= SHADER_NONE
;
340 if (wined3d_settings
.ps_mode
== PS_NONE
) {
341 *ps_selected
= SHADER_NONE
;
342 } else if (gl_info
->supported
[ARB_FRAGMENT_SHADER
] && wined3d_settings
.glslRequested
) {
343 *ps_selected
= SHADER_GLSL
;
344 } else if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
]) {
345 *ps_selected
= SHADER_ARB
;
347 *ps_selected
= SHADER_NONE
;
351 /** Select the number of report maximum shader constants based on the selected shader modes */
352 static void select_shader_max_constants(
353 int ps_selected_mode
,
354 int vs_selected_mode
,
355 WineD3D_GL_Info
*gl_info
) {
357 switch (vs_selected_mode
) {
359 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
360 gl_info
->max_vshader_constantsF
= gl_info
->vs_glsl_constantsF
- (MAX_CONST_B
/ 4) - MAX_CONST_I
- 1;
363 /* We have to subtract any other PARAMs that we might use in our shader programs.
364 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
365 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
366 gl_info
->max_vshader_constantsF
= gl_info
->vs_arb_constantsF
- 3;
369 gl_info
->max_vshader_constantsF
= 0;
373 switch (ps_selected_mode
) {
375 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
376 * In theory the texbem instruction may need one more shader constant too. But lets assume
377 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
378 * and lets not take away a uniform needlessly from all other shaders.
380 gl_info
->max_pshader_constantsF
= gl_info
->ps_glsl_constantsF
- (MAX_CONST_B
/ 4) - MAX_CONST_I
- 2;
383 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
384 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
386 gl_info
->max_pshader_constantsF
= gl_info
->ps_arb_constantsF
- 2;
389 gl_info
->max_pshader_constantsF
= 0;
394 /**********************************************************
395 * IWineD3D parts follows
396 **********************************************************/
398 #define GLINFO_LOCATION (*gl_info)
399 BOOL
IWineD3DImpl_FillGLCaps(WineD3D_GL_Info
*gl_info
) {
400 const char *GL_Extensions
= NULL
;
401 const char *WGL_Extensions
= NULL
;
402 const char *gl_string
= NULL
;
403 const char *gl_string_cursor
= NULL
;
405 GLfloat gl_floatv
[2];
406 int major
= 1, minor
= 0;
407 BOOL return_value
= TRUE
;
411 TRACE_(d3d_caps
)("(%p)\n", gl_info
);
413 gl_string
= (const char *) glGetString(GL_RENDERER
);
414 if (NULL
== gl_string
)
416 strcpy(gl_info
->gl_renderer
, gl_string
);
418 gl_string
= (const char *) glGetString(GL_VENDOR
);
419 TRACE_(d3d_caps
)("Filling vendor string %s\n", gl_string
);
420 if (gl_string
!= NULL
) {
421 /* Fill in the GL vendor */
422 if (strstr(gl_string
, "NVIDIA")) {
423 gl_info
->gl_vendor
= VENDOR_NVIDIA
;
424 } else if (strstr(gl_string
, "ATI")) {
425 gl_info
->gl_vendor
= VENDOR_ATI
;
426 } else if (strstr(gl_string
, "Intel(R)") ||
427 strstr(gl_info
->gl_renderer
, "Intel(R)")) {
428 gl_info
->gl_vendor
= VENDOR_INTEL
;
429 } else if (strstr(gl_string
, "Mesa")) {
430 gl_info
->gl_vendor
= VENDOR_MESA
;
432 gl_info
->gl_vendor
= VENDOR_WINE
;
435 gl_info
->gl_vendor
= VENDOR_WINE
;
439 TRACE_(d3d_caps
)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string
), gl_info
->gl_vendor
);
441 /* Parse the GL_VERSION field into major and minor information */
442 gl_string
= (const char *) glGetString(GL_VERSION
);
443 if (gl_string
!= NULL
) {
445 switch (gl_info
->gl_vendor
) {
447 gl_string_cursor
= strstr(gl_string
, "NVIDIA");
448 if (!gl_string_cursor
) {
449 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
453 gl_string_cursor
= strstr(gl_string_cursor
, " ");
454 if (!gl_string_cursor
) {
455 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
459 while (*gl_string_cursor
== ' ') {
463 if (!*gl_string_cursor
) {
464 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
468 major
= atoi(gl_string_cursor
);
469 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
473 if (*gl_string_cursor
++ != '.') {
474 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
478 minor
= atoi(gl_string_cursor
);
479 minor
= major
*100+minor
;
486 gl_string_cursor
= strchr(gl_string
, '-');
487 if (gl_string_cursor
) {
491 /* Check if version number is of the form x.y.z */
492 if (*gl_string_cursor
> '9' && *gl_string_cursor
< '0')
494 if (!error
&& *(gl_string_cursor
+2) > '9' && *(gl_string_cursor
+2) < '0')
496 if (!error
&& *(gl_string_cursor
+4) > '9' && *(gl_string_cursor
+4) < '0')
498 if (!error
&& *(gl_string_cursor
+1) != '.' && *(gl_string_cursor
+3) != '.')
501 /* Mark version number as malformed */
503 gl_string_cursor
= 0;
506 if (!gl_string_cursor
)
507 WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
509 major
= *gl_string_cursor
- '0';
510 minor
= (*(gl_string_cursor
+2) - '0') * 256 + (*(gl_string_cursor
+4) - '0');
516 gl_string_cursor
= strstr(gl_string
, "Mesa");
517 gl_string_cursor
= strstr(gl_string_cursor
, " ");
518 while (*gl_string_cursor
&& ' ' == *gl_string_cursor
) ++gl_string_cursor
;
519 if (*gl_string_cursor
) {
523 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
524 tmp
[cursor
++] = *gl_string_cursor
;
530 if (*gl_string_cursor
!= '.') WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
534 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
535 tmp
[cursor
++] = *gl_string_cursor
;
547 gl_info
->gl_driver_version
= MAKEDWORD_VERSION(major
, minor
);
548 TRACE_(d3d_caps
)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string
), major
, minor
, gl_info
->gl_driver_version
);
551 TRACE_(d3d_caps
)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info
->gl_renderer
), gl_info
->gl_card
);
554 * Initialize openGL extension related variables
555 * with Default values
557 memset(&gl_info
->supported
, 0, sizeof(gl_info
->supported
));
558 gl_info
->max_buffers
= 1;
559 gl_info
->max_textures
= 1;
560 gl_info
->max_texture_stages
= 1;
561 gl_info
->max_fragment_samplers
= 1;
562 gl_info
->max_vertex_samplers
= 0;
563 gl_info
->max_combined_samplers
= 0;
564 gl_info
->max_sampler_stages
= 1;
565 gl_info
->ps_arb_version
= PS_VERSION_NOT_SUPPORTED
;
566 gl_info
->ps_arb_max_temps
= 0;
567 gl_info
->ps_arb_max_instructions
= 0;
568 gl_info
->vs_arb_version
= VS_VERSION_NOT_SUPPORTED
;
569 gl_info
->vs_arb_max_temps
= 0;
570 gl_info
->vs_arb_max_instructions
= 0;
571 gl_info
->vs_nv_version
= VS_VERSION_NOT_SUPPORTED
;
572 gl_info
->vs_ati_version
= VS_VERSION_NOT_SUPPORTED
;
573 gl_info
->vs_glsl_constantsF
= 0;
574 gl_info
->ps_glsl_constantsF
= 0;
575 gl_info
->vs_arb_constantsF
= 0;
576 gl_info
->ps_arb_constantsF
= 0;
578 /* Now work out what GL support this card really has */
579 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
584 /* Retrieve opengl defaults */
585 glGetIntegerv(GL_MAX_CLIP_PLANES
, &gl_max
);
586 gl_info
->max_clipplanes
= min(WINED3DMAXUSERCLIPPLANES
, gl_max
);
587 TRACE_(d3d_caps
)("ClipPlanes support - num Planes=%d\n", gl_max
);
589 glGetIntegerv(GL_MAX_LIGHTS
, &gl_max
);
590 gl_info
->max_lights
= gl_max
;
591 TRACE_(d3d_caps
)("Lights support - max lights=%d\n", gl_max
);
593 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &gl_max
);
594 gl_info
->max_texture_size
= gl_max
;
595 TRACE_(d3d_caps
)("Maximum texture size support - max texture size=%d\n", gl_max
);
597 glGetFloatv(GL_POINT_SIZE_RANGE
, gl_floatv
);
598 gl_info
->max_pointsize
= gl_floatv
[1];
599 TRACE_(d3d_caps
)("Maximum point size support - max point size=%f\n", gl_floatv
[1]);
601 glGetIntegerv(GL_AUX_BUFFERS
, &gl_max
);
602 gl_info
->max_aux_buffers
= gl_max
;
603 TRACE_(d3d_caps
)("Offscreen rendering support - number of aux buffers=%d\n", gl_max
);
605 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
606 GL_Extensions
= (const char *) glGetString(GL_EXTENSIONS
);
607 TRACE_(d3d_caps
)("GL_Extensions reported:\n");
609 if (NULL
== GL_Extensions
) {
610 ERR(" GL_Extensions returns NULL\n");
612 while (*GL_Extensions
!= 0x00) {
617 while (isspace(*GL_Extensions
)) GL_Extensions
++;
618 Start
= GL_Extensions
;
619 while (!isspace(*GL_Extensions
) && *GL_Extensions
!= 0x00) {
623 len
= GL_Extensions
- Start
;
624 if (len
== 0 || len
>= sizeof(ThisExtn
))
627 memcpy(ThisExtn
, Start
, len
);
628 ThisExtn
[len
] = '\0';
629 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
631 for (i
= 0; i
< (sizeof(EXTENSION_MAP
) / sizeof(*EXTENSION_MAP
)); ++i
) {
632 if (!strcmp(ThisExtn
, EXTENSION_MAP
[i
].extension_string
)) {
633 TRACE_(d3d_caps
)(" FOUND: %s support\n", EXTENSION_MAP
[i
].extension_string
);
634 gl_info
->supported
[EXTENSION_MAP
[i
].extension
] = TRUE
;
640 if (gl_info
->supported
[APPLE_FENCE
]) {
641 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
642 * The apple extension interacts with some other apple exts. Disable the NV
643 * extension if the apple one is support to prevent confusion in other parts
646 gl_info
->supported
[NV_FENCE
] = FALSE
;
648 if (gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
]) {
649 TRACE_(d3d_caps
)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
650 gl_info
->supported
[NV_TEXGEN_REFLECTION
] = TRUE
;
652 if (gl_info
->supported
[NV_TEXTURE_SHADER2
]) {
653 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
654 * Won't occur in any real world situation though
656 gl_info
->supported
[ATI_ENVMAP_BUMPMAP
] = FALSE
;
658 if (gl_info
->supported
[ARB_DRAW_BUFFERS
]) {
659 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB
, &gl_max
);
660 gl_info
->max_buffers
= gl_max
;
661 TRACE_(d3d_caps
)("Max draw buffers: %u\n", gl_max
);
663 if (gl_info
->supported
[ARB_MULTITEXTURE
]) {
664 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB
, &gl_max
);
665 gl_info
->max_textures
= min(MAX_TEXTURES
, gl_max
);
666 TRACE_(d3d_caps
)("Max textures: %d\n", gl_info
->max_textures
);
668 if (gl_info
->supported
[NV_REGISTER_COMBINERS
]) {
670 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV
, &tmp
);
671 gl_info
->max_texture_stages
= min(MAX_TEXTURES
, tmp
);
673 gl_info
->max_texture_stages
= min(MAX_TEXTURES
, gl_max
);
675 TRACE_(d3d_caps
)("Max texture stages: %d\n", gl_info
->max_texture_stages
);
677 if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
]) {
679 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB
, &tmp
);
680 gl_info
->max_fragment_samplers
= min(MAX_FRAGMENT_SAMPLERS
, tmp
);
682 gl_info
->max_fragment_samplers
= max(gl_info
->max_fragment_samplers
, gl_max
);
684 TRACE_(d3d_caps
)("Max fragment samplers: %d\n", gl_info
->max_fragment_samplers
);
686 if (gl_info
->supported
[ARB_VERTEX_SHADER
]) {
688 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB
, &tmp
);
689 gl_info
->max_vertex_samplers
= tmp
;
690 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB
, &tmp
);
691 gl_info
->max_combined_samplers
= tmp
;
693 gl_info
->max_combined_samplers
= gl_info
->max_fragment_samplers
;
695 TRACE_(d3d_caps
)("Max vertex samplers: %u\n", gl_info
->max_vertex_samplers
);
696 TRACE_(d3d_caps
)("Max combined samplers: %u\n", gl_info
->max_combined_samplers
);
698 if (gl_info
->supported
[ARB_VERTEX_BLEND
]) {
699 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB
, &gl_max
);
700 gl_info
->max_blends
= gl_max
;
701 TRACE_(d3d_caps
)("Max blends: %u\n", gl_info
->max_blends
);
703 if (gl_info
->supported
[EXT_TEXTURE3D
]) {
704 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT
, &gl_max
);
705 gl_info
->max_texture3d_size
= gl_max
;
706 TRACE_(d3d_caps
)("Max texture3D size: %d\n", gl_info
->max_texture3d_size
);
708 if (gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
]) {
709 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
, &gl_max
);
710 gl_info
->max_anisotropy
= gl_max
;
711 TRACE_(d3d_caps
)("Max anisotropy: %d\n", gl_info
->max_anisotropy
);
713 if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
]) {
714 gl_info
->ps_arb_version
= PS_VERSION_11
;
715 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
, &gl_max
));
716 gl_info
->ps_arb_constantsF
= gl_max
;
717 TRACE_(d3d_caps
)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info
->ps_arb_constantsF
);
718 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_TEMPORARIES_ARB
, &gl_max
));
719 gl_info
->ps_arb_max_temps
= gl_max
;
720 TRACE_(d3d_caps
)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info
->ps_arb_max_temps
);
721 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_INSTRUCTIONS_ARB
, &gl_max
));
722 gl_info
->ps_arb_max_instructions
= gl_max
;
723 TRACE_(d3d_caps
)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info
->ps_arb_max_instructions
);
725 if (gl_info
->supported
[ARB_VERTEX_PROGRAM
]) {
726 gl_info
->vs_arb_version
= VS_VERSION_11
;
727 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
, &gl_max
));
728 gl_info
->vs_arb_constantsF
= gl_max
;
729 TRACE_(d3d_caps
)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info
->vs_arb_constantsF
);
730 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_TEMPORARIES_ARB
, &gl_max
));
731 gl_info
->vs_arb_max_temps
= gl_max
;
732 TRACE_(d3d_caps
)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info
->vs_arb_max_temps
);
733 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_INSTRUCTIONS_ARB
, &gl_max
));
734 gl_info
->vs_arb_max_instructions
= gl_max
;
735 TRACE_(d3d_caps
)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info
->vs_arb_max_instructions
);
737 if (gl_info
->supported
[ARB_VERTEX_SHADER
]) {
738 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB
, &gl_max
);
739 gl_info
->vs_glsl_constantsF
= gl_max
/ 4;
740 TRACE_(d3d_caps
)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info
->vs_glsl_constantsF
);
742 if (gl_info
->supported
[ARB_FRAGMENT_SHADER
]) {
743 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB
, &gl_max
);
744 gl_info
->ps_glsl_constantsF
= gl_max
/ 4;
745 TRACE_(d3d_caps
)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info
->ps_glsl_constantsF
);
747 if (gl_info
->supported
[EXT_VERTEX_SHADER
]) {
748 gl_info
->vs_ati_version
= VS_VERSION_11
;
750 if (gl_info
->supported
[NV_VERTEX_PROGRAM3
]) {
751 gl_info
->vs_nv_version
= VS_VERSION_30
;
752 } else if (gl_info
->supported
[NV_VERTEX_PROGRAM2
]) {
753 gl_info
->vs_nv_version
= VS_VERSION_20
;
754 } else if (gl_info
->supported
[NV_VERTEX_PROGRAM1_1
]) {
755 gl_info
->vs_nv_version
= VS_VERSION_11
;
756 } else if (gl_info
->supported
[NV_VERTEX_PROGRAM
]) {
757 gl_info
->vs_nv_version
= VS_VERSION_10
;
759 if (gl_info
->supported
[NV_FRAGMENT_PROGRAM2
]) {
760 gl_info
->ps_nv_version
= PS_VERSION_30
;
761 } else if (gl_info
->supported
[NV_FRAGMENT_PROGRAM
]) {
762 gl_info
->ps_nv_version
= PS_VERSION_20
;
766 checkGLcall("extension detection\n");
768 /* In some cases the number of texture stages can be larger than the number
769 * of samplers. The GF4 for example can use only 2 samplers (no fragment
770 * shaders), but 8 texture stages (register combiners). */
771 gl_info
->max_sampler_stages
= max(gl_info
->max_fragment_samplers
, gl_info
->max_texture_stages
);
773 /* We can only use ORM_FBO when the hardware supports it. */
774 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
&& !gl_info
->supported
[EXT_FRAMEBUFFER_OBJECT
]) {
775 WARN_(d3d_caps
)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
776 wined3d_settings
.offscreen_rendering_mode
= ORM_PBUFFER
;
779 /* MRTs are currently only supported when FBOs are used. */
780 if (wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
) {
781 gl_info
->max_buffers
= 1;
784 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
785 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
786 * in case of the latest videocards in the number of pixel/vertex pipelines.
788 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
789 * rendering. Various games use this information to get a rough estimation of the features of the card
790 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
791 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
792 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
795 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
796 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
797 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
798 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
799 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
800 * is used for rendering which is not always the case). This would work but it is not very portable. Second
801 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
804 * As said most games only use the PCI id to get an indication of the capabilities of the card.
805 * It doesn't really matter if the given id is the correct one if we return the id of a card with
806 * similar 3d features.
808 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
809 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
810 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
811 * won't pass we return a default card. This way is better than maintaining a full card database as even
812 * without a full database we can return a card with similar features. Second the size of the database
813 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
814 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
815 * to distinguishes between different models from that family.
817 switch (gl_info
->gl_vendor
) {
819 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
820 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
822 if(WINE_D3D9_CAPABLE(gl_info
) && (gl_info
->vs_nv_version
== VS_VERSION_30
)) {
823 if (strstr(gl_info
->gl_renderer
, "8800"))
824 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_8800GTS
;
825 else if(strstr(gl_info
->gl_renderer
, "8600") ||
826 strstr(gl_info
->gl_renderer
, "8700"))
827 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_8600GT
;
828 else if(strstr(gl_info
->gl_renderer
, "8300") ||
829 strstr(gl_info
->gl_renderer
, "8400") ||
830 strstr(gl_info
->gl_renderer
, "8500"))
831 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_8300GS
;
832 else if(strstr(gl_info
->gl_renderer
, "7800") ||
833 strstr(gl_info
->gl_renderer
, "7900") ||
834 strstr(gl_info
->gl_renderer
, "7950") ||
835 strstr(gl_info
->gl_renderer
, "Quadro FX 4") ||
836 strstr(gl_info
->gl_renderer
, "Quadro FX 5"))
837 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_7800GT
;
838 else if(strstr(gl_info
->gl_renderer
, "6800") ||
839 strstr(gl_info
->gl_renderer
, "7600") ||
840 strstr(gl_info
->gl_renderer
, "7700"))
841 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6800
;
842 else if(strstr(gl_info
->gl_renderer
, "6600") ||
843 strstr(gl_info
->gl_renderer
, "6610") ||
844 strstr(gl_info
->gl_renderer
, "6700"))
845 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6600GT
;
847 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6200
; /* Geforce 6100/6150/6200/7300/7400/7500 */
848 } else if(WINE_D3D9_CAPABLE(gl_info
)) {
849 if (strstr(gl_info
->gl_renderer
, "5800") ||
850 strstr(gl_info
->gl_renderer
, "5900") ||
851 strstr(gl_info
->gl_renderer
, "5950") ||
852 strstr(gl_info
->gl_renderer
, "Quadro FX"))
853 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5800
;
854 else if(strstr(gl_info
->gl_renderer
, "5600") ||
855 strstr(gl_info
->gl_renderer
, "5650") ||
856 strstr(gl_info
->gl_renderer
, "5700") ||
857 strstr(gl_info
->gl_renderer
, "5750"))
858 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5600
;
860 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5200
; /* GeforceFX 5100/5200/5250/5300/5500 */
861 } else if(WINE_D3D8_CAPABLE(gl_info
)) {
862 if (strstr(gl_info
->gl_renderer
, "GeForce4 Ti") || strstr(gl_info
->gl_renderer
, "Quadro4"))
863 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_TI4200
; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
865 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE3
; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
866 } else if(WINE_D3D7_CAPABLE(gl_info
)) {
867 if (strstr(gl_info
->gl_renderer
, "GeForce4 MX"))
868 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_MX
; /* MX420/MX440/MX460/MX4000 */
869 else if(strstr(gl_info
->gl_renderer
, "GeForce2 MX") || strstr(gl_info
->gl_renderer
, "Quadro2 MXR"))
870 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE2_MX
; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
871 else if(strstr(gl_info
->gl_renderer
, "GeForce2") || strstr(gl_info
->gl_renderer
, "Quadro2"))
872 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE2
; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
874 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE
; /* Geforce 256/DDR, Quadro */
876 if (strstr(gl_info
->gl_renderer
, "TNT2"))
877 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT2
; /* Riva TNT2 standard/M64/Pro/Ultra */
879 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT
; /* Riva TNT, Vanta */
883 if(WINE_D3D9_CAPABLE(gl_info
)) {
884 /* Radeon R6xx HD2900 - highend */
885 if (strstr(gl_info
->gl_renderer
, "HD 2900"))
886 gl_info
->gl_card
= CARD_ATI_RADEON_HD2900
;
887 /* Radeon R6xx HD2600- midend */
888 else if (strstr(gl_info
->gl_renderer
, "HD 2600"))
889 gl_info
->gl_card
= CARD_ATI_RADEON_HD2600
;
890 /* Radeon R6xx HD2300/HD2400 - lowend */
891 else if (strstr(gl_info
->gl_renderer
, "HD 2300") ||
892 strstr(gl_info
->gl_renderer
, "HD 2400"))
893 gl_info
->gl_card
= CARD_ATI_RADEON_HD2300
;
895 else if (strstr(gl_info
->gl_renderer
, "X1600") ||
896 strstr(gl_info
->gl_renderer
, "X1650") ||
897 strstr(gl_info
->gl_renderer
, "X1800") ||
898 strstr(gl_info
->gl_renderer
, "X1900") ||
899 strstr(gl_info
->gl_renderer
, "X1950"))
900 gl_info
->gl_card
= CARD_ATI_RADEON_X1600
;
901 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
902 else if(strstr(gl_info
->gl_renderer
, "X700") ||
903 strstr(gl_info
->gl_renderer
, "X800") ||
904 strstr(gl_info
->gl_renderer
, "X850") ||
905 strstr(gl_info
->gl_renderer
, "X1300") ||
906 strstr(gl_info
->gl_renderer
, "X1400") ||
907 strstr(gl_info
->gl_renderer
, "X1450") ||
908 strstr(gl_info
->gl_renderer
, "X1550"))
909 gl_info
->gl_card
= CARD_ATI_RADEON_X700
;
912 gl_info
->gl_card
= CARD_ATI_RADEON_9500
; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
913 } else if(WINE_D3D8_CAPABLE(gl_info
)) {
914 gl_info
->gl_card
= CARD_ATI_RADEON_8500
; /* Radeon 8500/9000/9100/9200/9300 */
915 } else if(WINE_D3D7_CAPABLE(gl_info
)) {
916 gl_info
->gl_card
= CARD_ATI_RADEON_7200
; /* Radeon 7000/7100/7200/7500 */
918 gl_info
->gl_card
= CARD_ATI_RAGE_128PRO
;
921 if (strstr(gl_info
->gl_renderer
, "915GM")) {
922 gl_info
->gl_card
= CARD_INTEL_I915GM
;
923 } else if (strstr(gl_info
->gl_renderer
, "915G")) {
924 gl_info
->gl_card
= CARD_INTEL_I915G
;
925 } else if (strstr(gl_info
->gl_renderer
, "865G")) {
926 gl_info
->gl_card
= CARD_INTEL_I865G
;
927 } else if (strstr(gl_info
->gl_renderer
, "855G")) {
928 gl_info
->gl_card
= CARD_INTEL_I855G
;
929 } else if (strstr(gl_info
->gl_renderer
, "830G")) {
930 gl_info
->gl_card
= CARD_INTEL_I830G
;
932 gl_info
->gl_card
= CARD_INTEL_I915G
;
938 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
939 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
940 * them a good generic choice.
942 gl_info
->gl_vendor
= VENDOR_NVIDIA
;
943 if(WINE_D3D9_CAPABLE(gl_info
))
944 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5600
;
945 else if(WINE_D3D8_CAPABLE(gl_info
))
946 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE3
;
947 else if(WINE_D3D7_CAPABLE(gl_info
))
948 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE
;
949 else if(WINE_D3D6_CAPABLE(gl_info
))
950 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT
;
952 gl_info
->gl_card
= CARD_NVIDIA_RIVA_128
;
954 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info
->gl_vendor
, gl_info
->gl_card
);
956 /* Load all the lookup tables
957 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
958 minLookup
[WINELOOKUP_WARPPARAM
] = WINED3DTADDRESS_WRAP
;
959 maxLookup
[WINELOOKUP_WARPPARAM
] = WINED3DTADDRESS_MIRRORONCE
;
961 minLookup
[WINELOOKUP_MAGFILTER
] = WINED3DTEXF_NONE
;
962 maxLookup
[WINELOOKUP_MAGFILTER
] = WINED3DTEXF_ANISOTROPIC
;
965 for (i
= 0; i
< MAX_LOOKUPS
; i
++) {
966 stateLookup
[i
] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup
[i
]) * (1 + maxLookup
[i
] - minLookup
[i
]) );
969 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_WRAP
- minLookup
[WINELOOKUP_WARPPARAM
]] = GL_REPEAT
;
970 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_CLAMP
- minLookup
[WINELOOKUP_WARPPARAM
]] = GL_CLAMP_TO_EDGE
;
971 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_BORDER
- minLookup
[WINELOOKUP_WARPPARAM
]] =
972 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] ? GL_CLAMP_TO_BORDER_ARB
: GL_REPEAT
;
973 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_BORDER
- minLookup
[WINELOOKUP_WARPPARAM
]] =
974 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] ? GL_CLAMP_TO_BORDER_ARB
: GL_REPEAT
;
975 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_MIRROR
- minLookup
[WINELOOKUP_WARPPARAM
]] =
976 gl_info
->supported
[ARB_TEXTURE_MIRRORED_REPEAT
] ? GL_MIRRORED_REPEAT_ARB
: GL_REPEAT
;
977 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_MIRRORONCE
- minLookup
[WINELOOKUP_WARPPARAM
]] =
978 gl_info
->supported
[ATI_TEXTURE_MIRROR_ONCE
] ? GL_MIRROR_CLAMP_TO_EDGE_ATI
: GL_REPEAT
;
980 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_NONE
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_NEAREST
;
981 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_POINT
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_NEAREST
;
982 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_LINEAR
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_LINEAR
;
983 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_ANISOTROPIC
- minLookup
[WINELOOKUP_MAGFILTER
]] =
984 gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR
: GL_NEAREST
;
987 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_NONE
] = GL_LINEAR
;
988 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_POINT
] = GL_LINEAR
;
989 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_LINEAR
] = GL_LINEAR
;
990 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_NONE
] = GL_NEAREST
;
991 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_POINT
] = GL_NEAREST_MIPMAP_NEAREST
;
992 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_LINEAR
] = GL_NEAREST_MIPMAP_LINEAR
;
993 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_NONE
] = GL_LINEAR
;
994 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_POINT
] = GL_LINEAR_MIPMAP_NEAREST
;
995 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_LINEAR
] = GL_LINEAR_MIPMAP_LINEAR
;
996 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_NONE
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ?
997 GL_LINEAR_MIPMAP_LINEAR
: GL_LINEAR
;
998 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_POINT
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR_MIPMAP_NEAREST
: GL_LINEAR
;
999 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_LINEAR
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR_MIPMAP_LINEAR
: GL_LINEAR
;
1001 /* TODO: config lookups */
1003 /* Make sure there's an active HDC else the WGL extensions will fail */
1004 hdc
= pwglGetCurrentDC();
1006 WGL_Extensions
= GL_EXTCALL(wglGetExtensionsStringARB(hdc
));
1007 TRACE_(d3d_caps
)("WGL_Extensions reported:\n");
1009 if (NULL
== WGL_Extensions
) {
1010 ERR(" WGL_Extensions returns NULL\n");
1012 while (*WGL_Extensions
!= 0x00) {
1017 while (isspace(*WGL_Extensions
)) WGL_Extensions
++;
1018 Start
= WGL_Extensions
;
1019 while (!isspace(*WGL_Extensions
) && *WGL_Extensions
!= 0x00) {
1023 len
= WGL_Extensions
- Start
;
1024 if (len
== 0 || len
>= sizeof(ThisExtn
))
1027 memcpy(ThisExtn
, Start
, len
);
1028 ThisExtn
[len
] = '\0';
1029 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
1031 if (!strcmp(ThisExtn
, "WGL_ARB_pbuffer")) {
1032 gl_info
->supported
[WGL_ARB_PBUFFER
] = TRUE
;
1033 TRACE_(d3d_caps
)("FOUND: WGL_ARB_pbuffer support\n");
1039 return return_value
;
1041 #undef GLINFO_LOCATION
1043 /**********************************************************
1044 * IWineD3D implementation follows
1045 **********************************************************/
1047 static UINT WINAPI
IWineD3DImpl_GetAdapterCount (IWineD3D
*iface
) {
1048 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1050 TRACE_(d3d_caps
)("(%p): Reporting %d adapters\n", This
, numAdapters
);
1054 static HRESULT WINAPI
IWineD3DImpl_RegisterSoftwareDevice(IWineD3D
*iface
, void* pInitializeFunction
) {
1055 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1056 FIXME("(%p)->(%p): stub\n", This
, pInitializeFunction
);
1060 static HMONITOR WINAPI
IWineD3DImpl_GetAdapterMonitor(IWineD3D
*iface
, UINT Adapter
) {
1061 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1063 if (Adapter
>= IWineD3DImpl_GetAdapterCount(iface
)) {
1067 TRACE_(d3d_caps
)("(%p)->(%d)\n", This
, Adapter
);
1068 return MonitorFromPoint(Adapters
[Adapter
].monitorPoint
, MONITOR_DEFAULTTOPRIMARY
);
1071 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1072 of the same bpp but different resolutions */
1074 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1075 static UINT WINAPI
IWineD3DImpl_GetAdapterModeCount(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
) {
1076 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1077 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Format: %s)\n", This
, Adapter
, debug_d3dformat(Format
));
1079 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1083 /* TODO: Store modes per adapter and read it from the adapter structure */
1084 if (Adapter
== 0) { /* Display */
1088 if (!DEBUG_SINGLE_MODE
) {
1091 ZeroMemory(&DevModeW
, sizeof(DevModeW
));
1092 DevModeW
.dmSize
= sizeof(DevModeW
);
1093 while (EnumDisplaySettingsExW(NULL
, j
, &DevModeW
, 0)) {
1097 case WINED3DFMT_UNKNOWN
:
1098 /* This is for D3D8, do not enumerate P8 here */
1099 if (DevModeW
.dmBitsPerPel
== 32 ||
1100 DevModeW
.dmBitsPerPel
== 16) i
++;
1102 case WINED3DFMT_X8R8G8B8
:
1103 if (DevModeW
.dmBitsPerPel
== 32) i
++;
1105 case WINED3DFMT_R5G6B5
:
1106 if (DevModeW
.dmBitsPerPel
== 16) i
++;
1109 if (DevModeW
.dmBitsPerPel
== 8) i
++;
1112 /* Skip other modes as they do not match the requested format */
1121 TRACE_(d3d_caps
)("(%p}->(Adapter: %d) => %d (out of %d)\n", This
, Adapter
, i
, j
);
1124 FIXME_(d3d_caps
)("Adapter not primary display\n");
1129 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1130 static HRESULT WINAPI
IWineD3DImpl_EnumAdapterModes(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
, UINT Mode
, WINED3DDISPLAYMODE
* pMode
) {
1131 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1132 TRACE_(d3d_caps
)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This
, Adapter
, Mode
, pMode
, debug_d3dformat(Format
));
1134 /* Validate the parameters as much as possible */
1135 if (NULL
== pMode
||
1136 Adapter
>= IWineD3DImpl_GetAdapterCount(iface
) ||
1137 Mode
>= IWineD3DImpl_GetAdapterModeCount(iface
, Adapter
, Format
)) {
1138 return WINED3DERR_INVALIDCALL
;
1141 /* TODO: Store modes per adapter and read it from the adapter structure */
1142 if (Adapter
== 0 && !DEBUG_SINGLE_MODE
) { /* Display */
1148 ZeroMemory(&DevModeW
, sizeof(DevModeW
));
1149 DevModeW
.dmSize
= sizeof(DevModeW
);
1151 /* If we are filtering to a specific format (D3D9), then need to skip
1152 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1153 just count through the ones with valid bit depths */
1154 while ((i
<=Mode
) && EnumDisplaySettingsExW(NULL
, j
++, &DevModeW
, 0)) {
1157 case WINED3DFMT_UNKNOWN
:
1158 /* This is D3D8. Do not enumerate P8 here */
1159 if (DevModeW
.dmBitsPerPel
== 32 ||
1160 DevModeW
.dmBitsPerPel
== 16) i
++;
1162 case WINED3DFMT_X8R8G8B8
:
1163 if (DevModeW
.dmBitsPerPel
== 32) i
++;
1165 case WINED3DFMT_R5G6B5
:
1166 if (DevModeW
.dmBitsPerPel
== 16) i
++;
1169 if (DevModeW
.dmBitsPerPel
== 8) i
++;
1172 /* Modes that don't match what we support can get an early-out */
1173 TRACE_(d3d_caps
)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format
));
1174 return WINED3DERR_INVALIDCALL
;
1179 TRACE_(d3d_caps
)("No modes found for format (%x - %s)\n", Format
, debug_d3dformat(Format
));
1180 return WINED3DERR_INVALIDCALL
;
1184 /* Now get the display mode via the calculated index */
1185 if (EnumDisplaySettingsExW(NULL
, ModeIdx
, &DevModeW
, 0)) {
1186 pMode
->Width
= DevModeW
.dmPelsWidth
;
1187 pMode
->Height
= DevModeW
.dmPelsHeight
;
1188 pMode
->RefreshRate
= WINED3DADAPTER_DEFAULT
;
1189 if (DevModeW
.dmFields
& DM_DISPLAYFREQUENCY
)
1190 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
1192 if (Format
== WINED3DFMT_UNKNOWN
)
1194 switch (DevModeW
.dmBitsPerPel
)
1197 pMode
->Format
= WINED3DFMT_P8
;
1200 pMode
->Format
= WINED3DFMT_R5G6B5
;
1203 pMode
->Format
= WINED3DFMT_X8R8G8B8
;
1206 pMode
->Format
= WINED3DFMT_UNKNOWN
;
1207 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW
.dmBitsPerPel
);
1210 pMode
->Format
= Format
;
1213 TRACE_(d3d_caps
)("Requested mode out of range %d\n", Mode
);
1214 return WINED3DERR_INVALIDCALL
;
1217 TRACE_(d3d_caps
)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode
->Width
, pMode
->Height
,
1218 pMode
->RefreshRate
, pMode
->Format
, debug_d3dformat(pMode
->Format
),
1219 DevModeW
.dmBitsPerPel
);
1221 } else if (DEBUG_SINGLE_MODE
) {
1222 /* Return one setting of the format requested */
1223 if (Mode
> 0) return WINED3DERR_INVALIDCALL
;
1225 pMode
->Height
= 600;
1226 pMode
->RefreshRate
= 60;
1227 pMode
->Format
= (Format
== WINED3DFMT_UNKNOWN
) ? WINED3DFMT_X8R8G8B8
: Format
;
1229 FIXME_(d3d_caps
)("Adapter not primary display\n");
1235 static HRESULT WINAPI
IWineD3DImpl_GetAdapterDisplayMode(IWineD3D
*iface
, UINT Adapter
, WINED3DDISPLAYMODE
* pMode
) {
1236 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1237 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, pMode: %p)\n", This
, Adapter
, pMode
);
1239 if (NULL
== pMode
||
1240 Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1241 return WINED3DERR_INVALIDCALL
;
1244 if (Adapter
== 0) { /* Display */
1248 ZeroMemory(&DevModeW
, sizeof(DevModeW
));
1249 DevModeW
.dmSize
= sizeof(DevModeW
);
1251 EnumDisplaySettingsExW(NULL
, ENUM_CURRENT_SETTINGS
, &DevModeW
, 0);
1252 pMode
->Width
= DevModeW
.dmPelsWidth
;
1253 pMode
->Height
= DevModeW
.dmPelsHeight
;
1254 bpp
= DevModeW
.dmBitsPerPel
;
1255 pMode
->RefreshRate
= WINED3DADAPTER_DEFAULT
;
1256 if (DevModeW
.dmFields
&DM_DISPLAYFREQUENCY
)
1258 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
1262 case 8: pMode
->Format
= WINED3DFMT_R3G3B2
; break;
1263 case 16: pMode
->Format
= WINED3DFMT_R5G6B5
; break;
1264 case 24: pMode
->Format
= WINED3DFMT_X8R8G8B8
; break; /* Robots needs 24bit to be X8R8G8B8 */
1265 case 32: pMode
->Format
= WINED3DFMT_X8R8G8B8
; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1266 default: pMode
->Format
= WINED3DFMT_UNKNOWN
;
1270 FIXME_(d3d_caps
)("Adapter not primary display\n");
1273 TRACE_(d3d_caps
)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode
->Width
,
1274 pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
1278 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1279 and fields being inserted in the middle, a new structure is used in place */
1280 static HRESULT WINAPI
IWineD3DImpl_GetAdapterIdentifier(IWineD3D
*iface
, UINT Adapter
, DWORD Flags
,
1281 WINED3DADAPTER_IDENTIFIER
* pIdentifier
) {
1282 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1284 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This
, Adapter
, Flags
, pIdentifier
);
1286 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1287 return WINED3DERR_INVALIDCALL
;
1290 /* Return the information requested */
1291 TRACE_(d3d_caps
)("device/Vendor Name and Version detection using FillGLCaps\n");
1292 strcpy(pIdentifier
->Driver
, Adapters
[Adapter
].driver
);
1293 strcpy(pIdentifier
->Description
, Adapters
[Adapter
].description
);
1295 /* Note dx8 doesn't supply a DeviceName */
1296 if (NULL
!= pIdentifier
->DeviceName
) strcpy(pIdentifier
->DeviceName
, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1297 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1298 pIdentifier
->DriverVersion
->u
.HighPart
= MAKEDWORD_VERSION(6, 14);
1299 pIdentifier
->DriverVersion
->u
.LowPart
= Adapters
[Adapter
].gl_info
.gl_driver_version
;
1300 *(pIdentifier
->VendorId
) = Adapters
[Adapter
].gl_info
.gl_vendor
;
1301 *(pIdentifier
->DeviceId
) = Adapters
[Adapter
].gl_info
.gl_card
;
1302 *(pIdentifier
->SubSysId
) = 0;
1303 *(pIdentifier
->Revision
) = 0;
1305 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1306 if (Flags
& WINED3DENUM_NO_WHQL_LEVEL
) {
1307 *(pIdentifier
->WHQLLevel
) = 0;
1309 *(pIdentifier
->WHQLLevel
) = 1;
1315 static BOOL
IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat
*cfg
, WINED3DFORMAT Format
) {
1316 short redSize
, greenSize
, blueSize
, alphaSize
, colorBits
;
1321 if(!getColorBits(Format
, &redSize
, &greenSize
, &blueSize
, &alphaSize
, &colorBits
)) {
1322 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format
));
1326 if(cfg
->redSize
< redSize
)
1329 if(cfg
->greenSize
< greenSize
)
1332 if(cfg
->blueSize
< blueSize
)
1335 if(cfg
->alphaSize
< alphaSize
)
1341 static BOOL
IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat
*cfg
, WINED3DFORMAT Format
) {
1342 short depthSize
, stencilSize
;
1347 if(!getDepthStencilBits(Format
, &depthSize
, &stencilSize
)) {
1348 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format
));
1352 if(cfg
->depthSize
< depthSize
)
1355 if(cfg
->stencilSize
< stencilSize
)
1361 static HRESULT WINAPI
IWineD3DImpl_CheckDepthStencilMatch(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1362 WINED3DFORMAT AdapterFormat
,
1363 WINED3DFORMAT RenderTargetFormat
,
1364 WINED3DFORMAT DepthStencilFormat
) {
1365 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1367 WineD3D_PixelFormat
*cfgs
;
1370 WARN_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1372 DeviceType
, debug_d3ddevicetype(DeviceType
),
1373 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1374 RenderTargetFormat
, debug_d3dformat(RenderTargetFormat
),
1375 DepthStencilFormat
, debug_d3dformat(DepthStencilFormat
));
1377 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1378 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This
, Adapter
, IWineD3D_GetAdapterCount(iface
));
1379 return WINED3DERR_INVALIDCALL
;
1382 cfgs
= Adapters
[Adapter
].cfgs
;
1383 nCfgs
= Adapters
[Adapter
].nCfgs
;
1384 for (it
= 0; it
< nCfgs
; ++it
) {
1385 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs
[it
], RenderTargetFormat
)) {
1386 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs
[it
], DepthStencilFormat
)) {
1387 TRACE_(d3d_caps
)("(%p) : Formats matched\n", This
);
1392 WARN_(d3d_caps
)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat
), debug_d3dformat(DepthStencilFormat
));
1394 return WINED3DERR_NOTAVAILABLE
;
1397 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1398 WINED3DFORMAT SurfaceFormat
,
1399 BOOL Windowed
, WINED3DMULTISAMPLE_TYPE MultiSampleType
, DWORD
* pQualityLevels
) {
1401 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1402 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1405 DeviceType
, debug_d3ddevicetype(DeviceType
),
1406 SurfaceFormat
, debug_d3dformat(SurfaceFormat
),
1411 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1412 return WINED3DERR_INVALIDCALL
;
1415 /* TODO: Store in Adapter structure */
1416 if (pQualityLevels
!= NULL
) {
1417 static int s_single_shot
= 0;
1418 if (!s_single_shot
) {
1419 FIXME("Quality levels unsupported at present\n");
1422 *pQualityLevels
= 1; /* Guess at a value! */
1425 if (WINED3DMULTISAMPLE_NONE
== MultiSampleType
) return WINED3D_OK
;
1426 return WINED3DERR_NOTAVAILABLE
;
1429 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceType(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE CheckType
,
1430 WINED3DFORMAT DisplayFormat
, WINED3DFORMAT BackBufferFormat
, BOOL Windowed
) {
1432 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1434 WineD3D_PixelFormat
*cfgs
;
1436 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1438 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1441 CheckType
, debug_d3ddevicetype(CheckType
),
1442 DisplayFormat
, debug_d3dformat(DisplayFormat
),
1443 BackBufferFormat
, debug_d3dformat(BackBufferFormat
),
1446 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1447 WARN_(d3d_caps
)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1448 return WINED3DERR_INVALIDCALL
;
1451 cfgs
= Adapters
[Adapter
].cfgs
;
1452 nCfgs
= Adapters
[Adapter
].nCfgs
;
1453 for (it
= 0; it
< nCfgs
; ++it
) {
1454 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs
[it
], DisplayFormat
)) {
1456 TRACE_(d3d_caps
)("OK\n");
1461 if(hr
!= WINED3D_OK
)
1462 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat
));
1464 if(hr
!= WINED3D_OK
)
1465 TRACE_(d3d_caps
)("returning something different from WINED3D_OK\n");
1470 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1471 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormat(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1472 WINED3DFORMAT AdapterFormat
, DWORD Usage
, WINED3DRESOURCETYPE RType
, WINED3DFORMAT CheckFormat
) {
1473 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1474 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1477 DeviceType
, debug_d3ddevicetype(DeviceType
),
1478 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1479 Usage
, debug_d3dusage(Usage
), debug_d3dusagequery(Usage
),
1480 RType
, debug_d3dresourcetype(RType
),
1481 CheckFormat
, debug_d3dformat(CheckFormat
));
1483 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1484 return WINED3DERR_INVALIDCALL
;
1487 if (Usage
& WINED3DUSAGE_QUERY_FILTER
) {
1488 switch (CheckFormat
) {
1489 /* Filtering not supported */
1490 case WINED3DFMT_A32B32G32R32F
:
1491 TRACE_(d3d_caps
)("[FAILED]\n");
1492 return WINED3DERR_NOTAVAILABLE
;
1498 if (Usage
& WINED3DUSAGE_AUTOGENMIPMAP
) {
1499 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP
)) {
1500 TRACE_(d3d_caps
)("[FAILED] - No mipmap generation support\n");
1501 return WINED3DERR_NOTAVAILABLE
;
1505 if(RType
== WINED3DRTYPE_VOLUMETEXTURE
) {
1506 if(!GL_SUPPORT(EXT_TEXTURE3D
)) {
1507 TRACE_(d3d_caps
)("[FAILED] - No volume texture support\n");
1508 return WINED3DERR_NOTAVAILABLE
;
1510 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1511 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1512 * app needing one of those formats, don't advertize them to avoid leading apps into
1513 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1516 switch(CheckFormat
) {
1518 case WINED3DFMT_A4L4
:
1519 case WINED3DFMT_R32F
:
1520 case WINED3DFMT_R16F
:
1521 case WINED3DFMT_X8L8V8U8
:
1522 case WINED3DFMT_L6V5U5
:
1523 TRACE_(d3d_caps
)("[FAILED] - No converted formats on volumes\n");
1524 return WINED3DERR_NOTAVAILABLE
;
1526 case WINED3DFMT_Q8W8V8U8
:
1527 case WINED3DFMT_V16U16
:
1528 if(!GL_SUPPORT(NV_TEXTURE_SHADER
)) {
1529 TRACE_(d3d_caps
)("[FAILED] - No converted formats on volumes\n");
1530 return WINED3DERR_NOTAVAILABLE
;
1534 case WINED3DFMT_V8U8
:
1535 if(!GL_SUPPORT(NV_TEXTURE_SHADER
) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP
)) {
1536 TRACE_(d3d_caps
)("[FAILED] - No converted formats on volumes\n");
1537 return WINED3DERR_NOTAVAILABLE
;
1541 case WINED3DFMT_DXT1
:
1542 case WINED3DFMT_DXT2
:
1543 case WINED3DFMT_DXT3
:
1544 case WINED3DFMT_DXT4
:
1545 case WINED3DFMT_DXT5
:
1546 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1547 * compressed texture results in an error. While the D3D refrast does
1548 * support s3tc volumes, at least the nvidia windows driver does not, so
1549 * we're free not to support this format.
1551 TRACE_(d3d_caps
)("[FAILED] - DXTn does not support 3D textures\n");
1552 return WINED3DERR_NOTAVAILABLE
;
1555 /* Do nothing, continue with checking the format below */
1559 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1560 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1561 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1562 if (Usage
& WINED3DUSAGE_QUERY_VERTEXTEXTURE
) {
1563 if (!GL_LIMITS(vertex_samplers
)) {
1564 TRACE_(d3d_caps
)("[FAILED]\n");
1565 return WINED3DERR_NOTAVAILABLE
;
1568 switch (CheckFormat
) {
1569 case WINED3DFMT_A32B32G32R32F
:
1570 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1571 TRACE_(d3d_caps
)("[FAILED]\n");
1572 return WINED3DERR_NOTAVAILABLE
;
1574 TRACE_(d3d_caps
)("[OK]\n");
1578 TRACE_(d3d_caps
)("[FAILED]\n");
1579 return WINED3DERR_NOTAVAILABLE
;
1583 if(Usage
& WINED3DUSAGE_DEPTHSTENCIL
) {
1584 switch (CheckFormat
) {
1585 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1586 * Windows supports only those 3, and enumerating the other formats confuses applications
1588 case WINED3DFMT_D24S8
:
1589 case WINED3DFMT_D24X8
:
1590 case WINED3DFMT_D16
:
1591 TRACE_(d3d_caps
)("[OK]\n");
1593 case WINED3DFMT_D16_LOCKABLE
:
1594 case WINED3DFMT_D24FS8
:
1595 case WINED3DFMT_D32F_LOCKABLE
:
1596 case WINED3DFMT_D24X4S4
:
1597 case WINED3DFMT_D15S1
:
1598 case WINED3DFMT_D32
:
1599 TRACE_(d3d_caps
)("[FAILED]. Disabled because not enumerated on windows\n");
1600 return WINED3DERR_NOTAVAILABLE
;
1602 TRACE_(d3d_caps
)("[FAILED]\n");
1603 return WINED3DERR_NOTAVAILABLE
;
1605 } else if(Usage
& WINED3DUSAGE_RENDERTARGET
) {
1606 switch (CheckFormat
) {
1607 case WINED3DFMT_R8G8B8
:
1608 case WINED3DFMT_A8R8G8B8
:
1609 case WINED3DFMT_X8R8G8B8
:
1610 case WINED3DFMT_R5G6B5
:
1611 case WINED3DFMT_X1R5G5B5
:
1612 case WINED3DFMT_A1R5G5B5
:
1613 case WINED3DFMT_A4R4G4B4
:
1614 case WINED3DFMT_R3G3B2
:
1615 case WINED3DFMT_X4R4G4B4
:
1616 case WINED3DFMT_A8B8G8R8
:
1617 case WINED3DFMT_X8B8G8R8
:
1619 TRACE_(d3d_caps
)("[OK]\n");
1621 case WINED3DFMT_R16F
:
1622 case WINED3DFMT_A16B16G16R16F
:
1623 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL
) || !GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1624 TRACE_(d3d_caps
)("[FAILED]\n");
1625 return WINED3DERR_NOTAVAILABLE
;
1627 TRACE_(d3d_caps
)("[OK]\n");
1629 case WINED3DFMT_A32B32G32R32F
:
1630 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1631 TRACE_(d3d_caps
)("[FAILED]\n");
1632 return WINED3DERR_NOTAVAILABLE
;
1634 TRACE_(d3d_caps
)("[OK]\n");
1637 TRACE_(d3d_caps
)("[FAILED]\n");
1638 return WINED3DERR_NOTAVAILABLE
;
1640 } else if(Usage
& WINED3DUSAGE_QUERY_LEGACYBUMPMAP
) {
1641 if(GL_SUPPORT(NV_REGISTER_COMBINERS
) && GL_SUPPORT(NV_TEXTURE_SHADER2
)) {
1642 switch (CheckFormat
) {
1643 case WINED3DFMT_V8U8
:
1644 TRACE_(d3d_caps
)("[OK]\n");
1646 /* TODO: Other bump map formats */
1648 TRACE_(d3d_caps
)("[FAILED]\n");
1649 return WINED3DERR_NOTAVAILABLE
;
1652 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP
)) {
1653 switch (CheckFormat
) {
1654 case WINED3DFMT_V8U8
:
1655 TRACE_(d3d_caps
)("[OK]\n");
1658 TRACE_(d3d_caps
)("[FAILED]\n");
1659 return WINED3DERR_NOTAVAILABLE
;
1662 TRACE_(d3d_caps
)("[FAILED]\n");
1663 return WINED3DERR_NOTAVAILABLE
;
1666 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
1667 switch (CheckFormat
) {
1668 case WINED3DFMT_DXT1
:
1669 case WINED3DFMT_DXT2
:
1670 case WINED3DFMT_DXT3
:
1671 case WINED3DFMT_DXT4
:
1672 case WINED3DFMT_DXT5
:
1673 TRACE_(d3d_caps
)("[OK]\n");
1676 break; /* Avoid compiler warnings */
1680 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1681 if (GL_SUPPORT(EXT_TEXTURE_SRGB
) && (Usage
& WINED3DUSAGE_QUERY_SRGBREAD
)) {
1682 switch (CheckFormat
) {
1683 case WINED3DFMT_A8R8G8B8
:
1684 case WINED3DFMT_X8R8G8B8
:
1685 case WINED3DFMT_A4R4G4B4
:
1687 case WINED3DFMT_A8L8
:
1688 case WINED3DFMT_DXT1
:
1689 case WINED3DFMT_DXT2
:
1690 case WINED3DFMT_DXT3
:
1691 case WINED3DFMT_DXT4
:
1692 case WINED3DFMT_DXT5
:
1693 TRACE_(d3d_caps
)("[OK]\n");
1697 TRACE_(d3d_caps
)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat
));
1698 return WINED3DERR_NOTAVAILABLE
;
1702 if (GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1704 BOOL half_pixel_support
= GL_SUPPORT(ARB_HALF_FLOAT_PIXEL
);
1706 switch (CheckFormat
) {
1707 case WINED3DFMT_R16F
:
1708 case WINED3DFMT_A16B16G16R16F
:
1709 if (!half_pixel_support
) break;
1710 case WINED3DFMT_R32F
:
1711 case WINED3DFMT_A32B32G32R32F
:
1712 TRACE_(d3d_caps
)("[OK]\n");
1715 break; /* Avoid compiler warnings */
1719 /* This format is nothing special and it is supported perfectly.
1720 * However, ati and nvidia driver on windows do not mark this format as
1721 * supported (tested with the dxCapsViewer) and pretending to
1722 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1723 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1724 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1726 if(This
->dxVersion
> 7 && CheckFormat
== WINED3DFMT_R8G8B8
) {
1727 TRACE_(d3d_caps
)("[FAILED]\n");
1728 return WINED3DERR_NOTAVAILABLE
;
1731 switch (CheckFormat
) {
1734 * supported: RGB(A) formats
1736 case WINED3DFMT_R8G8B8
: /* Enable for dx7, blacklisted for 8 and 9 above */
1737 case WINED3DFMT_A8R8G8B8
:
1738 case WINED3DFMT_X8R8G8B8
:
1739 case WINED3DFMT_R5G6B5
:
1740 case WINED3DFMT_X1R5G5B5
:
1741 case WINED3DFMT_A1R5G5B5
:
1742 case WINED3DFMT_A4R4G4B4
:
1743 case WINED3DFMT_R3G3B2
:
1745 case WINED3DFMT_X4R4G4B4
:
1746 case WINED3DFMT_A8B8G8R8
:
1747 case WINED3DFMT_X8B8G8R8
:
1748 case WINED3DFMT_A2R10G10B10
:
1749 case WINED3DFMT_A2B10G10R10
:
1750 TRACE_(d3d_caps
)("[OK]\n");
1754 * supported: Palettized
1757 TRACE_(d3d_caps
)("[OK]\n");
1761 * Supported: (Alpha)-Luminance
1764 case WINED3DFMT_A8L8
:
1765 case WINED3DFMT_A4L4
:
1766 TRACE_(d3d_caps
)("[OK]\n");
1770 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1771 * GL_NV_texture_shader), but advertized to make apps happy.
1772 * Enable some because games often fail when they are not available
1773 * and are still playable even without bump mapping
1775 case WINED3DFMT_V8U8
:
1776 case WINED3DFMT_V16U16
:
1777 case WINED3DFMT_L6V5U5
:
1778 case WINED3DFMT_X8L8V8U8
:
1779 case WINED3DFMT_Q8W8V8U8
:
1780 WARN_(d3d_caps
)("[Not supported, but pretended to do]\n");
1783 /* Those are not advertized by the nvidia windows driver, and not
1784 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1785 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1786 * ARGB format if needed
1788 case WINED3DFMT_W11V11U10
:
1789 case WINED3DFMT_A2W10V10U10
:
1790 WARN_(d3d_caps
)("[FAILED]\n");
1791 return WINED3DERR_NOTAVAILABLE
;
1794 * DXTN Formats: Handled above
1803 * Odd formats - not supported
1805 case WINED3DFMT_VERTEXDATA
:
1806 case WINED3DFMT_INDEX16
:
1807 case WINED3DFMT_INDEX32
:
1808 case WINED3DFMT_Q16W16V16U16
:
1809 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1810 return WINED3DERR_NOTAVAILABLE
;
1813 * Float formats: Not supported right now
1815 case WINED3DFMT_G16R16F
:
1816 case WINED3DFMT_G32R32F
:
1817 case WINED3DFMT_CxV8U8
:
1818 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1819 return WINED3DERR_NOTAVAILABLE
;
1822 case WINED3DFMT_G16R16
:
1823 case WINED3DFMT_A16B16G16R16
:
1824 case WINED3DFMT_A8R3G3B2
:
1825 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1826 return WINED3DERR_NOTAVAILABLE
;
1828 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1829 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1830 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1831 * We can do instancing with all shader versions, but we need vertex shaders.
1833 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1834 * to enable instancing. WineD3D doesn't need that and just ignores it.
1836 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1838 case WINEMAKEFOURCC('I','N','S','T'):
1839 TRACE("ATI Instancing check hack\n");
1840 if(GL_SUPPORT(ARB_VERTEX_PROGRAM
) || GL_SUPPORT(ARB_VERTEX_SHADER
)) {
1841 TRACE_(d3d_caps
)("[OK]\n");
1844 TRACE_(d3d_caps
)("[FAILED]\n");
1845 return WINED3DERR_NOTAVAILABLE
;
1852 TRACE_(d3d_caps
)("[FAILED]\n");
1853 return WINED3DERR_NOTAVAILABLE
;
1856 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1857 WINED3DFORMAT SourceFormat
, WINED3DFORMAT TargetFormat
) {
1858 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1860 FIXME_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1863 DeviceType
, debug_d3ddevicetype(DeviceType
),
1864 SourceFormat
, debug_d3dformat(SourceFormat
),
1865 TargetFormat
, debug_d3dformat(TargetFormat
));
1869 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1870 subset of a D3DCAPS9 structure. However, it has to come via a void *
1871 as the d3d8 interface cannot import the d3d9 header */
1872 static HRESULT WINAPI
IWineD3DImpl_GetDeviceCaps(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
, WINED3DCAPS
* pCaps
) {
1874 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1875 int vs_selected_mode
;
1876 int ps_selected_mode
;
1878 TRACE_(d3d_caps
)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This
, Adapter
, DeviceType
, pCaps
);
1880 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1881 return WINED3DERR_INVALIDCALL
;
1884 select_shader_mode(&Adapters
[Adapter
].gl_info
, DeviceType
, &ps_selected_mode
, &vs_selected_mode
);
1886 /* This function should *not* be modifying GL caps
1887 * TODO: move the functionality where it belongs */
1888 select_shader_max_constants(ps_selected_mode
, vs_selected_mode
, &Adapters
[Adapter
].gl_info
);
1890 /* ------------------------------------------------
1891 The following fields apply to both d3d8 and d3d9
1892 ------------------------------------------------ */
1893 *pCaps
->DeviceType
= (DeviceType
== WINED3DDEVTYPE_HAL
) ? WINED3DDEVTYPE_HAL
: WINED3DDEVTYPE_REF
; /* Not quite true, but use h/w supported by opengl I suppose */
1894 *pCaps
->AdapterOrdinal
= Adapter
;
1897 *pCaps
->Caps2
= WINED3DCAPS2_CANRENDERWINDOWED
|
1898 WINED3DCAPS2_FULLSCREENGAMMA
|
1899 WINED3DCAPS2_DYNAMICTEXTURES
;
1900 *pCaps
->Caps3
= WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD
;
1901 *pCaps
->PresentationIntervals
= WINED3DPRESENT_INTERVAL_IMMEDIATE
|
1902 WINED3DPRESENT_INTERVAL_ONE
;
1904 *pCaps
->CursorCaps
= WINED3DCURSORCAPS_COLOR
|
1905 WINED3DCURSORCAPS_LOWRES
;
1907 *pCaps
->DevCaps
= WINED3DDEVCAPS_FLOATTLVERTEX
|
1908 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY
|
1909 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY
|
1910 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
1911 WINED3DDEVCAPS_DRAWPRIMTLVERTEX
|
1912 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT
|
1913 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY
|
1914 WINED3DDEVCAPS_PUREDEVICE
|
1915 WINED3DDEVCAPS_HWRASTERIZATION
|
1916 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY
|
1917 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY
|
1918 WINED3DDEVCAPS_CANRENDERAFTERFLIP
|
1919 WINED3DDEVCAPS_DRAWPRIMITIVES2
|
1920 WINED3DDEVCAPS_DRAWPRIMITIVES2EX
|
1921 WINED3DDEVCAPS_RTPATCHES
;
1923 *pCaps
->PrimitiveMiscCaps
= WINED3DPMISCCAPS_CULLNONE
|
1924 WINED3DPMISCCAPS_CULLCCW
|
1925 WINED3DPMISCCAPS_CULLCW
|
1926 WINED3DPMISCCAPS_COLORWRITEENABLE
|
1927 WINED3DPMISCCAPS_CLIPTLVERTS
|
1928 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS
|
1929 WINED3DPMISCCAPS_MASKZ
|
1930 WINED3DPMISCCAPS_BLENDOP
;
1932 WINED3DPMISCCAPS_NULLREFERENCE
1933 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1934 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1935 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1936 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1937 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1938 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1940 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1942 if (GL_SUPPORT(NV_REGISTER_COMBINERS
))
1943 *pCaps
->PrimitiveMiscCaps
|= WINED3DPMISCCAPS_TSSARGTEMP
;
1944 if (GL_SUPPORT(NV_REGISTER_COMBINERS2
))
1945 *pCaps
->PrimitiveMiscCaps
|= WINED3DPMISCCAPS_PERSTAGECONSTANT
;
1948 *pCaps
->RasterCaps
= WINED3DPRASTERCAPS_DITHER
|
1949 WINED3DPRASTERCAPS_PAT
|
1950 WINED3DPRASTERCAPS_WFOG
|
1951 WINED3DPRASTERCAPS_ZFOG
|
1952 WINED3DPRASTERCAPS_FOGVERTEX
|
1953 WINED3DPRASTERCAPS_FOGTABLE
|
1954 WINED3DPRASTERCAPS_STIPPLE
|
1955 WINED3DPRASTERCAPS_SUBPIXEL
|
1956 WINED3DPRASTERCAPS_ZTEST
|
1957 WINED3DPRASTERCAPS_SCISSORTEST
|
1958 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
|
1959 WINED3DPRASTERCAPS_DEPTHBIAS
;
1961 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
1962 *pCaps
->RasterCaps
|= WINED3DPRASTERCAPS_ANISOTROPY
|
1963 WINED3DPRASTERCAPS_ZBIAS
|
1964 WINED3DPRASTERCAPS_MIPMAPLODBIAS
;
1966 if(GL_SUPPORT(NV_FOG_DISTANCE
)) {
1967 *pCaps
->RasterCaps
|= WINED3DPRASTERCAPS_FOGRANGE
;
1970 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1971 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1972 WINED3DPRASTERCAPS_ANTIALIASEDGES
1973 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1974 WINED3DPRASTERCAPS_WBUFFER */
1976 *pCaps
->ZCmpCaps
= WINED3DPCMPCAPS_ALWAYS
|
1977 WINED3DPCMPCAPS_EQUAL
|
1978 WINED3DPCMPCAPS_GREATER
|
1979 WINED3DPCMPCAPS_GREATEREQUAL
|
1980 WINED3DPCMPCAPS_LESS
|
1981 WINED3DPCMPCAPS_LESSEQUAL
|
1982 WINED3DPCMPCAPS_NEVER
|
1983 WINED3DPCMPCAPS_NOTEQUAL
;
1985 *pCaps
->SrcBlendCaps
= WINED3DPBLENDCAPS_BLENDFACTOR
|
1986 WINED3DPBLENDCAPS_BOTHINVSRCALPHA
|
1987 WINED3DPBLENDCAPS_BOTHSRCALPHA
|
1988 WINED3DPBLENDCAPS_DESTALPHA
|
1989 WINED3DPBLENDCAPS_DESTCOLOR
|
1990 WINED3DPBLENDCAPS_INVDESTALPHA
|
1991 WINED3DPBLENDCAPS_INVDESTCOLOR
|
1992 WINED3DPBLENDCAPS_INVSRCALPHA
|
1993 WINED3DPBLENDCAPS_INVSRCCOLOR
|
1994 WINED3DPBLENDCAPS_ONE
|
1995 WINED3DPBLENDCAPS_SRCALPHA
|
1996 WINED3DPBLENDCAPS_SRCALPHASAT
|
1997 WINED3DPBLENDCAPS_SRCCOLOR
|
1998 WINED3DPBLENDCAPS_ZERO
;
2000 *pCaps
->DestBlendCaps
= WINED3DPBLENDCAPS_BLENDFACTOR
|
2001 WINED3DPBLENDCAPS_DESTALPHA
|
2002 WINED3DPBLENDCAPS_DESTCOLOR
|
2003 WINED3DPBLENDCAPS_INVDESTALPHA
|
2004 WINED3DPBLENDCAPS_INVDESTCOLOR
|
2005 WINED3DPBLENDCAPS_INVSRCALPHA
|
2006 WINED3DPBLENDCAPS_INVSRCCOLOR
|
2007 WINED3DPBLENDCAPS_ONE
|
2008 WINED3DPBLENDCAPS_SRCALPHA
|
2009 WINED3DPBLENDCAPS_SRCCOLOR
|
2010 WINED3DPBLENDCAPS_ZERO
;
2011 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2012 * according to the glBlendFunc manpage
2014 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2015 * legacy settings for srcblend only
2018 *pCaps
->AlphaCmpCaps
= WINED3DPCMPCAPS_ALWAYS
|
2019 WINED3DPCMPCAPS_EQUAL
|
2020 WINED3DPCMPCAPS_GREATER
|
2021 WINED3DPCMPCAPS_GREATEREQUAL
|
2022 WINED3DPCMPCAPS_LESS
|
2023 WINED3DPCMPCAPS_LESSEQUAL
|
2024 WINED3DPCMPCAPS_NEVER
|
2025 WINED3DPCMPCAPS_NOTEQUAL
;
2027 *pCaps
->ShadeCaps
= WINED3DPSHADECAPS_SPECULARGOURAUDRGB
|
2028 WINED3DPSHADECAPS_COLORGOURAUDRGB
|
2029 WINED3DPSHADECAPS_ALPHAFLATBLEND
|
2030 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND
|
2031 WINED3DPSHADECAPS_COLORFLATRGB
|
2032 WINED3DPSHADECAPS_FOGFLAT
|
2033 WINED3DPSHADECAPS_FOGGOURAUD
|
2034 WINED3DPSHADECAPS_SPECULARFLATRGB
;
2036 *pCaps
->TextureCaps
= WINED3DPTEXTURECAPS_ALPHA
|
2037 WINED3DPTEXTURECAPS_ALPHAPALETTE
|
2038 WINED3DPTEXTURECAPS_BORDER
|
2039 WINED3DPTEXTURECAPS_MIPMAP
|
2040 WINED3DPTEXTURECAPS_PROJECTED
|
2041 WINED3DPTEXTURECAPS_PERSPECTIVE
;
2043 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO
)) {
2044 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_POW2
|
2045 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL
;
2048 if( GL_SUPPORT(EXT_TEXTURE3D
)) {
2049 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_VOLUMEMAP
|
2050 WINED3DPTEXTURECAPS_MIPVOLUMEMAP
|
2051 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2
;
2054 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
2055 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_CUBEMAP
|
2056 WINED3DPTEXTURECAPS_MIPCUBEMAP
|
2057 WINED3DPTEXTURECAPS_CUBEMAP_POW2
;
2061 *pCaps
->TextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2062 WINED3DPTFILTERCAPS_MAGFPOINT
|
2063 WINED3DPTFILTERCAPS_MINFLINEAR
|
2064 WINED3DPTFILTERCAPS_MINFPOINT
|
2065 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2066 WINED3DPTFILTERCAPS_MIPFPOINT
|
2067 WINED3DPTFILTERCAPS_LINEAR
|
2068 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2069 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2070 WINED3DPTFILTERCAPS_MIPLINEAR
|
2071 WINED3DPTFILTERCAPS_MIPNEAREST
|
2072 WINED3DPTFILTERCAPS_NEAREST
;
2074 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
2075 *pCaps
->TextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
|
2076 WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
2079 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
2080 *pCaps
->CubeTextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2081 WINED3DPTFILTERCAPS_MAGFPOINT
|
2082 WINED3DPTFILTERCAPS_MINFLINEAR
|
2083 WINED3DPTFILTERCAPS_MINFPOINT
|
2084 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2085 WINED3DPTFILTERCAPS_MIPFPOINT
|
2086 WINED3DPTFILTERCAPS_LINEAR
|
2087 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2088 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2089 WINED3DPTFILTERCAPS_MIPLINEAR
|
2090 WINED3DPTFILTERCAPS_MIPNEAREST
|
2091 WINED3DPTFILTERCAPS_NEAREST
;
2093 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
2094 *pCaps
->CubeTextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
|
2095 WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
2098 *pCaps
->CubeTextureFilterCaps
= 0;
2100 if (GL_SUPPORT(EXT_TEXTURE3D
)) {
2101 *pCaps
->VolumeTextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2102 WINED3DPTFILTERCAPS_MAGFPOINT
|
2103 WINED3DPTFILTERCAPS_MINFLINEAR
|
2104 WINED3DPTFILTERCAPS_MINFPOINT
|
2105 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2106 WINED3DPTFILTERCAPS_MIPFPOINT
|
2107 WINED3DPTFILTERCAPS_LINEAR
|
2108 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2109 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2110 WINED3DPTFILTERCAPS_MIPLINEAR
|
2111 WINED3DPTFILTERCAPS_MIPNEAREST
|
2112 WINED3DPTFILTERCAPS_NEAREST
;
2114 *pCaps
->VolumeTextureFilterCaps
= 0;
2116 *pCaps
->TextureAddressCaps
= WINED3DPTADDRESSCAPS_INDEPENDENTUV
|
2117 WINED3DPTADDRESSCAPS_CLAMP
|
2118 WINED3DPTADDRESSCAPS_WRAP
;
2120 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
2121 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_BORDER
;
2123 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
2124 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRROR
;
2126 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
2127 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRRORONCE
;
2130 if (GL_SUPPORT(EXT_TEXTURE3D
)) {
2131 *pCaps
->VolumeTextureAddressCaps
= WINED3DPTADDRESSCAPS_INDEPENDENTUV
|
2132 WINED3DPTADDRESSCAPS_CLAMP
|
2133 WINED3DPTADDRESSCAPS_WRAP
;
2134 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
2135 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_BORDER
;
2137 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
2138 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRROR
;
2140 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
2141 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRRORONCE
;
2144 *pCaps
->VolumeTextureAddressCaps
= 0;
2146 *pCaps
->LineCaps
= WINED3DLINECAPS_TEXTURE
|
2147 WINED3DLINECAPS_ZTEST
;
2149 WINED3DLINECAPS_BLEND
2150 WINED3DLINECAPS_ALPHACMP
2151 WINED3DLINECAPS_FOG */
2153 *pCaps
->MaxTextureWidth
= GL_LIMITS(texture_size
);
2154 *pCaps
->MaxTextureHeight
= GL_LIMITS(texture_size
);
2156 if(GL_SUPPORT(EXT_TEXTURE3D
))
2157 *pCaps
->MaxVolumeExtent
= GL_LIMITS(texture3d_size
);
2159 *pCaps
->MaxVolumeExtent
= 0;
2161 *pCaps
->MaxTextureRepeat
= 32768;
2162 *pCaps
->MaxTextureAspectRatio
= GL_LIMITS(texture_size
);
2163 *pCaps
->MaxVertexW
= 1.0;
2165 *pCaps
->GuardBandLeft
= 0;
2166 *pCaps
->GuardBandTop
= 0;
2167 *pCaps
->GuardBandRight
= 0;
2168 *pCaps
->GuardBandBottom
= 0;
2170 *pCaps
->ExtentsAdjust
= 0;
2172 *pCaps
->StencilCaps
= WINED3DSTENCILCAPS_DECRSAT
|
2173 WINED3DSTENCILCAPS_INCRSAT
|
2174 WINED3DSTENCILCAPS_INVERT
|
2175 WINED3DSTENCILCAPS_KEEP
|
2176 WINED3DSTENCILCAPS_REPLACE
|
2177 WINED3DSTENCILCAPS_ZERO
;
2178 if (GL_SUPPORT(EXT_STENCIL_WRAP
)) {
2179 *pCaps
->StencilCaps
|= WINED3DSTENCILCAPS_DECR
|
2180 WINED3DSTENCILCAPS_INCR
;
2182 if ( This
->dxVersion
> 8 &&
2183 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE
) ||
2184 GL_SUPPORT(ATI_SEPARATE_STENCIL
) ) ) {
2185 *pCaps
->StencilCaps
|= WINED3DSTENCILCAPS_TWOSIDED
;
2188 *pCaps
->FVFCaps
= WINED3DFVFCAPS_PSIZE
| 0x0008; /* 8 texture coords */
2190 *pCaps
->TextureOpCaps
= WINED3DTEXOPCAPS_ADD
|
2191 WINED3DTEXOPCAPS_ADDSIGNED
|
2192 WINED3DTEXOPCAPS_ADDSIGNED2X
|
2193 WINED3DTEXOPCAPS_MODULATE
|
2194 WINED3DTEXOPCAPS_MODULATE2X
|
2195 WINED3DTEXOPCAPS_MODULATE4X
|
2196 WINED3DTEXOPCAPS_SELECTARG1
|
2197 WINED3DTEXOPCAPS_SELECTARG2
|
2198 WINED3DTEXOPCAPS_DISABLE
;
2200 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE
) ||
2201 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE
) ||
2202 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
2203 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
|
2204 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
|
2205 WINED3DTEXOPCAPS_BLENDFACTORALPHA
|
2206 WINED3DTEXOPCAPS_BLENDCURRENTALPHA
|
2207 WINED3DTEXOPCAPS_LERP
|
2208 WINED3DTEXOPCAPS_SUBTRACT
;
2210 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3
) ||
2211 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
2212 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_ADDSMOOTH
|
2213 WINED3DTEXOPCAPS_MULTIPLYADD
|
2214 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
|
2215 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
|
2216 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM
;
2218 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3
))
2219 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_DOTPRODUCT3
;
2221 if (GL_SUPPORT(NV_REGISTER_COMBINERS
)) {
2222 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
|
2223 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
;
2226 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP
)) {
2227 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BUMPENVMAP
;
2228 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2
)) {
2229 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2230 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2231 * and 3D textures. It also allows us to keep the code simpler by having texture
2232 * shaders constantly enabled.
2234 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BUMPENVMAP
;
2235 /* TODO: Luminance bump map? */
2239 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2240 WINED3DTEXOPCAPS_PREMODULATE */
2243 *pCaps
->MaxTextureBlendStages
= GL_LIMITS(texture_stages
);
2244 *pCaps
->MaxSimultaneousTextures
= GL_LIMITS(textures
);
2245 *pCaps
->MaxUserClipPlanes
= GL_LIMITS(clipplanes
);
2246 *pCaps
->MaxActiveLights
= GL_LIMITS(lights
);
2248 *pCaps
->MaxVertexBlendMatrices
= GL_LIMITS(blends
);
2249 *pCaps
->MaxVertexBlendMatrixIndex
= 0;
2251 *pCaps
->MaxAnisotropy
= GL_LIMITS(anisotropy
);
2252 *pCaps
->MaxPointSize
= GL_LIMITS(pointsize
);
2255 *pCaps
->VertexProcessingCaps
= WINED3DVTXPCAPS_DIRECTIONALLIGHTS
|
2256 WINED3DVTXPCAPS_MATERIALSOURCE7
|
2257 WINED3DVTXPCAPS_POSITIONALLIGHTS
|
2258 WINED3DVTXPCAPS_LOCALVIEWER
|
2259 WINED3DVTXPCAPS_VERTEXFOG
|
2260 WINED3DVTXPCAPS_TEXGEN
;
2262 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2264 *pCaps
->MaxPrimitiveCount
= 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2265 *pCaps
->MaxVertexIndex
= 0xFFFFF;
2266 *pCaps
->MaxStreams
= MAX_STREAMS
;
2267 *pCaps
->MaxStreamStride
= 1024;
2269 if (vs_selected_mode
== SHADER_GLSL
) {
2270 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2271 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2272 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2273 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2274 if(GLINFO_LOCATION
.vs_nv_version
== VS_VERSION_20
)
2275 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(2,0);
2277 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(3,0);
2278 TRACE_(d3d_caps
)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2279 } else if (vs_selected_mode
== SHADER_ARB
) {
2280 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(1,1);
2281 TRACE_(d3d_caps
)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2283 *pCaps
->VertexShaderVersion
= 0;
2284 TRACE_(d3d_caps
)("Vertex shader functionality not available\n");
2287 *pCaps
->MaxVertexShaderConst
= GL_LIMITS(vshader_constantsF
);
2289 if (ps_selected_mode
== SHADER_GLSL
) {
2290 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2291 in case of GeforceFX cards. */
2292 if(GLINFO_LOCATION
.ps_nv_version
== PS_VERSION_20
)
2293 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(2,0);
2295 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(3,0);
2296 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2297 * Direct3D minimum requirement.
2299 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2300 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2302 * The problem is that the refrast clamps temporary results in the shader to
2303 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2304 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2305 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2306 * offer a way to query this.
2308 *pCaps
->PixelShader1xMaxValue
= 8.0;
2309 TRACE_(d3d_caps
)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2310 } else if (ps_selected_mode
== SHADER_ARB
) {
2311 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(1,4);
2312 *pCaps
->PixelShader1xMaxValue
= 8.0;
2313 TRACE_(d3d_caps
)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2315 *pCaps
->PixelShaderVersion
= 0;
2316 *pCaps
->PixelShader1xMaxValue
= 0.0;
2317 TRACE_(d3d_caps
)("Pixel shader functionality not available\n");
2320 /* ------------------------------------------------
2321 The following fields apply to d3d9 only
2322 ------------------------------------------------ */
2323 if (This
->dxVersion
> 8) {
2324 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2325 *pCaps
->DevCaps2
= WINED3DDEVCAPS2_STREAMOFFSET
;
2326 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2327 *pCaps
->MaxNpatchTessellationLevel
= 0;
2328 *pCaps
->MasterAdapterOrdinal
= 0;
2329 *pCaps
->AdapterOrdinalInGroup
= 0;
2330 *pCaps
->NumberOfAdaptersInGroup
= 1;
2332 if(*pCaps
->VertexShaderVersion
>= WINED3DVS_VERSION(2,0)) {
2333 /* OpenGL supports all the formats below, perhaps not always
2334 * without conversion, but it supports them.
2335 * Further GLSL doesn't seem to have an official unsigned type so
2336 * don't advertise it yet as I'm not sure how we handle it.
2337 * We might need to add some clamping in the shader engine to
2339 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2340 *pCaps
->DeclTypes
= WINED3DDTCAPS_UBYTE4
|
2341 WINED3DDTCAPS_UBYTE4N
|
2342 WINED3DDTCAPS_SHORT2N
|
2343 WINED3DDTCAPS_SHORT4N
;
2344 if (GL_SUPPORT(NV_HALF_FLOAT
)) {
2345 *pCaps
->DeclTypes
|=
2346 WINED3DDTCAPS_FLOAT16_2
|
2347 WINED3DDTCAPS_FLOAT16_4
;
2350 *pCaps
->DeclTypes
= 0;
2352 *pCaps
->NumSimultaneousRTs
= GL_LIMITS(buffers
);
2355 *pCaps
->StretchRectFilterCaps
= WINED3DPTFILTERCAPS_MINFPOINT
|
2356 WINED3DPTFILTERCAPS_MAGFPOINT
|
2357 WINED3DPTFILTERCAPS_MINFLINEAR
|
2358 WINED3DPTFILTERCAPS_MAGFLINEAR
;
2359 *pCaps
->VertexTextureFilterCaps
= 0;
2361 if(*pCaps
->VertexShaderVersion
== WINED3DVS_VERSION(3,0)) {
2362 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2363 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2364 *pCaps
->VS20Caps
.Caps
= WINED3DVS20CAPS_PREDICATION
;
2365 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH
; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2366 *pCaps
->VS20Caps
.NumTemps
= max(32, GLINFO_LOCATION
.vs_arb_max_temps
);
2367 *pCaps
->VS20Caps
.StaticFlowControlDepth
= WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH
; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2369 *pCaps
->MaxVShaderInstructionsExecuted
= 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2370 *pCaps
->MaxVertexShader30InstructionSlots
= max(512, GLINFO_LOCATION
.vs_arb_max_instructions
);
2371 } else if(*pCaps
->VertexShaderVersion
== WINED3DVS_VERSION(2,0)) {
2372 *pCaps
->VS20Caps
.Caps
= 0;
2373 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH
;
2374 *pCaps
->VS20Caps
.NumTemps
= max(12, GLINFO_LOCATION
.vs_arb_max_temps
);
2375 *pCaps
->VS20Caps
.StaticFlowControlDepth
= 1;
2377 *pCaps
->MaxVShaderInstructionsExecuted
= 65535;
2378 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
2379 } else { /* VS 1.x */
2380 *pCaps
->VS20Caps
.Caps
= 0;
2381 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= 0;
2382 *pCaps
->VS20Caps
.NumTemps
= 0;
2383 *pCaps
->VS20Caps
.StaticFlowControlDepth
= 0;
2385 *pCaps
->MaxVShaderInstructionsExecuted
= 0;
2386 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
2389 if(*pCaps
->PixelShaderVersion
== WINED3DPS_VERSION(3,0)) {
2390 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2391 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2393 /* 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 */
2394 *pCaps
->PS20Caps
.Caps
= WINED3DPS20CAPS_ARBITRARYSWIZZLE
|
2395 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS
|
2396 WINED3DPS20CAPS_PREDICATION
|
2397 WINED3DPS20CAPS_NODEPENDENTREADLIMIT
|
2398 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
;
2399 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH
; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2400 *pCaps
->PS20Caps
.NumTemps
= max(32, GLINFO_LOCATION
.ps_arb_max_temps
);
2401 *pCaps
->PS20Caps
.StaticFlowControlDepth
= WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH
; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2402 *pCaps
->PS20Caps
.NumInstructionSlots
= WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS
; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2404 *pCaps
->MaxPShaderInstructionsExecuted
= 65535;
2405 *pCaps
->MaxPixelShader30InstructionSlots
= max(WINED3DMIN30SHADERINSTRUCTIONS
, GLINFO_LOCATION
.ps_arb_max_instructions
);
2406 } else if(*pCaps
->PixelShaderVersion
== WINED3DPS_VERSION(2,0)) {
2407 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2408 *pCaps
->PS20Caps
.Caps
= 0;
2409 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2410 *pCaps
->PS20Caps
.NumTemps
= max(12, GLINFO_LOCATION
.ps_arb_max_temps
);
2411 *pCaps
->PS20Caps
.StaticFlowControlDepth
= WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH
; /* Minumum: 1 */
2412 *pCaps
->PS20Caps
.NumInstructionSlots
= WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS
; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2414 *pCaps
->MaxPShaderInstructionsExecuted
= 512; /* Minimum value, a GeforceFX uses 1024 */
2415 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
2416 } else { /* PS 1.x */
2417 *pCaps
->PS20Caps
.Caps
= 0;
2418 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= 0;
2419 *pCaps
->PS20Caps
.NumTemps
= 0;
2420 *pCaps
->PS20Caps
.StaticFlowControlDepth
= 0;
2421 *pCaps
->PS20Caps
.NumInstructionSlots
= 0;
2423 *pCaps
->MaxPShaderInstructionsExecuted
= 0;
2424 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
2431 static unsigned int glsl_program_key_hash(void *key
) {
2432 glsl_program_key_t
*k
= (glsl_program_key_t
*)key
;
2434 unsigned int hash
= k
->vshader
| k
->pshader
<< 16;
2435 hash
+= ~(hash
<< 15);
2436 hash
^= (hash
>> 10);
2437 hash
+= (hash
<< 3);
2438 hash
^= (hash
>> 6);
2439 hash
+= ~(hash
<< 11);
2440 hash
^= (hash
>> 16);
2445 static BOOL
glsl_program_key_compare(void *keya
, void *keyb
) {
2446 glsl_program_key_t
*ka
= (glsl_program_key_t
*)keya
;
2447 glsl_program_key_t
*kb
= (glsl_program_key_t
*)keyb
;
2449 return ka
->vshader
== kb
->vshader
&& ka
->pshader
== kb
->pshader
;
2452 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2453 and fields being inserted in the middle, a new structure is used in place */
2454 static HRESULT WINAPI
IWineD3DImpl_CreateDevice(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
, HWND hFocusWindow
,
2455 DWORD BehaviourFlags
, IWineD3DDevice
** ppReturnedDeviceInterface
,
2458 IWineD3DDeviceImpl
*object
= NULL
;
2459 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2463 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2464 * number and create a device without a 3D adapter for 2D only operation.
2466 if (IWineD3D_GetAdapterCount(iface
) && Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
2467 return WINED3DERR_INVALIDCALL
;
2470 /* Create a WineD3DDevice object */
2471 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DDeviceImpl
));
2472 *ppReturnedDeviceInterface
= (IWineD3DDevice
*)object
;
2473 TRACE("Created WineD3DDevice object @ %p\n", object
);
2474 if (NULL
== object
) {
2475 return WINED3DERR_OUTOFVIDEOMEMORY
;
2478 /* Set up initial COM information */
2479 object
->lpVtbl
= &IWineD3DDevice_Vtbl
;
2481 object
->wineD3D
= iface
;
2482 object
->adapter
= numAdapters
? &Adapters
[Adapter
] : NULL
;
2483 IWineD3D_AddRef(object
->wineD3D
);
2484 object
->parent
= parent
;
2486 if(This
->dxVersion
== 7) {
2487 object
->surface_alignment
= 8;
2489 object
->surface_alignment
= 4;
2492 /* Set the state up as invalid until the device is fully created */
2493 object
->state
= WINED3DERR_DRIVERINTERNALERROR
;
2495 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This
, Adapter
, DeviceType
,
2496 hFocusWindow
, BehaviourFlags
, ppReturnedDeviceInterface
);
2498 /* Save the creation parameters */
2499 object
->createParms
.AdapterOrdinal
= Adapter
;
2500 object
->createParms
.DeviceType
= DeviceType
;
2501 object
->createParms
.hFocusWindow
= hFocusWindow
;
2502 object
->createParms
.BehaviorFlags
= BehaviourFlags
;
2504 /* Initialize other useful values */
2505 object
->adapterNo
= Adapter
;
2506 object
->devType
= DeviceType
;
2508 select_shader_mode(&GLINFO_LOCATION
, DeviceType
, &object
->ps_selected_mode
, &object
->vs_selected_mode
);
2509 if (object
->ps_selected_mode
== SHADER_GLSL
|| object
->vs_selected_mode
== SHADER_GLSL
) {
2510 object
->shader_backend
= &glsl_shader_backend
;
2511 object
->glsl_program_lookup
= hash_table_create(&glsl_program_key_hash
, &glsl_program_key_compare
);
2512 } else if (object
->ps_selected_mode
== SHADER_ARB
|| object
->vs_selected_mode
== SHADER_ARB
) {
2513 object
->shader_backend
= &arb_program_shader_backend
;
2515 object
->shader_backend
= &none_shader_backend
;
2518 /* set the state of the device to valid */
2519 object
->state
= WINED3D_OK
;
2521 /* Get the initial screen setup for ddraw */
2522 object
->ddraw_width
= GetSystemMetrics(SM_CXSCREEN
);
2523 object
->ddraw_height
= GetSystemMetrics(SM_CYSCREEN
);
2525 object
->ddraw_format
= pixelformat_for_depth(GetDeviceCaps(hDC
, BITSPIXEL
) * GetDeviceCaps(hDC
, PLANES
));
2528 for(i
= 0; i
< PATCHMAP_SIZE
; i
++) {
2529 list_init(&object
->patches
[i
]);
2533 #undef GLINFO_LOCATION
2535 static HRESULT WINAPI
IWineD3DImpl_GetParent(IWineD3D
*iface
, IUnknown
**pParent
) {
2536 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2537 IUnknown_AddRef(This
->parent
);
2538 *pParent
= This
->parent
;
2542 ULONG WINAPI
D3DCB_DefaultDestroySurface(IWineD3DSurface
*pSurface
) {
2543 IUnknown
* surfaceParent
;
2544 TRACE("(%p) call back\n", pSurface
);
2546 /* Now, release the parent, which will take care of cleaning up the surface for us */
2547 IWineD3DSurface_GetParent(pSurface
, &surfaceParent
);
2548 IUnknown_Release(surfaceParent
);
2549 return IUnknown_Release(surfaceParent
);
2552 ULONG WINAPI
D3DCB_DefaultDestroyVolume(IWineD3DVolume
*pVolume
) {
2553 IUnknown
* volumeParent
;
2554 TRACE("(%p) call back\n", pVolume
);
2556 /* Now, release the parent, which will take care of cleaning up the volume for us */
2557 IWineD3DVolume_GetParent(pVolume
, &volumeParent
);
2558 IUnknown_Release(volumeParent
);
2559 return IUnknown_Release(volumeParent
);
2562 #define PUSH1(att) attribs[nAttribs++] = (att);
2563 #define GLINFO_LOCATION (Adapters[0].gl_info)
2564 BOOL
InitAdapters(void) {
2565 static HMODULE mod_gl
;
2567 int ps_selected_mode
, vs_selected_mode
;
2569 /* No need to hold any lock. The calling library makes sure only one thread calls
2570 * wined3d simultaneously
2572 if(numAdapters
> 0) return TRUE
;
2574 TRACE("Initializing adapters\n");
2577 #ifdef USE_WIN32_OPENGL
2578 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2579 mod_gl
= LoadLibraryA("opengl32.dll");
2581 ERR("Can't load opengl32.dll!\n");
2585 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2586 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2587 mod_gl
= GetModuleHandleA("gdi32.dll");
2591 /* Load WGL core functions from opengl32.dll */
2592 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2596 if(!pwglGetProcAddress
) {
2597 ERR("Unable to load wglGetProcAddress!\n");
2601 /* Dynamically load all GL core functions */
2605 /* For now only one default adapter */
2612 WineD3D_PixelFormat
*cfgs
;
2614 DISPLAY_DEVICEW DisplayDevice
;
2617 TRACE("Initializing default adapter\n");
2618 Adapters
[0].monitorPoint
.x
= -1;
2619 Adapters
[0].monitorPoint
.y
= -1;
2621 if (!WineD3D_CreateFakeGLContext()) {
2622 ERR("Failed to get a gl context for default adapter\n");
2623 HeapFree(GetProcessHeap(), 0, Adapters
);
2624 WineD3D_ReleaseFakeGLContext();
2628 ret
= IWineD3DImpl_FillGLCaps(&Adapters
[0].gl_info
);
2630 ERR("Failed to initialize gl caps for default adapter\n");
2631 HeapFree(GetProcessHeap(), 0, Adapters
);
2632 WineD3D_ReleaseFakeGLContext();
2635 ret
= initPixelFormats(&Adapters
[0].gl_info
);
2637 ERR("Failed to init gl formats\n");
2638 HeapFree(GetProcessHeap(), 0, Adapters
);
2639 WineD3D_ReleaseFakeGLContext();
2643 hdc
= pwglGetCurrentDC();
2645 ERR("Failed to get gl HDC\n");
2646 HeapFree(GetProcessHeap(), 0, Adapters
);
2647 WineD3D_ReleaseFakeGLContext();
2651 Adapters
[0].driver
= "Display";
2652 Adapters
[0].description
= "Direct3D HAL";
2654 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2655 DisplayDevice
.cb
= sizeof(DisplayDevice
);
2656 EnumDisplayDevicesW(NULL
, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice
, 0);
2657 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice
.DeviceName
));
2658 strcpyW(Adapters
[0].DeviceName
, DisplayDevice
.DeviceName
);
2660 attribute
= WGL_NUMBER_PIXEL_FORMATS_ARB
;
2661 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc
, 0, 0, 1, &attribute
, &Adapters
[0].nCfgs
));
2663 Adapters
[0].cfgs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, Adapters
[0].nCfgs
*sizeof(WineD3D_PixelFormat
));
2664 cfgs
= Adapters
[0].cfgs
;
2665 PUSH1(WGL_RED_BITS_ARB
)
2666 PUSH1(WGL_GREEN_BITS_ARB
)
2667 PUSH1(WGL_BLUE_BITS_ARB
)
2668 PUSH1(WGL_ALPHA_BITS_ARB
)
2669 PUSH1(WGL_DEPTH_BITS_ARB
)
2670 PUSH1(WGL_STENCIL_BITS_ARB
)
2672 for(iPixelFormat
=1; iPixelFormat
<=Adapters
[0].nCfgs
; iPixelFormat
++) {
2673 res
= GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, 0, nAttribs
, attribs
, values
));
2678 /* Cache the pixel format */
2679 cfgs
->iPixelFormat
= iPixelFormat
;
2680 cfgs
->redSize
= values
[0];
2681 cfgs
->greenSize
= values
[1];
2682 cfgs
->blueSize
= values
[2];
2683 cfgs
->alphaSize
= values
[3];
2684 cfgs
->depthSize
= values
[4];
2685 cfgs
->stencilSize
= values
[5];
2687 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
);
2690 WineD3D_ReleaseFakeGLContext();
2692 select_shader_mode(&Adapters
[0].gl_info
, WINED3DDEVTYPE_HAL
, &ps_selected_mode
, &vs_selected_mode
);
2693 select_shader_max_constants(ps_selected_mode
, vs_selected_mode
, &Adapters
[0].gl_info
);
2697 TRACE("%d adapters successfully initialized\n", numAdapters
);
2702 #undef GLINFO_LOCATION
2704 /**********************************************************
2705 * IWineD3D VTbl follows
2706 **********************************************************/
2708 const IWineD3DVtbl IWineD3D_Vtbl
=
2711 IWineD3DImpl_QueryInterface
,
2712 IWineD3DImpl_AddRef
,
2713 IWineD3DImpl_Release
,
2715 IWineD3DImpl_GetParent
,
2716 IWineD3DImpl_GetAdapterCount
,
2717 IWineD3DImpl_RegisterSoftwareDevice
,
2718 IWineD3DImpl_GetAdapterMonitor
,
2719 IWineD3DImpl_GetAdapterModeCount
,
2720 IWineD3DImpl_EnumAdapterModes
,
2721 IWineD3DImpl_GetAdapterDisplayMode
,
2722 IWineD3DImpl_GetAdapterIdentifier
,
2723 IWineD3DImpl_CheckDeviceMultiSampleType
,
2724 IWineD3DImpl_CheckDepthStencilMatch
,
2725 IWineD3DImpl_CheckDeviceType
,
2726 IWineD3DImpl_CheckDeviceFormat
,
2727 IWineD3DImpl_CheckDeviceFormatConversion
,
2728 IWineD3DImpl_GetDeviceCaps
,
2729 IWineD3DImpl_CreateDevice