rpcrt4/tests: Fix the marshalling test for Win64.
[wine.git] / dlls / wined3d / directx.c
blobf96d10192f8d07d874714de07e807e3cbc8bc818
1 /*
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
8 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 /* Compile time diagnostics: */
27 #ifndef DEBUG_SINGLE_MODE
28 /* Set to 1 to force only a single display mode to be exposed: */
29 #define DEBUG_SINGLE_MODE 0
30 #endif
32 #include "config.h"
33 #include <assert.h>
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 #define GLINFO_LOCATION (*gl_info)
41 /* The d3d device ID */
42 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
44 /* Extension detection */
45 static const struct {
46 const char *extension_string;
47 GL_SupportedExt extension;
48 DWORD version;
49 } EXTENSION_MAP[] = {
50 /* APPLE */
51 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
52 {"GL_APPLE_fence", APPLE_FENCE, 0 },
53 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
54 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
55 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
57 /* ATI */
58 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
59 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
60 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
61 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
62 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
64 /* ARB */
65 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
66 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
67 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
68 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
69 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
70 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
71 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
72 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
73 {"GL_ARB_imaging", ARB_IMAGING, 0 },
74 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
75 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
76 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
77 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
78 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
79 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
80 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
81 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
82 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
83 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
84 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
85 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
86 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
87 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
88 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
89 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
90 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
91 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
92 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
93 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
94 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
95 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
96 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
97 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
99 /* EXT */
100 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
101 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
102 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
103 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
104 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
105 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
106 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
107 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
108 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
109 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
110 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
111 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
112 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
113 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
114 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
115 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
116 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
117 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
118 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
119 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
120 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
121 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
122 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
123 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
124 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
125 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
126 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
127 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
129 /* NV */
130 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
131 {"GL_NV_fence", NV_FENCE, 0 },
132 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
133 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
134 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
135 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
136 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
137 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
138 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
139 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
140 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
141 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
142 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
143 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
144 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
145 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
146 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
147 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
148 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
149 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
150 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
152 /* SGI */
153 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
156 /**********************************************************
157 * Utility functions follow
158 **********************************************************/
160 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
161 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
162 WINED3DDEVTYPE DeviceType);
163 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
164 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
166 /* lookup tables */
167 const int minLookup[MAX_LOOKUPS] =
169 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
172 const int maxLookup[MAX_LOOKUPS] =
174 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
177 DWORD *stateLookup[MAX_LOOKUPS];
179 struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
180 const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
182 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
183 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
184 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
185 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
188 GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
189 const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
191 GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
194 /* drawStridedSlow attributes */
195 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
196 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
197 glAttribFunc specular_func_3ubv;
198 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
199 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
200 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
203 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
204 * i.e., there is no GL Context - Get a default rendering context to enable the
205 * function query some info from GL.
208 static int wined3d_fake_gl_context_ref = 0;
209 static BOOL wined3d_fake_gl_context_foreign;
210 static BOOL wined3d_fake_gl_context_available = FALSE;
211 static HDC wined3d_fake_gl_context_hdc = NULL;
212 static HWND wined3d_fake_gl_context_hwnd = NULL;
214 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
215 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
217 0, 0, &wined3d_fake_gl_context_cs,
218 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
219 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
220 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
222 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
224 static void WineD3D_ReleaseFakeGLContext(void) {
225 HGLRC glCtx;
227 EnterCriticalSection(&wined3d_fake_gl_context_cs);
229 if(!wined3d_fake_gl_context_available) {
230 TRACE_(d3d_caps)("context not available\n");
231 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
232 return;
235 glCtx = pwglGetCurrentContext();
237 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
238 if (0 == (--wined3d_fake_gl_context_ref) ) {
239 if(!wined3d_fake_gl_context_foreign && glCtx) {
240 TRACE_(d3d_caps)("destroying fake GL context\n");
241 pwglMakeCurrent(NULL, NULL);
242 pwglDeleteContext(glCtx);
244 if(wined3d_fake_gl_context_hdc)
245 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
246 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
247 if(wined3d_fake_gl_context_hwnd)
248 DestroyWindow(wined3d_fake_gl_context_hwnd);
249 wined3d_fake_gl_context_hwnd = NULL;
250 wined3d_fake_gl_context_available = FALSE;
252 assert(wined3d_fake_gl_context_ref >= 0);
254 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
257 static BOOL WineD3D_CreateFakeGLContext(void) {
258 HGLRC glCtx = NULL;
260 EnterCriticalSection(&wined3d_fake_gl_context_cs);
262 TRACE("getting context...\n");
263 if(wined3d_fake_gl_context_ref > 0) goto ret;
264 assert(0 == wined3d_fake_gl_context_ref);
266 wined3d_fake_gl_context_foreign = TRUE;
268 glCtx = pwglGetCurrentContext();
269 if (!glCtx) {
270 PIXELFORMATDESCRIPTOR pfd;
271 int iPixelFormat;
273 wined3d_fake_gl_context_foreign = FALSE;
275 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
276 wined3d_fake_gl_context_hwnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
277 if(!wined3d_fake_gl_context_hwnd) {
278 ERR("HWND creation failed!\n");
279 goto fail;
281 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
282 if(!wined3d_fake_gl_context_hdc) {
283 ERR("GetDC failed!\n");
284 goto fail;
287 /* PixelFormat selection */
288 ZeroMemory(&pfd, sizeof(pfd));
289 pfd.nSize = sizeof(pfd);
290 pfd.nVersion = 1;
291 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
292 pfd.iPixelType = PFD_TYPE_RGBA;
293 pfd.cColorBits = 32;
294 pfd.iLayerType = PFD_MAIN_PLANE;
296 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
297 if(!iPixelFormat) {
298 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
299 ERR("Can't find a suitable iPixelFormat\n");
300 goto fail;
302 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
303 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
305 /* Create a GL context */
306 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
307 if (!glCtx) {
308 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
309 goto fail;
312 /* Make it the current GL context */
313 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
314 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
315 goto fail;
319 ret:
320 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
321 wined3d_fake_gl_context_ref++;
322 wined3d_fake_gl_context_available = TRUE;
323 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
324 return TRUE;
325 fail:
326 if(wined3d_fake_gl_context_hdc)
327 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
328 wined3d_fake_gl_context_hdc = NULL;
329 if(wined3d_fake_gl_context_hwnd)
330 DestroyWindow(wined3d_fake_gl_context_hwnd);
331 wined3d_fake_gl_context_hwnd = NULL;
332 if(glCtx) pwglDeleteContext(glCtx);
333 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
334 return FALSE;
337 /* Adjust the amount of used texture memory */
338 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
339 struct WineD3DAdapter *adapter = D3DDevice->adapter;
341 adapter->UsedTextureRam += glram;
342 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
343 return adapter->UsedTextureRam;
346 /**********************************************************
347 * IUnknown parts follows
348 **********************************************************/
350 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
354 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
355 if (IsEqualGUID(riid, &IID_IUnknown)
356 || IsEqualGUID(riid, &IID_IWineD3DBase)
357 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
358 IUnknown_AddRef(iface);
359 *ppobj = This;
360 return S_OK;
362 *ppobj = NULL;
363 return E_NOINTERFACE;
366 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
367 IWineD3DImpl *This = (IWineD3DImpl *)iface;
368 ULONG refCount = InterlockedIncrement(&This->ref);
370 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
371 return refCount;
374 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
375 IWineD3DImpl *This = (IWineD3DImpl *)iface;
376 ULONG ref;
377 TRACE("(%p) : Releasing from %d\n", This, This->ref);
378 ref = InterlockedDecrement(&This->ref);
379 if (ref == 0) {
380 unsigned int i;
382 for (i = 0; i < This->adapter_count; ++i)
384 HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
386 HeapFree(GetProcessHeap(), 0, This);
389 return ref;
392 /* Set the shader type for this device, depending on the given capabilities,
393 * the device type, and the user preferences in wined3d_settings */
395 static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
397 if (wined3d_settings.vs_mode == VS_NONE) {
398 *vs_selected = SHADER_NONE;
399 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
400 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
401 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
402 * shaders only on this card. */
403 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
404 *vs_selected = SHADER_ARB;
405 else
406 *vs_selected = SHADER_GLSL;
407 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
408 *vs_selected = SHADER_ARB;
409 } else {
410 *vs_selected = SHADER_NONE;
413 if (wined3d_settings.ps_mode == PS_NONE) {
414 *ps_selected = SHADER_NONE;
415 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
416 *ps_selected = SHADER_GLSL;
417 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
418 *ps_selected = SHADER_ARB;
419 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
420 *ps_selected = SHADER_ATI;
421 } else {
422 *ps_selected = SHADER_NONE;
426 /** Select the number of report maximum shader constants based on the selected shader modes */
427 static void select_shader_max_constants(
428 int ps_selected_mode,
429 int vs_selected_mode,
430 WineD3D_GL_Info *gl_info) {
432 switch (vs_selected_mode) {
433 case SHADER_GLSL:
434 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
435 break;
436 case SHADER_ARB:
437 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
438 break;
439 default:
440 gl_info->max_vshader_constantsF = 0;
441 break;
444 switch (ps_selected_mode) {
445 case SHADER_GLSL:
446 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
447 break;
448 case SHADER_ARB:
449 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
450 break;
451 default:
452 gl_info->max_pshader_constantsF = 0;
453 break;
457 /**********************************************************
458 * IWineD3D parts follows
459 **********************************************************/
461 /* GL locking is done by the caller */
462 static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info)
464 GLuint prog;
465 BOOL ret = FALSE;
466 const char *testcode =
467 "!!ARBvp1.0\n"
468 "PARAM C[66] = { program.env[0..65] };\n"
469 "ADDRESS A0;"
470 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
471 "ARL A0.x, zero.x;\n"
472 "MOV result.position, C[A0.x + 65];\n"
473 "END\n";
475 while(glGetError());
476 GL_EXTCALL(glGenProgramsARB(1, &prog));
477 if(!prog) {
478 ERR("Failed to create an ARB offset limit test program\n");
480 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
481 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
482 strlen(testcode), testcode));
483 if(glGetError() != 0) {
484 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
485 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
486 ret = TRUE;
487 } else TRACE("OpenGL implementation allows offsets > 63\n");
489 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
490 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
491 checkGLcall("ARB vp offset limit test cleanup\n");
493 return ret;
496 static DWORD ver_for_ext(GL_SupportedExt ext)
498 unsigned int i;
499 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
500 if(EXTENSION_MAP[i].extension == ext) {
501 return EXTENSION_MAP[i].version;
504 return 0;
507 static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
508 const char *GL_Extensions = NULL;
509 const char *WGL_Extensions = NULL;
510 const char *gl_string = NULL;
511 const char *gl_string_cursor = NULL;
512 GLint gl_max;
513 GLfloat gl_floatv[2];
514 int major = 1, minor = 0;
515 BOOL return_value = TRUE;
516 unsigned i;
517 HDC hdc;
518 unsigned int vidmem=0;
520 TRACE_(d3d_caps)("(%p)\n", gl_info);
522 ENTER_GL();
524 gl_string = (const char *) glGetString(GL_RENDERER);
525 if (!gl_string) gl_string = "None";
526 strcpy(gl_info->gl_renderer, gl_string);
528 gl_string = (const char *) glGetString(GL_VENDOR);
529 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
530 if (gl_string != NULL) {
531 /* Fill in the GL vendor */
532 if (strstr(gl_string, "NVIDIA")) {
533 gl_info->gl_vendor = VENDOR_NVIDIA;
534 } else if (strstr(gl_string, "ATI")) {
535 gl_info->gl_vendor = VENDOR_ATI;
536 } else if (strstr(gl_string, "Intel(R)") ||
537 strstr(gl_info->gl_renderer, "Intel(R)") ||
538 strstr(gl_string, "Intel Inc.")) {
539 gl_info->gl_vendor = VENDOR_INTEL;
540 } else if (strstr(gl_string, "Mesa")) {
541 gl_info->gl_vendor = VENDOR_MESA;
542 } else {
543 gl_info->gl_vendor = VENDOR_WINE;
545 } else {
546 gl_info->gl_vendor = VENDOR_WINE;
550 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
552 /* Parse the GL_VERSION field into major and minor information */
553 gl_string = (const char *) glGetString(GL_VERSION);
554 if (gl_string != NULL) {
556 /* First, parse the generic opengl version. This is supposed not to be convoluted with
557 * driver specific information
559 gl_string_cursor = gl_string;
560 major = atoi(gl_string_cursor);
561 if(major <= 0) {
562 ERR("Invalid opengl major version: %d\n", major);
564 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
565 ++gl_string_cursor;
567 if (*gl_string_cursor++ != '.') {
568 ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
570 minor = atoi(gl_string_cursor);
571 TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
572 gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
574 /* Now parse the driver specific string which we'll report to the app */
575 switch (gl_info->gl_vendor) {
576 case VENDOR_NVIDIA:
577 gl_string_cursor = strstr(gl_string, "NVIDIA");
578 if (!gl_string_cursor) {
579 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
580 break;
583 gl_string_cursor = strstr(gl_string_cursor, " ");
584 if (!gl_string_cursor) {
585 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
586 break;
589 while (*gl_string_cursor == ' ') {
590 ++gl_string_cursor;
593 if (!*gl_string_cursor) {
594 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
595 break;
598 major = atoi(gl_string_cursor);
599 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
600 ++gl_string_cursor;
603 if (*gl_string_cursor++ != '.') {
604 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
605 break;
608 minor = atoi(gl_string_cursor);
609 minor = major*100+minor;
610 major = 10;
612 break;
614 case VENDOR_ATI:
615 major = minor = 0;
616 gl_string_cursor = strchr(gl_string, '-');
617 if (gl_string_cursor) {
618 gl_string_cursor++;
620 /* Check if version number is of the form x.y.z */
621 if ( *gl_string_cursor < '0' || *gl_string_cursor > '9'
622 || *(gl_string_cursor+1) != '.'
623 || *(gl_string_cursor+2) < '0' || *(gl_string_cursor+2) > '9'
624 || *(gl_string_cursor+3) != '.'
625 || *(gl_string_cursor+4) < '0' || *(gl_string_cursor+4) > '9' )
626 /* Mark version number as malformed */
627 gl_string_cursor = 0;
630 if (!gl_string_cursor)
631 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
632 else {
633 major = *gl_string_cursor - '0';
634 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
636 break;
638 case VENDOR_INTEL:
639 /* Apple and Mesa version strings look differently, but both provide intel drivers */
640 if(strstr(gl_string, "APPLE")) {
641 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
642 * We only need the first part, and use the APPLE as identification
643 * "1.2 APPLE-1.4.56"
645 gl_string_cursor = gl_string;
646 major = atoi(gl_string_cursor);
647 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
648 ++gl_string_cursor;
651 if (*gl_string_cursor++ != '.') {
652 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
653 break;
656 minor = atoi(gl_string_cursor);
657 break;
660 case VENDOR_MESA:
661 gl_string_cursor = strstr(gl_string, "Mesa");
662 gl_string_cursor = strstr(gl_string_cursor, " ");
663 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
664 if (*gl_string_cursor) {
665 char tmp[16];
666 int cursor = 0;
668 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
669 tmp[cursor++] = *gl_string_cursor;
670 ++gl_string_cursor;
672 tmp[cursor] = 0;
673 major = atoi(tmp);
675 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
676 ++gl_string_cursor;
678 cursor = 0;
679 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
680 tmp[cursor++] = *gl_string_cursor;
681 ++gl_string_cursor;
683 tmp[cursor] = 0;
684 minor = atoi(tmp);
686 break;
688 default:
689 major = 0;
690 minor = 9;
692 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
693 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
694 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
695 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
696 } else {
697 FIXME("OpenGL driver did not return version information\n");
698 gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
699 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
702 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
705 * Initialize openGL extension related variables
706 * with Default values
708 memset(gl_info->supported, 0, sizeof(gl_info->supported));
709 gl_info->max_buffers = 1;
710 gl_info->max_textures = 1;
711 gl_info->max_texture_stages = 1;
712 gl_info->max_fragment_samplers = 1;
713 gl_info->max_vertex_samplers = 0;
714 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
715 gl_info->max_sampler_stages = 1;
716 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
717 gl_info->ps_arb_max_temps = 0;
718 gl_info->ps_arb_max_instructions = 0;
719 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
720 gl_info->vs_arb_max_temps = 0;
721 gl_info->vs_arb_max_instructions = 0;
722 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
723 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
724 gl_info->vs_glsl_constantsF = 0;
725 gl_info->ps_glsl_constantsF = 0;
726 gl_info->vs_arb_constantsF = 0;
727 gl_info->ps_arb_constantsF = 0;
729 /* Retrieve opengl defaults */
730 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
731 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
732 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
734 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
735 gl_info->max_lights = gl_max;
736 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
738 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
739 gl_info->max_texture_size = gl_max;
740 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
742 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
743 gl_info->max_pointsizemin = gl_floatv[0];
744 gl_info->max_pointsize = gl_floatv[1];
745 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
747 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
748 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
749 TRACE_(d3d_caps)("GL_Extensions reported:\n");
751 if (NULL == GL_Extensions) {
752 ERR(" GL_Extensions returns NULL\n");
753 } else {
754 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
756 while (*GL_Extensions != 0x00) {
757 const char *Start;
758 char ThisExtn[256];
759 size_t len;
761 while (isspace(*GL_Extensions)) GL_Extensions++;
762 Start = GL_Extensions;
763 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
764 GL_Extensions++;
767 len = GL_Extensions - Start;
768 if (len == 0 || len >= sizeof(ThisExtn))
769 continue;
771 memcpy(ThisExtn, Start, len);
772 ThisExtn[len] = '\0';
773 TRACE_(d3d_caps)("- %s\n", ThisExtn);
775 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
776 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
777 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
778 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
779 break;
784 LEAVE_GL();
786 /* Now work out what GL support this card really has */
787 #define USE_GL_FUNC(type, pfn, ext, replace) { \
788 DWORD ver = ver_for_ext(ext); \
789 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
790 else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
791 else gl_info->pfn = NULL; \
793 GL_EXT_FUNCS_GEN;
794 #undef USE_GL_FUNC
796 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
797 WGL_EXT_FUNCS_GEN;
798 #undef USE_GL_FUNC
800 ENTER_GL();
801 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
802 * loading the functions, otherwise the code above will load the extension entry points instead of the
803 * core functions, which may not work
805 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
806 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
807 EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
808 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
809 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
813 if (gl_info->supported[APPLE_FENCE]) {
814 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
815 * The apple extension interacts with some other apple exts. Disable the NV
816 * extension if the apple one is support to prevent confusion in other parts
817 * of the code
819 gl_info->supported[NV_FENCE] = FALSE;
821 if (gl_info->supported[APPLE_FLOAT_PIXELS]) {
822 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
824 * The enums are the same:
825 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
826 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
827 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
828 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
829 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
831 if(!gl_info->supported[ARB_TEXTURE_FLOAT]) {
832 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n");
833 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
835 if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) {
836 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n");
837 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
840 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
841 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
842 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
844 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
845 if(gl_info->supported[NV_REGISTER_COMBINERS]) {
846 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
847 * are supported. The nv extensions provide the same functionality as the
848 * ATI one, and a bit more(signed pixelformats)
850 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
853 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
854 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
855 gl_info->max_buffers = gl_max;
856 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
858 if (gl_info->supported[ARB_MULTITEXTURE]) {
859 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
860 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
861 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
863 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
864 GLint tmp;
865 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
866 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
867 } else {
868 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
870 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
872 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
873 GLint tmp;
874 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
875 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
876 } else {
877 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
879 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
881 if (gl_info->supported[ARB_VERTEX_SHADER]) {
882 GLint tmp;
883 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
884 gl_info->max_vertex_samplers = tmp;
885 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
886 gl_info->max_combined_samplers = tmp;
888 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
889 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
890 * an issue because then the sampler setup only depends on the two shaders. If a pixel
891 * shader is used with fixed function vertex processing we're fine too because fixed function
892 * vertex processing doesn't use any samplers. If fixed function fragment processing is
893 * used we have to make sure that all vertex sampler setups are valid together with all
894 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
895 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
896 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
897 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
898 * a fixed function pipeline anymore.
900 * So this is just a check to check that our assumption holds true. If not, write a warning
901 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
903 if(gl_info->max_vertex_samplers && gl_info->max_combined_samplers < 12 &&
904 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
905 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
906 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
907 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
908 if( gl_info->max_combined_samplers > MAX_TEXTURES )
909 gl_info->max_vertex_samplers =
910 gl_info->max_combined_samplers - MAX_TEXTURES;
911 else
912 gl_info->max_vertex_samplers = 0;
914 } else {
915 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
917 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
918 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
920 if (gl_info->supported[ARB_VERTEX_BLEND]) {
921 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
922 gl_info->max_blends = gl_max;
923 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
925 if (gl_info->supported[EXT_TEXTURE3D]) {
926 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
927 gl_info->max_texture3d_size = gl_max;
928 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
930 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
931 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
932 gl_info->max_anisotropy = gl_max;
933 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
935 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
936 gl_info->ps_arb_version = PS_VERSION_11;
937 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
938 gl_info->ps_arb_constantsF = gl_max;
939 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
940 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
941 gl_info->ps_arb_max_temps = gl_max;
942 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
943 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
944 gl_info->ps_arb_max_instructions = gl_max;
945 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
947 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
948 gl_info->vs_arb_version = VS_VERSION_11;
949 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
950 gl_info->vs_arb_constantsF = gl_max;
951 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
952 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
953 gl_info->vs_arb_max_temps = gl_max;
954 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
955 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
956 gl_info->vs_arb_max_instructions = gl_max;
957 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
959 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
961 if (gl_info->supported[ARB_VERTEX_SHADER]) {
962 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
963 gl_info->vs_glsl_constantsF = gl_max / 4;
964 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
966 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
967 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
968 gl_info->ps_glsl_constantsF = gl_max / 4;
969 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
970 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
971 gl_info->max_glsl_varyings = gl_max;
972 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
974 if (gl_info->supported[EXT_VERTEX_SHADER]) {
975 gl_info->vs_ati_version = VS_VERSION_11;
977 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
978 gl_info->vs_nv_version = VS_VERSION_30;
979 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
980 gl_info->vs_nv_version = VS_VERSION_20;
981 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
982 gl_info->vs_nv_version = VS_VERSION_11;
983 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
984 gl_info->vs_nv_version = VS_VERSION_10;
986 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
987 gl_info->ps_nv_version = PS_VERSION_30;
988 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
989 gl_info->ps_nv_version = PS_VERSION_20;
991 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) {
992 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
993 } else {
994 gl_info->max_shininess = 128.0;
996 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
997 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
998 * This saves a few redundant glDisable calls
1000 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1002 if(gl_info->supported[ATI_FRAGMENT_SHADER]) {
1003 /* Disable NV_register_combiners and fragment shader if this is supported.
1004 * generally the NV extensions are preferred over the ATI ones, and this
1005 * extension is disabled if register_combiners and texture_shader2 are both
1006 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1007 * fragment processing support
1009 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1010 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1011 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1012 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1013 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1015 if(gl_info->supported[NV_HALF_FLOAT]) {
1016 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float */
1017 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
1019 if(gl_info->supported[ARB_POINT_SPRITE]) {
1020 gl_info->max_point_sprite_units = gl_info->max_textures;
1021 } else {
1022 gl_info->max_point_sprite_units = 0;
1025 checkGLcall("extension detection\n");
1027 /* In some cases the number of texture stages can be larger than the number
1028 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1029 * shaders), but 8 texture stages (register combiners). */
1030 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1032 /* We can only use ORM_FBO when the hardware supports it. */
1033 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1034 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to backbuffer offscreen rendering mode.\n");
1035 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
1038 /* MRTs are currently only supported when FBOs are used. */
1039 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1040 gl_info->max_buffers = 1;
1043 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
1044 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
1045 * in case of the latest videocards in the number of pixel/vertex pipelines.
1047 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
1048 * rendering. Various games use this information to get a rough estimation of the features of the card
1049 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
1050 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
1051 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
1052 * not the PCI id.
1054 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
1055 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
1056 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
1057 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
1058 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1059 * is used for rendering which is not always the case). This would work but it is not very portable. Second
1060 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1061 * is limited.
1063 * As said most games only use the PCI id to get an indication of the capabilities of the card.
1064 * It doesn't really matter if the given id is the correct one if we return the id of a card with
1065 * similar 3d features.
1067 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
1068 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1069 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1070 * won't pass we return a default card. This way is better than maintaining a full card database as even
1071 * without a full database we can return a card with similar features. Second the size of the database
1072 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
1073 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
1074 * to distinguishes between different models from that family.
1076 * The code also selects a default amount of video memory which we will use for an estimation of the amount
1077 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
1078 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
1079 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
1080 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
1081 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1082 * memory behind our backs if really needed.
1083 * Note that the amount of video memory can be overruled using a registry setting.
1085 switch (gl_info->gl_vendor) {
1086 case VENDOR_NVIDIA:
1087 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1088 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1090 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1091 /* Geforce 200 - highend */
1092 if(strstr(gl_info->gl_renderer, "GTX 280") ||
1093 strstr(gl_info->gl_renderer, "GTX 285") ||
1094 strstr(gl_info->gl_renderer, "GTX 295"))
1096 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1097 vidmem = 1024;
1099 /* Geforce 200 - midend high */
1100 if(strstr(gl_info->gl_renderer, "GTX 275")) {
1101 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX275;
1102 vidmem = 896;
1104 /* Geforce 200 - midend */
1105 if(strstr(gl_info->gl_renderer, "GTX 260")) {
1106 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX260;
1107 vidmem = 1024;
1109 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1110 else if(strstr(gl_info->gl_renderer, "9800") ||
1111 strstr(gl_info->gl_renderer, "GTS 150") ||
1112 strstr(gl_info->gl_renderer, "GTS 250"))
1114 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1115 vidmem = 512;
1117 /* Geforce9 - midend */
1118 else if(strstr(gl_info->gl_renderer, "9600")) {
1119 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1120 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1122 /* Geforce9 - midend low / Geforce 200 - low*/
1123 else if(strstr(gl_info->gl_renderer, "9500") ||
1124 strstr(gl_info->gl_renderer, "GT 120") ||
1125 strstr(gl_info->gl_renderer, "GT 130"))
1127 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9500GT;
1128 vidmem = 256; /* The 9500GT has 256-1024MB */
1130 /* Geforce9 - lowend */
1131 else if(strstr(gl_info->gl_renderer, "9400")) {
1132 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9400GT;
1133 vidmem = 256; /* The 9400GT has 256-1024MB */
1135 /* Geforce9 - lowend low */
1136 else if(strstr(gl_info->gl_renderer, "9100") ||
1137 strstr(gl_info->gl_renderer, "9200") ||
1138 strstr(gl_info->gl_renderer, "9300") ||
1139 strstr(gl_info->gl_renderer, "G 100"))
1141 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9200;
1142 vidmem = 256; /* The 9100-9300 cards have 256MB */
1144 /* Geforce8 - highend */
1145 else if (strstr(gl_info->gl_renderer, "8800")) {
1146 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1147 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1149 /* Geforce8 - midend mobile */
1150 else if(strstr(gl_info->gl_renderer, "8600 M")) {
1151 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1152 vidmem = 512;
1154 /* Geforce8 - midend */
1155 else if(strstr(gl_info->gl_renderer, "8600") ||
1156 strstr(gl_info->gl_renderer, "8700"))
1158 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1159 vidmem = 256;
1161 /* Geforce8 - lowend */
1162 else if(strstr(gl_info->gl_renderer, "8300") ||
1163 strstr(gl_info->gl_renderer, "8400") ||
1164 strstr(gl_info->gl_renderer, "8500"))
1166 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1167 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1169 /* Geforce7 - highend */
1170 else if(strstr(gl_info->gl_renderer, "7800") ||
1171 strstr(gl_info->gl_renderer, "7900") ||
1172 strstr(gl_info->gl_renderer, "7950") ||
1173 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1174 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1176 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1177 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1179 /* Geforce7 midend */
1180 else if(strstr(gl_info->gl_renderer, "7600") ||
1181 strstr(gl_info->gl_renderer, "7700")) {
1182 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1183 vidmem = 256; /* The 7600 uses 256-512MB */
1184 /* Geforce7 lower medium */
1185 } else if(strstr(gl_info->gl_renderer, "7400")) {
1186 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1187 vidmem = 256; /* The 7400 uses 256-512MB */
1189 /* Geforce7 lowend */
1190 else if(strstr(gl_info->gl_renderer, "7300")) {
1191 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1192 vidmem = 256; /* Mac Pros with this card have 256 MB */
1194 /* Geforce6 highend */
1195 else if(strstr(gl_info->gl_renderer, "6800"))
1197 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1198 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1200 /* Geforce6 - midend */
1201 else if(strstr(gl_info->gl_renderer, "6600") ||
1202 strstr(gl_info->gl_renderer, "6610") ||
1203 strstr(gl_info->gl_renderer, "6700"))
1205 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1206 vidmem = 128; /* A 6600GT has 128-256MB */
1208 /* Geforce6/7 lowend */
1209 else {
1210 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1211 vidmem = 64; /* */
1213 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1214 /* GeforceFX - highend */
1215 if (strstr(gl_info->gl_renderer, "5800") ||
1216 strstr(gl_info->gl_renderer, "5900") ||
1217 strstr(gl_info->gl_renderer, "5950") ||
1218 strstr(gl_info->gl_renderer, "Quadro FX"))
1220 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1221 vidmem = 256; /* 5800-5900 cards use 256MB */
1223 /* GeforceFX - midend */
1224 else if(strstr(gl_info->gl_renderer, "5600") ||
1225 strstr(gl_info->gl_renderer, "5650") ||
1226 strstr(gl_info->gl_renderer, "5700") ||
1227 strstr(gl_info->gl_renderer, "5750"))
1229 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1230 vidmem = 128; /* A 5600 uses 128-256MB */
1232 /* GeforceFX - lowend */
1233 else {
1234 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1235 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1237 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1238 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1239 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1240 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1242 else {
1243 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1244 vidmem = 64; /* Geforce3 cards have 64-128MB */
1246 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1247 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1248 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1249 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1251 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1252 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1253 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1255 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1256 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1257 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1259 else {
1260 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1261 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1263 } else {
1264 if (strstr(gl_info->gl_renderer, "TNT2")) {
1265 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1266 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1268 else {
1269 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1270 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1273 break;
1274 case VENDOR_ATI:
1275 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1277 * beware: renderer string do not match exact card model,
1278 * eg HD 4800 is returned for multiple card, even for RV790 based one
1280 if(WINE_D3D9_CAPABLE(gl_info)) {
1281 /* Radeon R7xx HD4800 - highend */
1282 if (strstr(gl_info->gl_renderer, "HD 4800") || /* Radeon RV7xx HD48xx generic renderer string */
1283 strstr(gl_info->gl_renderer, "HD 4830") || /* Radeon RV770 */
1284 strstr(gl_info->gl_renderer, "HD 4850") || /* Radeon RV770 */
1285 strstr(gl_info->gl_renderer, "HD 4870") || /* Radeon RV770 */
1286 strstr(gl_info->gl_renderer, "HD 4890")) /* Radeon RV790 */
1288 gl_info->gl_card = CARD_ATI_RADEON_HD4800;
1289 vidmem = 512; /* note: HD4890 cards use 1024MB */
1291 /* Radeon R740 HD4700 - midend */
1292 else if (strstr(gl_info->gl_renderer, "HD 4700") || /* Radeon RV770 */
1293 strstr(gl_info->gl_renderer, "HD 4770")) /* Radeon RV740 */
1295 gl_info->gl_card = CARD_ATI_RADEON_HD4700;
1296 vidmem = 512;
1298 /* Radeon R730 HD4600 - midend */
1299 else if (strstr(gl_info->gl_renderer, "HD 4600") || /* Radeon RV730 */
1300 strstr(gl_info->gl_renderer, "HD 4650") || /* Radeon RV730 */
1301 strstr(gl_info->gl_renderer, "HD 4670")) /* Radeon RV730 */
1303 gl_info->gl_card = CARD_ATI_RADEON_HD4600;
1304 vidmem = 512;
1306 /* Radeon R710 HD4500/HD4350 - lowend */
1307 else if (strstr(gl_info->gl_renderer, "HD 4350") || /* Radeon RV710 */
1308 strstr(gl_info->gl_renderer, "HD 4550")) /* Radeon RV710 */
1310 gl_info->gl_card = CARD_ATI_RADEON_HD4350;
1311 vidmem = 256;
1313 /* Radeon R6xx HD2900/HD3800 - highend */
1314 else if (strstr(gl_info->gl_renderer, "HD 2900") ||
1315 strstr(gl_info->gl_renderer, "HD 3870") ||
1316 strstr(gl_info->gl_renderer, "HD 3850"))
1318 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1319 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1321 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1322 else if (strstr(gl_info->gl_renderer, "HD 2600") ||
1323 strstr(gl_info->gl_renderer, "HD 3830") ||
1324 strstr(gl_info->gl_renderer, "HD 3690") ||
1325 strstr(gl_info->gl_renderer, "HD 3650"))
1327 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1328 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1330 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1331 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1332 strstr(gl_info->gl_renderer, "HD 2400") ||
1333 strstr(gl_info->gl_renderer, "HD 3470") ||
1334 strstr(gl_info->gl_renderer, "HD 3450") ||
1335 strstr(gl_info->gl_renderer, "HD 3430"))
1337 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1338 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1340 /* Radeon R6xx/R7xx integrated */
1341 else if (strstr(gl_info->gl_renderer, "HD 3100") ||
1342 strstr(gl_info->gl_renderer, "HD 3200") ||
1343 strstr(gl_info->gl_renderer, "HD 3300"))
1345 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1346 vidmem = 128; /* 128MB */
1348 /* Radeon R5xx */
1349 else if (strstr(gl_info->gl_renderer, "X1600") ||
1350 strstr(gl_info->gl_renderer, "X1650") ||
1351 strstr(gl_info->gl_renderer, "X1800") ||
1352 strstr(gl_info->gl_renderer, "X1900") ||
1353 strstr(gl_info->gl_renderer, "X1950"))
1355 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1356 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1358 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1359 else if(strstr(gl_info->gl_renderer, "X700") ||
1360 strstr(gl_info->gl_renderer, "X800") ||
1361 strstr(gl_info->gl_renderer, "X850") ||
1362 strstr(gl_info->gl_renderer, "X1300") ||
1363 strstr(gl_info->gl_renderer, "X1400") ||
1364 strstr(gl_info->gl_renderer, "X1450") ||
1365 strstr(gl_info->gl_renderer, "X1550"))
1367 gl_info->gl_card = CARD_ATI_RADEON_X700;
1368 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1370 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1371 else if(strstr(gl_info->gl_renderer, "Radeon Xpress"))
1373 gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M;
1374 vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1376 /* Radeon R3xx */
1377 else {
1378 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1379 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1381 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1382 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1383 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1384 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1385 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1386 vidmem = 32; /* There are models with up to 64MB */
1387 } else {
1388 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1389 vidmem = 16; /* There are 16-32MB models */
1391 break;
1392 case VENDOR_INTEL:
1393 if (strstr(gl_info->gl_renderer, "GMA 950") ||
1394 strstr(gl_info->gl_renderer, "945GM")) {
1395 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1396 gl_info->gl_card = CARD_INTEL_I945GM;
1397 vidmem = 64;
1398 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1399 gl_info->gl_card = CARD_INTEL_I915GM;
1400 } else if (strstr(gl_info->gl_renderer, "915G")) {
1401 gl_info->gl_card = CARD_INTEL_I915G;
1402 } else if (strstr(gl_info->gl_renderer, "865G")) {
1403 gl_info->gl_card = CARD_INTEL_I865G;
1404 } else if (strstr(gl_info->gl_renderer, "855G")) {
1405 gl_info->gl_card = CARD_INTEL_I855G;
1406 } else if (strstr(gl_info->gl_renderer, "830G")) {
1407 gl_info->gl_card = CARD_INTEL_I830G;
1408 } else {
1409 gl_info->gl_card = CARD_INTEL_I915G;
1411 break;
1412 case VENDOR_MESA:
1413 case VENDOR_WINE:
1414 default:
1415 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1416 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1417 * them a good generic choice.
1419 gl_info->gl_vendor = VENDOR_NVIDIA;
1420 if(WINE_D3D9_CAPABLE(gl_info))
1421 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1422 else if(WINE_D3D8_CAPABLE(gl_info))
1423 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1424 else if(WINE_D3D7_CAPABLE(gl_info))
1425 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1426 else if(WINE_D3D6_CAPABLE(gl_info))
1427 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1428 else
1429 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1431 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1433 /* If we have an estimate use it, else default to 64MB; */
1434 if(vidmem)
1435 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1436 else
1437 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1439 /* Load all the lookup tables */
1440 for (i = 0; i < MAX_LOOKUPS; i++) {
1441 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1444 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1445 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1446 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1447 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1448 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1449 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1450 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1451 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1452 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1453 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1455 magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
1456 magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
1457 magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
1458 magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1459 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1462 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1463 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
1464 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
1465 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
1466 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1467 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1468 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1469 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1470 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1471 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
1472 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1473 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
1474 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1475 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
1476 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1478 /* TODO: config lookups */
1480 /* Make sure there's an active HDC else the WGL extensions will fail */
1481 hdc = pwglGetCurrentDC();
1482 if (hdc) {
1483 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
1484 if(GL_EXTCALL(wglGetExtensionsStringARB))
1485 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1487 if (NULL == WGL_Extensions) {
1488 ERR(" WGL_Extensions returns NULL\n");
1489 } else {
1490 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1491 while (*WGL_Extensions != 0x00) {
1492 const char *Start;
1493 char ThisExtn[256];
1494 size_t len;
1496 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1497 Start = WGL_Extensions;
1498 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1499 WGL_Extensions++;
1502 len = WGL_Extensions - Start;
1503 if (len == 0 || len >= sizeof(ThisExtn))
1504 continue;
1506 memcpy(ThisExtn, Start, len);
1507 ThisExtn[len] = '\0';
1508 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1510 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1511 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1512 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1514 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
1515 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
1516 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
1518 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1519 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1520 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1525 LEAVE_GL();
1527 return return_value;
1530 /**********************************************************
1531 * IWineD3D implementation follows
1532 **********************************************************/
1534 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1535 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1537 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
1539 return This->adapter_count;
1542 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1543 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1544 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1545 return WINED3D_OK;
1548 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1549 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1551 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1553 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1554 return NULL;
1557 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1560 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1561 of the same bpp but different resolutions */
1563 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1564 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1565 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1566 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1568 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1569 return 0;
1572 /* TODO: Store modes per adapter and read it from the adapter structure */
1573 if (Adapter == 0) { /* Display */
1574 int i = 0;
1575 int j = 0;
1577 if (!DEBUG_SINGLE_MODE) {
1578 DEVMODEW DevModeW;
1580 ZeroMemory(&DevModeW, sizeof(DevModeW));
1581 DevModeW.dmSize = sizeof(DevModeW);
1582 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1583 j++;
1584 switch (Format)
1586 case WINED3DFMT_UNKNOWN:
1587 /* This is for D3D8, do not enumerate P8 here */
1588 if (DevModeW.dmBitsPerPel == 32 ||
1589 DevModeW.dmBitsPerPel == 16) i++;
1590 break;
1591 case WINED3DFMT_X8R8G8B8:
1592 if (DevModeW.dmBitsPerPel == 32) i++;
1593 break;
1594 case WINED3DFMT_R5G6B5:
1595 if (DevModeW.dmBitsPerPel == 16) i++;
1596 break;
1597 case WINED3DFMT_P8:
1598 if (DevModeW.dmBitsPerPel == 8) i++;
1599 break;
1600 default:
1601 /* Skip other modes as they do not match the requested format */
1602 break;
1605 } else {
1606 i = 1;
1607 j = 1;
1610 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1611 return i;
1612 } else {
1613 FIXME_(d3d_caps)("Adapter not primary display\n");
1615 return 0;
1618 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1619 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1620 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1621 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1623 /* Validate the parameters as much as possible */
1624 if (NULL == pMode ||
1625 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1626 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1627 return WINED3DERR_INVALIDCALL;
1630 /* TODO: Store modes per adapter and read it from the adapter structure */
1631 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1632 DEVMODEW DevModeW;
1633 int ModeIdx = 0;
1634 UINT i = 0;
1635 int j = 0;
1637 ZeroMemory(&DevModeW, sizeof(DevModeW));
1638 DevModeW.dmSize = sizeof(DevModeW);
1640 /* If we are filtering to a specific format (D3D9), then need to skip
1641 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1642 just count through the ones with valid bit depths */
1643 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1644 switch (Format)
1646 case WINED3DFMT_UNKNOWN:
1647 /* This is D3D8. Do not enumerate P8 here */
1648 if (DevModeW.dmBitsPerPel == 32 ||
1649 DevModeW.dmBitsPerPel == 16) i++;
1650 break;
1651 case WINED3DFMT_X8R8G8B8:
1652 if (DevModeW.dmBitsPerPel == 32) i++;
1653 break;
1654 case WINED3DFMT_R5G6B5:
1655 if (DevModeW.dmBitsPerPel == 16) i++;
1656 break;
1657 case WINED3DFMT_P8:
1658 if (DevModeW.dmBitsPerPel == 8) i++;
1659 break;
1660 default:
1661 /* Modes that don't match what we support can get an early-out */
1662 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1663 return WINED3DERR_INVALIDCALL;
1667 if (i == 0) {
1668 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1669 return WINED3DERR_INVALIDCALL;
1671 ModeIdx = j - 1;
1673 /* Now get the display mode via the calculated index */
1674 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1675 pMode->Width = DevModeW.dmPelsWidth;
1676 pMode->Height = DevModeW.dmPelsHeight;
1677 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1678 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1679 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1681 if (Format == WINED3DFMT_UNKNOWN) {
1682 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1683 } else {
1684 pMode->Format = Format;
1686 } else {
1687 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1688 return WINED3DERR_INVALIDCALL;
1691 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1692 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1693 DevModeW.dmBitsPerPel);
1695 } else if (DEBUG_SINGLE_MODE) {
1696 /* Return one setting of the format requested */
1697 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1698 pMode->Width = 800;
1699 pMode->Height = 600;
1700 pMode->RefreshRate = 60;
1701 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1702 } else {
1703 FIXME_(d3d_caps)("Adapter not primary display\n");
1706 return WINED3D_OK;
1709 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1710 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1711 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1713 if (NULL == pMode ||
1714 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1715 return WINED3DERR_INVALIDCALL;
1718 if (Adapter == 0) { /* Display */
1719 int bpp = 0;
1720 DEVMODEW DevModeW;
1722 ZeroMemory(&DevModeW, sizeof(DevModeW));
1723 DevModeW.dmSize = sizeof(DevModeW);
1725 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1726 pMode->Width = DevModeW.dmPelsWidth;
1727 pMode->Height = DevModeW.dmPelsHeight;
1728 bpp = DevModeW.dmBitsPerPel;
1729 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1730 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1732 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1735 pMode->Format = pixelformat_for_depth(bpp);
1736 } else {
1737 FIXME_(d3d_caps)("Adapter not primary display\n");
1740 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1741 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1742 return WINED3D_OK;
1745 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1746 and fields being inserted in the middle, a new structure is used in place */
1747 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1748 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1749 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1751 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1753 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1754 return WINED3DERR_INVALIDCALL;
1757 /* Return the information requested */
1758 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1759 strcpy(pIdentifier->Driver, This->adapters[Adapter].driver);
1760 if(This->adapters[Adapter].gl_info.driver_description)
1761 strcpy(pIdentifier->Description, This->adapters[Adapter].gl_info.driver_description);
1762 else /* Copy default description "Direct3D HAL" */
1763 strcpy(pIdentifier->Description, This->adapters[Adapter].description);
1765 /* Note dx8 doesn't supply a DeviceName */
1766 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY1"); /* FIXME: May depend on desktop? */
1767 pIdentifier->DriverVersion->u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
1768 pIdentifier->DriverVersion->u.LowPart = This->adapters[Adapter].gl_info.driver_version;
1769 *(pIdentifier->VendorId) = This->adapters[Adapter].gl_info.gl_vendor;
1770 *(pIdentifier->DeviceId) = This->adapters[Adapter].gl_info.gl_card;
1771 *(pIdentifier->SubSysId) = 0;
1772 *(pIdentifier->Revision) = 0;
1773 *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID;
1775 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1777 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
1778 *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id;
1781 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1783 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
1784 *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id;
1787 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1788 *(pIdentifier->WHQLLevel) = 0;
1789 } else {
1790 *(pIdentifier->WHQLLevel) = 1;
1793 return WINED3D_OK;
1796 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_GL_Info *gl_info,
1797 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
1799 short redSize, greenSize, blueSize, alphaSize, colorBits;
1801 if(!cfg)
1802 return FALSE;
1804 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
1805 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
1807 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
1808 return FALSE;
1811 if(cfg->redSize < redSize)
1812 return FALSE;
1814 if(cfg->greenSize < greenSize)
1815 return FALSE;
1817 if(cfg->blueSize < blueSize)
1818 return FALSE;
1820 if(cfg->alphaSize < alphaSize)
1821 return FALSE;
1823 return TRUE;
1824 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
1825 if (format_desc->format == WINED3DFMT_R16_FLOAT)
1826 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1827 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
1828 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1829 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
1830 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
1831 if (format_desc->format == WINED3DFMT_R32_FLOAT)
1832 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1833 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
1834 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1835 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
1836 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
1837 } else {
1838 /* Probably a color index mode */
1839 return FALSE;
1842 return FALSE;
1845 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_GL_Info *gl_info,
1846 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
1848 short depthSize, stencilSize;
1849 BOOL lockable = FALSE;
1851 if(!cfg)
1852 return FALSE;
1854 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
1856 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
1857 return FALSE;
1860 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32F_LOCKABLE))
1861 lockable = TRUE;
1863 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
1864 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
1865 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
1866 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
1867 return FALSE;
1869 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
1870 * allow more stencil bits than requested. */
1871 if(cfg->stencilSize < stencilSize)
1872 return FALSE;
1874 return TRUE;
1877 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1878 WINED3DFORMAT AdapterFormat,
1879 WINED3DFORMAT RenderTargetFormat,
1880 WINED3DFORMAT DepthStencilFormat) {
1881 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1882 int nCfgs;
1883 const WineD3D_PixelFormat *cfgs;
1884 const struct WineD3DAdapter *adapter;
1885 const struct GlPixelFormatDesc *rt_format_desc;
1886 const struct GlPixelFormatDesc *ds_format_desc;
1887 int it;
1889 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1890 This, Adapter,
1891 DeviceType, debug_d3ddevicetype(DeviceType),
1892 AdapterFormat, debug_d3dformat(AdapterFormat),
1893 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1894 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1896 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1897 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1898 return WINED3DERR_INVALIDCALL;
1901 adapter = &This->adapters[Adapter];
1902 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
1903 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
1904 cfgs = adapter->cfgs;
1905 nCfgs = adapter->nCfgs;
1906 for (it = 0; it < nCfgs; ++it) {
1907 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
1909 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
1911 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1912 return WINED3D_OK;
1916 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1918 return WINED3DERR_NOTAVAILABLE;
1921 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1922 WINED3DFORMAT SurfaceFormat,
1923 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1925 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1926 const struct GlPixelFormatDesc *glDesc;
1927 const struct WineD3DAdapter *adapter;
1929 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1930 This,
1931 Adapter,
1932 DeviceType, debug_d3ddevicetype(DeviceType),
1933 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1934 Windowed,
1935 MultiSampleType,
1936 pQualityLevels);
1938 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1939 return WINED3DERR_INVALIDCALL;
1942 /* TODO: handle Windowed, add more quality levels */
1944 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
1945 if(pQualityLevels) *pQualityLevels = 1;
1946 return WINED3D_OK;
1949 /* By default multisampling is disabled right now as it causes issues
1950 * on some Nvidia driver versions and it doesn't work well in combination
1951 * with FBOs yet. */
1952 if(!wined3d_settings.allow_multisampling)
1953 return WINED3DERR_NOTAVAILABLE;
1955 adapter = &This->adapters[Adapter];
1956 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
1957 if (!glDesc) return WINED3DERR_INVALIDCALL;
1959 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
1960 int i, nCfgs;
1961 const WineD3D_PixelFormat *cfgs;
1963 cfgs = adapter->cfgs;
1964 nCfgs = adapter->nCfgs;
1965 for(i=0; i<nCfgs; i++) {
1966 if(cfgs[i].numSamples != MultiSampleType)
1967 continue;
1969 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
1970 continue;
1972 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1974 if(pQualityLevels)
1975 *pQualityLevels = 1; /* Guess at a value! */
1976 return WINED3D_OK;
1979 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
1980 short redSize, greenSize, blueSize, alphaSize, colorBits;
1981 int i, nCfgs;
1982 const WineD3D_PixelFormat *cfgs;
1984 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
1986 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
1987 return WINED3DERR_NOTAVAILABLE;
1990 cfgs = adapter->cfgs;
1991 nCfgs = adapter->nCfgs;
1992 for(i=0; i<nCfgs; i++) {
1993 if(cfgs[i].numSamples != MultiSampleType)
1994 continue;
1995 if(cfgs[i].redSize != redSize)
1996 continue;
1997 if(cfgs[i].greenSize != greenSize)
1998 continue;
1999 if(cfgs[i].blueSize != blueSize)
2000 continue;
2001 if(cfgs[i].alphaSize != alphaSize)
2002 continue;
2004 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2006 if(pQualityLevels)
2007 *pQualityLevels = 1; /* Guess at a value! */
2008 return WINED3D_OK;
2011 return WINED3DERR_NOTAVAILABLE;
2014 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2015 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
2017 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2018 HRESULT hr = WINED3DERR_NOTAVAILABLE;
2019 UINT nmodes;
2021 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
2022 This,
2023 Adapter,
2024 DeviceType, debug_d3ddevicetype(DeviceType),
2025 DisplayFormat, debug_d3dformat(DisplayFormat),
2026 BackBufferFormat, debug_d3dformat(BackBufferFormat),
2027 Windowed);
2029 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2030 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2031 return WINED3DERR_INVALIDCALL;
2034 /* The task of this function is to check whether a certain display / backbuffer format
2035 * combination is available on the given adapter. In fullscreen mode microsoft specified
2036 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2037 * and display format should match exactly.
2038 * In windowed mode format conversion can occur and this depends on the driver. When format
2039 * conversion is done, this function should nevertheless fail and applications need to use
2040 * CheckDeviceFormatConversion.
2041 * At the moment we assume that fullscreen and windowed have the same capabilities */
2043 /* There are only 4 display formats */
2044 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
2045 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
2046 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
2047 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
2049 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2050 return WINED3DERR_NOTAVAILABLE;
2053 /* If the requested DisplayFormat is not available, don't continue */
2054 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2055 if(!nmodes) {
2056 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2057 return WINED3DERR_NOTAVAILABLE;
2060 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2061 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2062 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2063 return WINED3DERR_NOTAVAILABLE;
2066 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2067 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
2068 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2069 return WINED3DERR_NOTAVAILABLE;
2072 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2073 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
2074 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2075 return WINED3DERR_NOTAVAILABLE;
2078 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2079 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
2080 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2081 return WINED3DERR_NOTAVAILABLE;
2084 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2085 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
2086 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2087 return WINED3DERR_NOTAVAILABLE;
2090 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2091 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2092 if(FAILED(hr))
2093 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2095 return hr;
2099 /* Check if we support bumpmapping for a format */
2100 static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
2101 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2103 const struct fragment_pipeline *fp;
2105 switch(format_desc->format)
2107 case WINED3DFMT_R8G8_SNORM:
2108 case WINED3DFMT_R16G16_SNORM:
2109 case WINED3DFMT_L6V5U5:
2110 case WINED3DFMT_X8L8V8U8:
2111 case WINED3DFMT_R8G8B8A8_SNORM:
2112 /* Ask the fixed function pipeline implementation if it can deal
2113 * with the conversion. If we've got a GL extension giving native
2114 * support this will be an identity conversion. */
2115 fp = select_fragment_implementation(adapter, DeviceType);
2116 if (fp->color_fixup_supported(format_desc->color_fixup))
2118 TRACE_(d3d_caps)("[OK]\n");
2119 return TRUE;
2121 TRACE_(d3d_caps)("[FAILED]\n");
2122 return FALSE;
2124 default:
2125 TRACE_(d3d_caps)("[FAILED]\n");
2126 return FALSE;
2130 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2131 static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
2132 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2134 int it=0;
2136 /* Only allow depth/stencil formats */
2137 if (!(ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) return FALSE;
2139 /* Walk through all WGL pixel formats to find a match */
2140 for (it = 0; it < adapter->nCfgs; ++it)
2142 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2143 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2145 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2147 return TRUE;
2152 return FALSE;
2155 static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2157 /* The flags entry of a format contains the filtering capability */
2158 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2160 return FALSE;
2163 /* Check the render target capabilities of a format */
2164 static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
2165 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2167 /* Filter out non-RT formats */
2168 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2170 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2171 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2172 int it;
2173 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2174 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2176 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2177 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2179 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2180 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2181 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2182 TRACE_(d3d_caps)("[FAILED]\n");
2183 return FALSE;
2186 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2187 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2188 for (it = 0; it < adapter->nCfgs; ++it)
2190 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2191 &cfgs[it], check_format_desc))
2193 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2194 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2195 return TRUE;
2198 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2199 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2200 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2201 int it;
2203 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2204 for (it = 0; it < adapter->nCfgs; ++it)
2206 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2207 &cfgs[it], check_format_desc))
2209 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2210 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2211 return TRUE;
2214 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2215 /* For now return TRUE for FBOs until we have some proper checks.
2216 * Note that this function will only be called when the format is around for texturing. */
2217 return TRUE;
2219 return FALSE;
2222 static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2224 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2226 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2227 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2228 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2229 return FALSE;
2232 switch (format_desc->format)
2234 case WINED3DFMT_A8R8G8B8:
2235 case WINED3DFMT_X8R8G8B8:
2236 case WINED3DFMT_A4R4G4B4:
2237 case WINED3DFMT_L8:
2238 case WINED3DFMT_A8L8:
2239 case WINED3DFMT_DXT1:
2240 case WINED3DFMT_DXT2:
2241 case WINED3DFMT_DXT3:
2242 case WINED3DFMT_DXT4:
2243 case WINED3DFMT_DXT5:
2244 TRACE_(d3d_caps)("[OK]\n");
2245 return TRUE;
2247 default:
2248 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2249 return FALSE;
2251 return FALSE;
2254 static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
2255 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2257 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2258 * doing the color fixup in shaders.
2259 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2260 if ((format_desc->format == WINED3DFMT_X8R8G8B8) || (format_desc->format == WINED3DFMT_A8R8G8B8))
2262 int vs_selected_mode;
2263 int ps_selected_mode;
2264 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2266 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2267 TRACE_(d3d_caps)("[OK]\n");
2268 return TRUE;
2272 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2273 return FALSE;
2276 /* Check if a format support blending in combination with pixel shaders */
2277 static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter,
2278 const struct GlPixelFormatDesc *format_desc)
2280 /* The flags entry of a format contains the post pixel shader blending capability */
2281 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2283 return FALSE;
2286 static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2288 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2289 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2290 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2291 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2292 * capability anyway.
2294 * For now lets report this on all formats, but in the future we may want to
2295 * restrict it to some should games need that
2297 return TRUE;
2300 /* Check if a texture format is supported on the given adapter */
2301 static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
2302 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2304 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2305 const shader_backend_t *shader_backend;
2306 const struct fragment_pipeline *fp;
2308 switch (format_desc->format)
2310 /*****
2311 * supported: RGB(A) formats
2313 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2314 case WINED3DFMT_A8R8G8B8:
2315 case WINED3DFMT_X8R8G8B8:
2316 case WINED3DFMT_R5G6B5:
2317 case WINED3DFMT_X1R5G5B5:
2318 case WINED3DFMT_A1R5G5B5:
2319 case WINED3DFMT_A4R4G4B4:
2320 case WINED3DFMT_A8_UNORM:
2321 case WINED3DFMT_X4R4G4B4:
2322 case WINED3DFMT_R8G8B8A8_UNORM:
2323 case WINED3DFMT_X8B8G8R8:
2324 case WINED3DFMT_A2R10G10B10:
2325 case WINED3DFMT_R10G10B10A2_UNORM:
2326 case WINED3DFMT_R16G16_UNORM:
2327 TRACE_(d3d_caps)("[OK]\n");
2328 return TRUE;
2330 case WINED3DFMT_R3G3B2:
2331 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2332 return FALSE;
2334 /*****
2335 * supported: Palettized
2337 case WINED3DFMT_P8:
2338 TRACE_(d3d_caps)("[OK]\n");
2339 return TRUE;
2340 /* No Windows driver offers A8P8, so don't offer it either */
2341 case WINED3DFMT_A8P8:
2342 return FALSE;
2344 /*****
2345 * Supported: (Alpha)-Luminance
2347 case WINED3DFMT_L8:
2348 case WINED3DFMT_A8L8:
2349 case WINED3DFMT_L16:
2350 TRACE_(d3d_caps)("[OK]\n");
2351 return TRUE;
2353 /* Not supported on Windows, thus disabled */
2354 case WINED3DFMT_A4L4:
2355 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2356 return FALSE;
2358 /*****
2359 * Supported: Depth/Stencil formats
2361 case WINED3DFMT_D16_LOCKABLE:
2362 case WINED3DFMT_D16_UNORM:
2363 case WINED3DFMT_D15S1:
2364 case WINED3DFMT_D24X8:
2365 case WINED3DFMT_D24X4S4:
2366 case WINED3DFMT_D24S8:
2367 case WINED3DFMT_D24FS8:
2368 case WINED3DFMT_D32:
2369 case WINED3DFMT_D32F_LOCKABLE:
2370 return TRUE;
2372 /*****
2373 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2374 * GL_NV_texture_shader). Emulated by shaders
2376 case WINED3DFMT_R8G8_SNORM:
2377 case WINED3DFMT_X8L8V8U8:
2378 case WINED3DFMT_L6V5U5:
2379 case WINED3DFMT_R8G8B8A8_SNORM:
2380 case WINED3DFMT_R16G16_SNORM:
2381 /* Ask the shader backend if it can deal with the conversion. If
2382 * we've got a GL extension giving native support this will be an
2383 * identity conversion. */
2384 shader_backend = select_shader_backend(adapter, DeviceType);
2385 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
2387 TRACE_(d3d_caps)("[OK]\n");
2388 return TRUE;
2390 TRACE_(d3d_caps)("[FAILED]\n");
2391 return FALSE;
2393 case WINED3DFMT_DXT1:
2394 case WINED3DFMT_DXT2:
2395 case WINED3DFMT_DXT3:
2396 case WINED3DFMT_DXT4:
2397 case WINED3DFMT_DXT5:
2398 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2399 TRACE_(d3d_caps)("[OK]\n");
2400 return TRUE;
2402 TRACE_(d3d_caps)("[FAILED]\n");
2403 return FALSE;
2406 /*****
2407 * Odd formats - not supported
2409 case WINED3DFMT_VERTEXDATA:
2410 case WINED3DFMT_R16_UINT:
2411 case WINED3DFMT_R32_UINT:
2412 case WINED3DFMT_R16G16B16A16_SNORM:
2413 case WINED3DFMT_A2W10V10U10:
2414 case WINED3DFMT_W11V11U10:
2415 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2416 return FALSE;
2418 /*****
2419 * WINED3DFMT_CxV8U8: Not supported right now
2421 case WINED3DFMT_CxV8U8:
2422 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2423 return FALSE;
2425 /* YUV formats */
2426 case WINED3DFMT_UYVY:
2427 case WINED3DFMT_YUY2:
2428 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2429 TRACE_(d3d_caps)("[OK]\n");
2430 return TRUE;
2432 TRACE_(d3d_caps)("[FAILED]\n");
2433 return FALSE;
2434 case WINED3DFMT_YV12:
2435 TRACE_(d3d_caps)("[FAILED]\n");
2436 return FALSE;
2438 /* Not supported */
2439 case WINED3DFMT_R16G16B16A16_UNORM:
2440 case WINED3DFMT_A8R3G3B2:
2441 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2442 return FALSE;
2444 /* Floating point formats */
2445 case WINED3DFMT_R16_FLOAT:
2446 case WINED3DFMT_R16G16_FLOAT:
2447 case WINED3DFMT_R16G16B16A16_FLOAT:
2448 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2449 TRACE_(d3d_caps)("[OK]\n");
2450 return TRUE;
2452 TRACE_(d3d_caps)("[FAILED]\n");
2453 return FALSE;
2455 case WINED3DFMT_R32_FLOAT:
2456 case WINED3DFMT_R32G32_FLOAT:
2457 case WINED3DFMT_R32G32B32A32_FLOAT:
2458 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2459 TRACE_(d3d_caps)("[OK]\n");
2460 return TRUE;
2462 TRACE_(d3d_caps)("[FAILED]\n");
2463 return FALSE;
2465 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2466 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2467 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2468 * We can do instancing with all shader versions, but we need vertex shaders.
2470 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2471 * to enable instancing. WineD3D doesn't need that and just ignores it.
2473 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2475 case WINEMAKEFOURCC('I','N','S','T'):
2476 TRACE("ATI Instancing check hack\n");
2477 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2478 TRACE_(d3d_caps)("[OK]\n");
2479 return TRUE;
2481 TRACE_(d3d_caps)("[FAILED]\n");
2482 return FALSE;
2484 /* Some weird FOURCC formats */
2485 case WINED3DFMT_R8G8_B8G8:
2486 case WINED3DFMT_G8R8_G8B8:
2487 case WINED3DFMT_MULTI2_ARGB8:
2488 TRACE_(d3d_caps)("[FAILED]\n");
2489 return FALSE;
2491 /* Vendor specific formats */
2492 case WINED3DFMT_ATI2N:
2493 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2494 shader_backend = select_shader_backend(adapter, DeviceType);
2495 fp = select_fragment_implementation(adapter, DeviceType);
2496 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
2497 && fp->color_fixup_supported(format_desc->color_fixup))
2499 TRACE_(d3d_caps)("[OK]\n");
2500 return TRUE;
2503 TRACE_(d3d_caps)("[OK]\n");
2504 return TRUE;
2506 TRACE_(d3d_caps)("[FAILED]\n");
2507 return FALSE;
2509 case WINED3DFMT_NVHU:
2510 case WINED3DFMT_NVHS:
2511 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2512 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2513 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2514 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2515 * Applications have to deal with not having NVHS and NVHU.
2517 TRACE_(d3d_caps)("[FAILED]\n");
2518 return FALSE;
2520 case WINED3DFMT_UNKNOWN:
2521 return FALSE;
2523 default:
2524 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
2525 break;
2527 return FALSE;
2530 static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
2531 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
2533 const struct blit_shader *blitter;
2535 if(SurfaceType == SURFACE_GDI) {
2536 switch(check_format_desc->format)
2538 case WINED3DFMT_R8G8B8:
2539 case WINED3DFMT_A8R8G8B8:
2540 case WINED3DFMT_X8R8G8B8:
2541 case WINED3DFMT_R5G6B5:
2542 case WINED3DFMT_X1R5G5B5:
2543 case WINED3DFMT_A1R5G5B5:
2544 case WINED3DFMT_A4R4G4B4:
2545 case WINED3DFMT_R3G3B2:
2546 case WINED3DFMT_A8_UNORM:
2547 case WINED3DFMT_A8R3G3B2:
2548 case WINED3DFMT_X4R4G4B4:
2549 case WINED3DFMT_R10G10B10A2_UNORM:
2550 case WINED3DFMT_R8G8B8A8_UNORM:
2551 case WINED3DFMT_X8B8G8R8:
2552 case WINED3DFMT_R16G16_UNORM:
2553 case WINED3DFMT_A2R10G10B10:
2554 case WINED3DFMT_R16G16B16A16_UNORM:
2555 case WINED3DFMT_P8:
2556 TRACE_(d3d_caps)("[OK]\n");
2557 return TRUE;
2558 default:
2559 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
2560 return FALSE;
2564 /* All format that are supported for textures are supported for surfaces as well */
2565 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
2566 /* All depth stencil formats are supported on surfaces */
2567 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
2569 /* If opengl can't process the format natively, the blitter may be able to convert it */
2570 blitter = select_blit_implementation(adapter, DeviceType);
2571 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
2573 TRACE_(d3d_caps)("[OK]\n");
2574 return TRUE;
2577 /* Reject other formats */
2578 TRACE_(d3d_caps)("[FAILED]\n");
2579 return FALSE;
2582 static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2584 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2586 if (!GL_LIMITS(vertex_samplers)) {
2587 TRACE_(d3d_caps)("[FAILED]\n");
2588 return FALSE;
2591 switch (format_desc->format)
2593 case WINED3DFMT_R32G32B32A32_FLOAT:
2594 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2595 TRACE_(d3d_caps)("[FAILED]\n");
2596 return FALSE;
2598 TRACE_(d3d_caps)("[OK]\n");
2599 return TRUE;
2601 default:
2602 TRACE_(d3d_caps)("[FAILED]\n");
2603 return FALSE;
2605 return FALSE;
2608 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2609 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
2610 WINED3DSURFTYPE SurfaceType) {
2611 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2612 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
2613 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2614 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
2615 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
2616 DWORD UsageCaps = 0;
2618 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
2619 This,
2620 Adapter,
2621 DeviceType, debug_d3ddevicetype(DeviceType),
2622 AdapterFormat, debug_d3dformat(AdapterFormat),
2623 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
2624 RType, debug_d3dresourcetype(RType),
2625 CheckFormat, debug_d3dformat(CheckFormat));
2627 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2628 return WINED3DERR_INVALIDCALL;
2631 if(RType == WINED3DRTYPE_CUBETEXTURE) {
2633 if(SurfaceType != SURFACE_OPENGL) {
2634 TRACE("[FAILED]\n");
2635 return WINED3DERR_NOTAVAILABLE;
2638 /* Cubetexture allows:
2639 * - D3DUSAGE_AUTOGENMIPMAP
2640 * - D3DUSAGE_DEPTHSTENCIL
2641 * - D3DUSAGE_DYNAMIC
2642 * - D3DUSAGE_NONSECURE (d3d9ex)
2643 * - D3DUSAGE_RENDERTARGET
2644 * - D3DUSAGE_SOFTWAREPROCESSING
2645 * - D3DUSAGE_QUERY_WRAPANDMIP
2647 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2648 /* Check if the texture format is around */
2649 if (CheckTextureCapability(adapter, DeviceType, format_desc))
2651 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2652 /* Check for automatic mipmap generation support */
2653 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2654 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2655 } else {
2656 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2657 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2661 /* Always report dynamic locking */
2662 if(Usage & WINED3DUSAGE_DYNAMIC)
2663 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2665 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2666 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
2668 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2669 } else {
2670 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2671 return WINED3DERR_NOTAVAILABLE;
2675 /* Always report software processing */
2676 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2677 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2679 /* Check QUERY_FILTER support */
2680 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2681 if (CheckFilterCapability(adapter, format_desc))
2683 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2684 } else {
2685 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2686 return WINED3DERR_NOTAVAILABLE;
2690 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2691 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2692 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
2694 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2695 } else {
2696 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2697 return WINED3DERR_NOTAVAILABLE;
2701 /* Check QUERY_SRGBREAD support */
2702 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2703 if (CheckSrgbReadCapability(adapter, format_desc))
2705 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2706 } else {
2707 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2708 return WINED3DERR_NOTAVAILABLE;
2712 /* Check QUERY_SRGBWRITE support */
2713 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2714 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
2716 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2717 } else {
2718 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2719 return WINED3DERR_NOTAVAILABLE;
2723 /* Check QUERY_VERTEXTEXTURE support */
2724 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2725 if (CheckVertexTextureCapability(adapter, format_desc))
2727 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2728 } else {
2729 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2730 return WINED3DERR_NOTAVAILABLE;
2734 /* Check QUERY_WRAPANDMIP support */
2735 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2736 if (CheckWrapAndMipCapability(adapter, format_desc))
2738 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2739 } else {
2740 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2741 return WINED3DERR_NOTAVAILABLE;
2744 } else {
2745 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
2746 return WINED3DERR_NOTAVAILABLE;
2748 } else {
2749 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
2750 return WINED3DERR_NOTAVAILABLE;
2752 } else if(RType == WINED3DRTYPE_SURFACE) {
2753 /* Surface allows:
2754 * - D3DUSAGE_DEPTHSTENCIL
2755 * - D3DUSAGE_NONSECURE (d3d9ex)
2756 * - D3DUSAGE_RENDERTARGET
2759 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
2761 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2762 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
2764 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2765 } else {
2766 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
2767 return WINED3DERR_NOTAVAILABLE;
2771 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2772 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
2774 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2775 } else {
2776 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2777 return WINED3DERR_NOTAVAILABLE;
2781 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2782 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2783 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
2785 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2786 } else {
2787 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2788 return WINED3DERR_NOTAVAILABLE;
2791 } else {
2792 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
2793 return WINED3DERR_NOTAVAILABLE;
2796 } else if(RType == WINED3DRTYPE_TEXTURE) {
2797 /* Texture allows:
2798 * - D3DUSAGE_AUTOGENMIPMAP
2799 * - D3DUSAGE_DEPTHSTENCIL
2800 * - D3DUSAGE_DMAP
2801 * - D3DUSAGE_DYNAMIC
2802 * - D3DUSAGE_NONSECURE (d3d9ex)
2803 * - D3DUSAGE_RENDERTARGET
2804 * - D3DUSAGE_SOFTWAREPROCESSING
2805 * - D3DUSAGE_TEXTAPI (d3d9ex)
2806 * - D3DUSAGE_QUERY_WRAPANDMIP
2809 if(SurfaceType != SURFACE_OPENGL) {
2810 TRACE("[FAILED]\n");
2811 return WINED3DERR_NOTAVAILABLE;
2814 /* Check if the texture format is around */
2815 if (CheckTextureCapability(adapter, DeviceType, format_desc))
2817 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2818 /* Check for automatic mipmap generation support */
2819 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2820 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2821 } else {
2822 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2823 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2827 /* Always report dynamic locking */
2828 if(Usage & WINED3DUSAGE_DYNAMIC)
2829 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2831 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2832 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
2834 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2835 } else {
2836 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2837 return WINED3DERR_NOTAVAILABLE;
2841 /* Always report software processing */
2842 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2843 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2845 /* Check QUERY_FILTER support */
2846 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2847 if (CheckFilterCapability(adapter, format_desc))
2849 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2850 } else {
2851 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2852 return WINED3DERR_NOTAVAILABLE;
2856 /* Check QUERY_LEGACYBUMPMAP support */
2857 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
2858 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
2860 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
2861 } else {
2862 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
2863 return WINED3DERR_NOTAVAILABLE;
2867 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2868 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2869 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
2871 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2872 } else {
2873 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2874 return WINED3DERR_NOTAVAILABLE;
2878 /* Check QUERY_SRGBREAD support */
2879 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2880 if (CheckSrgbReadCapability(adapter, format_desc))
2882 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2883 } else {
2884 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2885 return WINED3DERR_NOTAVAILABLE;
2889 /* Check QUERY_SRGBWRITE support */
2890 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2891 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
2893 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2894 } else {
2895 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2896 return WINED3DERR_NOTAVAILABLE;
2900 /* Check QUERY_VERTEXTEXTURE support */
2901 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2902 if (CheckVertexTextureCapability(adapter, format_desc))
2904 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2905 } else {
2906 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2907 return WINED3DERR_NOTAVAILABLE;
2911 /* Check QUERY_WRAPANDMIP support */
2912 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2913 if (CheckWrapAndMipCapability(adapter, format_desc))
2915 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2916 } else {
2917 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2918 return WINED3DERR_NOTAVAILABLE;
2922 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2923 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
2925 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2926 } else {
2927 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
2928 return WINED3DERR_NOTAVAILABLE;
2931 } else {
2932 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
2933 return WINED3DERR_NOTAVAILABLE;
2935 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
2936 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
2937 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
2939 * Volumetexture allows:
2940 * - D3DUSAGE_DYNAMIC
2941 * - D3DUSAGE_NONSECURE (d3d9ex)
2942 * - D3DUSAGE_SOFTWAREPROCESSING
2943 * - D3DUSAGE_QUERY_WRAPANDMIP
2946 if(SurfaceType != SURFACE_OPENGL) {
2947 TRACE("[FAILED]\n");
2948 return WINED3DERR_NOTAVAILABLE;
2951 /* Check volume texture and volume usage caps */
2952 if(GL_SUPPORT(EXT_TEXTURE3D)) {
2953 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
2955 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
2956 return WINED3DERR_NOTAVAILABLE;
2959 /* Always report dynamic locking */
2960 if(Usage & WINED3DUSAGE_DYNAMIC)
2961 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2963 /* Always report software processing */
2964 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2965 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2967 /* Check QUERY_FILTER support */
2968 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2969 if (CheckFilterCapability(adapter, format_desc))
2971 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2972 } else {
2973 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2974 return WINED3DERR_NOTAVAILABLE;
2978 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2979 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2980 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
2982 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2983 } else {
2984 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2985 return WINED3DERR_NOTAVAILABLE;
2989 /* Check QUERY_SRGBREAD support */
2990 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2991 if (CheckSrgbReadCapability(adapter, format_desc))
2993 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2994 } else {
2995 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2996 return WINED3DERR_NOTAVAILABLE;
3000 /* Check QUERY_SRGBWRITE support */
3001 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3002 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3004 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3005 } else {
3006 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3007 return WINED3DERR_NOTAVAILABLE;
3011 /* Check QUERY_VERTEXTEXTURE support */
3012 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3013 if (CheckVertexTextureCapability(adapter, format_desc))
3015 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3016 } else {
3017 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3018 return WINED3DERR_NOTAVAILABLE;
3022 /* Check QUERY_WRAPANDMIP support */
3023 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3024 if (CheckWrapAndMipCapability(adapter, format_desc))
3026 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3027 } else {
3028 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3029 return WINED3DERR_NOTAVAILABLE;
3032 } else {
3033 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3034 return WINED3DERR_NOTAVAILABLE;
3037 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3038 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3039 * app needing one of those formats, don't advertize them to avoid leading apps into
3040 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3041 * except of R32F.
3043 switch(CheckFormat) {
3044 case WINED3DFMT_P8:
3045 case WINED3DFMT_A4L4:
3046 case WINED3DFMT_R32_FLOAT:
3047 case WINED3DFMT_R16_FLOAT:
3048 case WINED3DFMT_X8L8V8U8:
3049 case WINED3DFMT_L6V5U5:
3050 case WINED3DFMT_R16G16_UNORM:
3051 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3052 return WINED3DERR_NOTAVAILABLE;
3054 case WINED3DFMT_R8G8B8A8_SNORM:
3055 case WINED3DFMT_R16G16_SNORM:
3056 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3057 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3058 return WINED3DERR_NOTAVAILABLE;
3060 break;
3062 case WINED3DFMT_R8G8_SNORM:
3063 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3064 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3065 return WINED3DERR_NOTAVAILABLE;
3067 break;
3069 case WINED3DFMT_DXT1:
3070 case WINED3DFMT_DXT2:
3071 case WINED3DFMT_DXT3:
3072 case WINED3DFMT_DXT4:
3073 case WINED3DFMT_DXT5:
3074 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3075 * compressed texture results in an error. While the D3D refrast does
3076 * support s3tc volumes, at least the nvidia windows driver does not, so
3077 * we're free not to support this format.
3079 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3080 return WINED3DERR_NOTAVAILABLE;
3082 default:
3083 /* Do nothing, continue with checking the format below */
3084 break;
3086 } else if(RType == WINED3DRTYPE_BUFFER){
3087 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3088 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3089 return WINED3DERR_NOTAVAILABLE;
3092 /* This format is nothing special and it is supported perfectly.
3093 * However, ati and nvidia driver on windows do not mark this format as
3094 * supported (tested with the dxCapsViewer) and pretending to
3095 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
3096 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
3097 * Enable it on dx7. It will need additional checking on dx10 when we support it.
3099 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
3100 TRACE_(d3d_caps)("[FAILED]\n");
3101 return WINED3DERR_NOTAVAILABLE;
3104 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3105 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3106 * usage flags match. */
3107 if(UsageCaps == Usage) {
3108 return WINED3D_OK;
3109 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3110 return WINED3DOK_NOAUTOGEN;
3111 } else {
3112 TRACE_(d3d_caps)("[FAILED] - Usage=%#08x requested for CheckFormat=%s and RType=%d but only %#08x is available\n", Usage, debug_d3dformat(CheckFormat), RType, UsageCaps);
3113 return WINED3DERR_NOTAVAILABLE;
3117 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3118 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3119 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3121 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3122 This,
3123 Adapter,
3124 DeviceType, debug_d3ddevicetype(DeviceType),
3125 SourceFormat, debug_d3dformat(SourceFormat),
3126 TargetFormat, debug_d3dformat(TargetFormat));
3127 return WINED3D_OK;
3130 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3132 const shader_backend_t *ret;
3133 int vs_selected_mode;
3134 int ps_selected_mode;
3136 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3137 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3138 ret = &glsl_shader_backend;
3139 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3140 ret = &arb_program_shader_backend;
3141 } else {
3142 ret = &none_shader_backend;
3144 return ret;
3147 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
3148 WINED3DDEVTYPE DeviceType)
3150 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3151 int vs_selected_mode;
3152 int ps_selected_mode;
3154 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3155 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3156 return &arbfp_fragment_pipeline;
3157 } else if(ps_selected_mode == SHADER_ATI) {
3158 return &atifs_fragment_pipeline;
3159 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3160 return &nvts_fragment_pipeline;
3161 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3162 return &nvrc_fragment_pipeline;
3163 } else {
3164 return &ffp_fragment_pipeline;
3168 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3170 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3171 int vs_selected_mode;
3172 int ps_selected_mode;
3174 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3175 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3176 return &arbfp_blit;
3177 } else {
3178 return &ffp_blit;
3182 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3183 subset of a D3DCAPS9 structure. However, it has to come via a void *
3184 as the d3d8 interface cannot import the d3d9 header */
3185 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3187 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3188 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3189 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3190 int vs_selected_mode;
3191 int ps_selected_mode;
3192 struct shader_caps shader_caps;
3193 struct fragment_caps fragment_caps;
3194 const shader_backend_t *shader_backend;
3195 const struct fragment_pipeline *frag_pipeline = NULL;
3196 DWORD ckey_caps, blit_caps, fx_caps;
3198 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3200 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3201 return WINED3DERR_INVALIDCALL;
3204 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3206 /* This function should *not* be modifying GL caps
3207 * TODO: move the functionality where it belongs */
3208 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
3210 /* ------------------------------------------------
3211 The following fields apply to both d3d8 and d3d9
3212 ------------------------------------------------ */
3213 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3214 pCaps->AdapterOrdinal = Adapter;
3216 pCaps->Caps = 0;
3217 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3218 WINED3DCAPS2_FULLSCREENGAMMA |
3219 WINED3DCAPS2_DYNAMICTEXTURES;
3220 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3221 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3224 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3225 WINED3DCAPS3_COPY_TO_VIDMEM |
3226 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3228 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3229 WINED3DPRESENT_INTERVAL_ONE;
3231 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3232 WINED3DCURSORCAPS_LOWRES;
3234 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3235 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3236 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3237 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3238 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3239 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3240 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3241 WINED3DDEVCAPS_PUREDEVICE |
3242 WINED3DDEVCAPS_HWRASTERIZATION |
3243 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3244 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3245 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3246 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3247 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3248 WINED3DDEVCAPS_RTPATCHES;
3250 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3251 WINED3DPMISCCAPS_CULLCCW |
3252 WINED3DPMISCCAPS_CULLCW |
3253 WINED3DPMISCCAPS_COLORWRITEENABLE |
3254 WINED3DPMISCCAPS_CLIPTLVERTS |
3255 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3256 WINED3DPMISCCAPS_MASKZ |
3257 WINED3DPMISCCAPS_BLENDOP |
3258 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3259 /* TODO:
3260 WINED3DPMISCCAPS_NULLREFERENCE
3261 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3262 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3263 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3264 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3266 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3267 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3269 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3270 WINED3DPRASTERCAPS_PAT |
3271 WINED3DPRASTERCAPS_WFOG |
3272 WINED3DPRASTERCAPS_ZFOG |
3273 WINED3DPRASTERCAPS_FOGVERTEX |
3274 WINED3DPRASTERCAPS_FOGTABLE |
3275 WINED3DPRASTERCAPS_STIPPLE |
3276 WINED3DPRASTERCAPS_SUBPIXEL |
3277 WINED3DPRASTERCAPS_ZTEST |
3278 WINED3DPRASTERCAPS_SCISSORTEST |
3279 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3280 WINED3DPRASTERCAPS_DEPTHBIAS;
3282 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3283 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3284 WINED3DPRASTERCAPS_ZBIAS |
3285 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3287 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3288 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3290 /* FIXME Add:
3291 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3292 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3293 WINED3DPRASTERCAPS_ANTIALIASEDGES
3294 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3295 WINED3DPRASTERCAPS_WBUFFER */
3297 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3298 WINED3DPCMPCAPS_EQUAL |
3299 WINED3DPCMPCAPS_GREATER |
3300 WINED3DPCMPCAPS_GREATEREQUAL |
3301 WINED3DPCMPCAPS_LESS |
3302 WINED3DPCMPCAPS_LESSEQUAL |
3303 WINED3DPCMPCAPS_NEVER |
3304 WINED3DPCMPCAPS_NOTEQUAL;
3306 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3307 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3308 WINED3DPBLENDCAPS_DESTALPHA |
3309 WINED3DPBLENDCAPS_DESTCOLOR |
3310 WINED3DPBLENDCAPS_INVDESTALPHA |
3311 WINED3DPBLENDCAPS_INVDESTCOLOR |
3312 WINED3DPBLENDCAPS_INVSRCALPHA |
3313 WINED3DPBLENDCAPS_INVSRCCOLOR |
3314 WINED3DPBLENDCAPS_ONE |
3315 WINED3DPBLENDCAPS_SRCALPHA |
3316 WINED3DPBLENDCAPS_SRCALPHASAT |
3317 WINED3DPBLENDCAPS_SRCCOLOR |
3318 WINED3DPBLENDCAPS_ZERO;
3320 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3321 WINED3DPBLENDCAPS_DESTCOLOR |
3322 WINED3DPBLENDCAPS_INVDESTALPHA |
3323 WINED3DPBLENDCAPS_INVDESTCOLOR |
3324 WINED3DPBLENDCAPS_INVSRCALPHA |
3325 WINED3DPBLENDCAPS_INVSRCCOLOR |
3326 WINED3DPBLENDCAPS_ONE |
3327 WINED3DPBLENDCAPS_SRCALPHA |
3328 WINED3DPBLENDCAPS_SRCCOLOR |
3329 WINED3DPBLENDCAPS_ZERO;
3330 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3331 * according to the glBlendFunc manpage
3333 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3334 * legacy settings for srcblend only
3337 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3338 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3339 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3343 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3344 WINED3DPCMPCAPS_EQUAL |
3345 WINED3DPCMPCAPS_GREATER |
3346 WINED3DPCMPCAPS_GREATEREQUAL |
3347 WINED3DPCMPCAPS_LESS |
3348 WINED3DPCMPCAPS_LESSEQUAL |
3349 WINED3DPCMPCAPS_NEVER |
3350 WINED3DPCMPCAPS_NOTEQUAL;
3352 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3353 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3354 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3355 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3356 WINED3DPSHADECAPS_COLORFLATRGB |
3357 WINED3DPSHADECAPS_FOGFLAT |
3358 WINED3DPSHADECAPS_FOGGOURAUD |
3359 WINED3DPSHADECAPS_SPECULARFLATRGB;
3361 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3362 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3363 WINED3DPTEXTURECAPS_TRANSPARENCY |
3364 WINED3DPTEXTURECAPS_BORDER |
3365 WINED3DPTEXTURECAPS_MIPMAP |
3366 WINED3DPTEXTURECAPS_PROJECTED |
3367 WINED3DPTEXTURECAPS_PERSPECTIVE;
3369 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3370 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3371 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3374 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3375 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3376 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3377 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3380 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3381 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3382 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3383 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3387 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3388 WINED3DPTFILTERCAPS_MAGFPOINT |
3389 WINED3DPTFILTERCAPS_MINFLINEAR |
3390 WINED3DPTFILTERCAPS_MINFPOINT |
3391 WINED3DPTFILTERCAPS_MIPFLINEAR |
3392 WINED3DPTFILTERCAPS_MIPFPOINT |
3393 WINED3DPTFILTERCAPS_LINEAR |
3394 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3395 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3396 WINED3DPTFILTERCAPS_MIPLINEAR |
3397 WINED3DPTFILTERCAPS_MIPNEAREST |
3398 WINED3DPTFILTERCAPS_NEAREST;
3400 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3401 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3402 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3405 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3406 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3407 WINED3DPTFILTERCAPS_MAGFPOINT |
3408 WINED3DPTFILTERCAPS_MINFLINEAR |
3409 WINED3DPTFILTERCAPS_MINFPOINT |
3410 WINED3DPTFILTERCAPS_MIPFLINEAR |
3411 WINED3DPTFILTERCAPS_MIPFPOINT |
3412 WINED3DPTFILTERCAPS_LINEAR |
3413 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3414 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3415 WINED3DPTFILTERCAPS_MIPLINEAR |
3416 WINED3DPTFILTERCAPS_MIPNEAREST |
3417 WINED3DPTFILTERCAPS_NEAREST;
3419 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3420 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3421 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3423 } else
3424 pCaps->CubeTextureFilterCaps = 0;
3426 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3427 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3428 WINED3DPTFILTERCAPS_MAGFPOINT |
3429 WINED3DPTFILTERCAPS_MINFLINEAR |
3430 WINED3DPTFILTERCAPS_MINFPOINT |
3431 WINED3DPTFILTERCAPS_MIPFLINEAR |
3432 WINED3DPTFILTERCAPS_MIPFPOINT |
3433 WINED3DPTFILTERCAPS_LINEAR |
3434 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3435 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3436 WINED3DPTFILTERCAPS_MIPLINEAR |
3437 WINED3DPTFILTERCAPS_MIPNEAREST |
3438 WINED3DPTFILTERCAPS_NEAREST;
3439 } else
3440 pCaps->VolumeTextureFilterCaps = 0;
3442 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3443 WINED3DPTADDRESSCAPS_CLAMP |
3444 WINED3DPTADDRESSCAPS_WRAP;
3446 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3447 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3449 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3450 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3452 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3453 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3456 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3457 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3458 WINED3DPTADDRESSCAPS_CLAMP |
3459 WINED3DPTADDRESSCAPS_WRAP;
3460 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3461 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3463 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3464 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3466 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3467 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3469 } else
3470 pCaps->VolumeTextureAddressCaps = 0;
3472 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3473 WINED3DLINECAPS_ZTEST |
3474 WINED3DLINECAPS_BLEND |
3475 WINED3DLINECAPS_ALPHACMP |
3476 WINED3DLINECAPS_FOG;
3477 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3478 * idea how generating the smoothing alpha values works; the result is different
3481 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3482 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3484 if(GL_SUPPORT(EXT_TEXTURE3D))
3485 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3486 else
3487 pCaps->MaxVolumeExtent = 0;
3489 pCaps->MaxTextureRepeat = 32768;
3490 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3491 pCaps->MaxVertexW = 1.0;
3493 pCaps->GuardBandLeft = 0;
3494 pCaps->GuardBandTop = 0;
3495 pCaps->GuardBandRight = 0;
3496 pCaps->GuardBandBottom = 0;
3498 pCaps->ExtentsAdjust = 0;
3500 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3501 WINED3DSTENCILCAPS_INCRSAT |
3502 WINED3DSTENCILCAPS_INVERT |
3503 WINED3DSTENCILCAPS_KEEP |
3504 WINED3DSTENCILCAPS_REPLACE |
3505 WINED3DSTENCILCAPS_ZERO;
3506 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3507 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3508 WINED3DSTENCILCAPS_INCR;
3510 if ( This->dxVersion > 8 &&
3511 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
3512 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
3513 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3516 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3518 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3519 pCaps->MaxActiveLights = GL_LIMITS(lights);
3521 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3522 pCaps->MaxVertexBlendMatrixIndex = 0;
3524 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3525 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3528 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3529 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3530 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3531 WINED3DVTXPCAPS_LOCALVIEWER |
3532 WINED3DVTXPCAPS_VERTEXFOG |
3533 WINED3DVTXPCAPS_TEXGEN;
3534 /* FIXME: Add
3535 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3537 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3538 pCaps->MaxVertexIndex = 0xFFFFF;
3539 pCaps->MaxStreams = MAX_STREAMS;
3540 pCaps->MaxStreamStride = 1024;
3542 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3543 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3544 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3545 pCaps->MaxNpatchTessellationLevel = 0;
3546 pCaps->MasterAdapterOrdinal = 0;
3547 pCaps->AdapterOrdinalInGroup = 0;
3548 pCaps->NumberOfAdaptersInGroup = 1;
3550 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3552 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3553 WINED3DPTFILTERCAPS_MAGFPOINT |
3554 WINED3DPTFILTERCAPS_MINFLINEAR |
3555 WINED3DPTFILTERCAPS_MAGFLINEAR;
3556 pCaps->VertexTextureFilterCaps = 0;
3558 memset(&shader_caps, 0, sizeof(shader_caps));
3559 shader_backend = select_shader_backend(adapter, DeviceType);
3560 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
3562 memset(&fragment_caps, 0, sizeof(fragment_caps));
3563 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
3564 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
3566 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
3567 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
3569 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
3570 * Ignore shader model capabilities if disabled in config
3572 if(vs_selected_mode == SHADER_NONE) {
3573 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
3574 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
3575 pCaps->MaxVertexShaderConst = 0;
3576 } else {
3577 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
3578 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
3581 if(ps_selected_mode == SHADER_NONE) {
3582 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
3583 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
3584 pCaps->PixelShader1xMaxValue = 0.0;
3585 } else {
3586 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
3587 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
3590 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
3591 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
3592 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
3594 pCaps->VS20Caps = shader_caps.VS20Caps;
3595 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
3596 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
3597 pCaps->PS20Caps = shader_caps.PS20Caps;
3598 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
3599 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
3601 /* The following caps are shader specific, but they are things we cannot detect, or which
3602 * are the same among all shader models. So to avoid code duplication set the shader version
3603 * specific, but otherwise constant caps here
3605 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
3606 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3607 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
3608 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
3609 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3610 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.vs_arb_max_temps);
3611 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
3613 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
3614 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
3615 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
3616 pCaps->VS20Caps.Caps = 0;
3617 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
3618 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.vs_arb_max_temps);
3619 pCaps->VS20Caps.StaticFlowControlDepth = 1;
3621 pCaps->MaxVShaderInstructionsExecuted = 65535;
3622 pCaps->MaxVertexShader30InstructionSlots = 0;
3623 } else { /* VS 1.x */
3624 pCaps->VS20Caps.Caps = 0;
3625 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
3626 pCaps->VS20Caps.NumTemps = 0;
3627 pCaps->VS20Caps.StaticFlowControlDepth = 0;
3629 pCaps->MaxVShaderInstructionsExecuted = 0;
3630 pCaps->MaxVertexShader30InstructionSlots = 0;
3633 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
3634 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3635 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
3637 /* 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 */
3638 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
3639 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
3640 WINED3DPS20CAPS_PREDICATION |
3641 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
3642 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
3643 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3644 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.ps_arb_max_temps);
3645 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
3646 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
3648 pCaps->MaxPShaderInstructionsExecuted = 65535;
3649 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
3650 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
3651 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
3652 pCaps->PS20Caps.Caps = 0;
3653 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
3654 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.ps_arb_max_temps);
3655 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
3656 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
3658 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
3659 pCaps->MaxPixelShader30InstructionSlots = 0;
3660 } else { /* PS 1.x */
3661 pCaps->PS20Caps.Caps = 0;
3662 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
3663 pCaps->PS20Caps.NumTemps = 0;
3664 pCaps->PS20Caps.StaticFlowControlDepth = 0;
3665 pCaps->PS20Caps.NumInstructionSlots = 0;
3667 pCaps->MaxPShaderInstructionsExecuted = 0;
3668 pCaps->MaxPixelShader30InstructionSlots = 0;
3671 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
3672 /* OpenGL supports all the formats below, perhaps not always
3673 * without conversion, but it supports them.
3674 * Further GLSL doesn't seem to have an official unsigned type so
3675 * don't advertise it yet as I'm not sure how we handle it.
3676 * We might need to add some clamping in the shader engine to
3677 * support it.
3678 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
3679 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
3680 WINED3DDTCAPS_UBYTE4N |
3681 WINED3DDTCAPS_SHORT2N |
3682 WINED3DDTCAPS_SHORT4N;
3683 if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
3684 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
3685 WINED3DDTCAPS_FLOAT16_4;
3687 } else
3688 pCaps->DeclTypes = 0;
3690 /* Set DirectDraw helper Caps */
3691 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
3692 WINEDDCKEYCAPS_SRCBLT;
3693 fx_caps = WINEDDFXCAPS_BLTALPHA |
3694 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
3695 WINEDDFXCAPS_BLTMIRRORUPDOWN |
3696 WINEDDFXCAPS_BLTROTATION90 |
3697 WINEDDFXCAPS_BLTSHRINKX |
3698 WINEDDFXCAPS_BLTSHRINKXN |
3699 WINEDDFXCAPS_BLTSHRINKY |
3700 WINEDDFXCAPS_BLTSHRINKXN |
3701 WINEDDFXCAPS_BLTSTRETCHX |
3702 WINEDDFXCAPS_BLTSTRETCHXN |
3703 WINEDDFXCAPS_BLTSTRETCHY |
3704 WINEDDFXCAPS_BLTSTRETCHYN;
3705 blit_caps = WINEDDCAPS_BLT |
3706 WINEDDCAPS_BLTCOLORFILL |
3707 WINEDDCAPS_BLTDEPTHFILL |
3708 WINEDDCAPS_BLTSTRETCH |
3709 WINEDDCAPS_CANBLTSYSMEM |
3710 WINEDDCAPS_CANCLIP |
3711 WINEDDCAPS_CANCLIPSTRETCHED |
3712 WINEDDCAPS_COLORKEY |
3713 WINEDDCAPS_COLORKEYHWASSIST |
3714 WINEDDCAPS_ALIGNBOUNDARYSRC;
3716 /* Fill the ddraw caps structure */
3717 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
3718 WINEDDCAPS_PALETTE |
3719 blit_caps;
3720 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
3721 WINEDDCAPS2_NOPAGELOCKREQUIRED |
3722 WINEDDCAPS2_PRIMARYGAMMA |
3723 WINEDDCAPS2_WIDESURFACES |
3724 WINEDDCAPS2_CANRENDERWINDOWED;
3725 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
3726 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
3727 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
3728 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
3729 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
3730 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
3731 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
3732 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
3733 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
3735 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
3736 WINEDDSCAPS_BACKBUFFER |
3737 WINEDDSCAPS_FLIP |
3738 WINEDDSCAPS_FRONTBUFFER |
3739 WINEDDSCAPS_OFFSCREENPLAIN |
3740 WINEDDSCAPS_PALETTE |
3741 WINEDDSCAPS_PRIMARYSURFACE |
3742 WINEDDSCAPS_SYSTEMMEMORY |
3743 WINEDDSCAPS_VIDEOMEMORY |
3744 WINEDDSCAPS_VISIBLE;
3745 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
3747 /* Set D3D caps if OpenGL is available. */
3748 if (adapter->opengl)
3750 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
3751 WINEDDSCAPS_MIPMAP |
3752 WINEDDSCAPS_TEXTURE |
3753 WINEDDSCAPS_ZBUFFER;
3754 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
3757 return WINED3D_OK;
3760 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
3761 and fields being inserted in the middle, a new structure is used in place */
3762 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
3763 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
3764 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
3766 IWineD3DDeviceImpl *object = NULL;
3767 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3768 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3769 WINED3DDISPLAYMODE mode;
3770 const struct fragment_pipeline *frag_pipeline = NULL;
3771 int i;
3772 struct fragment_caps ffp_caps;
3773 struct shader_caps shader_caps;
3774 HRESULT hr;
3776 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
3777 * number and create a device without a 3D adapter for 2D only operation.
3779 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
3780 return WINED3DERR_INVALIDCALL;
3783 /* Create a WineD3DDevice object */
3784 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
3785 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
3786 TRACE("Created WineD3DDevice object @ %p\n", object);
3787 if (NULL == object) {
3788 return WINED3DERR_OUTOFVIDEOMEMORY;
3791 /* Set up initial COM information */
3792 object->lpVtbl = &IWineD3DDevice_Vtbl;
3793 object->ref = 1;
3794 object->wineD3D = iface;
3795 object->adapter = This->adapter_count ? adapter : NULL;
3796 IWineD3D_AddRef(object->wineD3D);
3797 object->parent = parent;
3798 object->device_parent = device_parent;
3799 list_init(&object->resources);
3800 list_init(&object->shaders);
3802 if(This->dxVersion == 7) {
3803 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
3804 } else {
3805 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
3807 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
3809 /* Set the state up as invalid until the device is fully created */
3810 object->state = WINED3DERR_DRIVERINTERNALERROR;
3812 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
3813 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
3815 /* Save the creation parameters */
3816 object->createParms.AdapterOrdinal = Adapter;
3817 object->createParms.DeviceType = DeviceType;
3818 object->createParms.hFocusWindow = hFocusWindow;
3819 object->createParms.BehaviorFlags = BehaviourFlags;
3821 /* Initialize other useful values */
3822 object->adapterNo = Adapter;
3823 object->devType = DeviceType;
3825 select_shader_mode(&adapter->gl_info, DeviceType,
3826 &object->ps_selected_mode, &object->vs_selected_mode);
3827 object->shader_backend = select_shader_backend(adapter, DeviceType);
3829 memset(&shader_caps, 0, sizeof(shader_caps));
3830 object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
3831 object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
3832 object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
3833 object->vs_clipping = shader_caps.VSClipping;
3835 memset(&ffp_caps, 0, sizeof(ffp_caps));
3836 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
3837 object->frag_pipe = frag_pipeline;
3838 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
3839 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
3840 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
3841 hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
3842 ffp_vertexstate_template, frag_pipeline, misc_state_template);
3844 if (FAILED(hr)) {
3845 IWineD3D_Release(object->wineD3D);
3846 HeapFree(GetProcessHeap(), 0, object);
3848 return hr;
3851 object->blitter = select_blit_implementation(adapter, DeviceType);
3853 /* set the state of the device to valid */
3854 object->state = WINED3D_OK;
3856 /* Get the initial screen setup for ddraw */
3857 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
3859 object->ddraw_width = mode.Width;
3860 object->ddraw_height = mode.Height;
3861 object->ddraw_format = mode.Format;
3863 for(i = 0; i < PATCHMAP_SIZE; i++) {
3864 list_init(&object->patches[i]);
3867 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
3869 return WINED3D_OK;
3872 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
3873 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3874 IUnknown_AddRef(This->parent);
3875 *pParent = This->parent;
3876 return WINED3D_OK;
3879 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
3880 IUnknown* surfaceParent;
3881 TRACE("(%p) call back\n", pSurface);
3883 /* Now, release the parent, which will take care of cleaning up the surface for us */
3884 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
3885 IUnknown_Release(surfaceParent);
3886 return IUnknown_Release(surfaceParent);
3889 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
3890 IUnknown* volumeParent;
3891 TRACE("(%p) call back\n", pVolume);
3893 /* Now, release the parent, which will take care of cleaning up the volume for us */
3894 IWineD3DVolume_GetParent(pVolume, &volumeParent);
3895 IUnknown_Release(volumeParent);
3896 return IUnknown_Release(volumeParent);
3899 static BOOL match_apple(const WineD3D_GL_Info *gl_info)
3901 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
3902 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
3903 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
3905 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
3906 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
3907 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
3908 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
3909 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
3910 * the chance that other implementations support them is rather small since Win32 QuickTime uses
3911 * DirectDraw, not OpenGL.
3913 if(gl_info->supported[APPLE_FENCE] &&
3914 gl_info->supported[APPLE_CLIENT_STORAGE] &&
3915 gl_info->supported[APPLE_FLUSH_RENDER] &&
3916 gl_info->supported[APPLE_YCBCR_422]) {
3917 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
3918 TRACE_(d3d_caps)("Activating MacOS fixups\n");
3919 return TRUE;
3920 } else {
3921 TRACE_(d3d_caps)("Apple extensions are not supported\n");
3922 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
3923 return FALSE;
3927 static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
3928 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
3929 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
3930 * all the texture. This function detects this bug by its symptom and disables PBOs
3931 * if the test fails.
3933 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
3934 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
3935 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
3936 * read back is compared to the original. If they are equal PBOs are assumed to work,
3937 * otherwise the PBO extension is disabled.
3939 GLuint texture, pbo;
3940 static const unsigned int pattern[] = {
3941 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
3942 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
3943 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
3944 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
3946 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
3948 if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
3949 /* No PBO -> No point in testing them */
3950 return;
3953 ENTER_GL();
3955 while(glGetError());
3956 glGenTextures(1, &texture);
3957 glBindTexture(GL_TEXTURE_2D, texture);
3959 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3960 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
3961 checkGLcall("Specifying the PBO test texture\n");
3963 GL_EXTCALL(glGenBuffersARB(1, &pbo));
3964 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
3965 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
3966 checkGLcall("Specifying the PBO test pbo\n");
3968 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3969 checkGLcall("Loading the PBO test texture\n");
3971 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
3972 glFinish(); /* just to be sure */
3974 memset(check, 0, sizeof(check));
3975 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
3976 checkGLcall("Reading back the PBO test texture\n");
3978 glDeleteTextures(1, &texture);
3979 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
3980 checkGLcall("PBO test cleanup\n");
3982 LEAVE_GL();
3984 if(memcmp(check, pattern, sizeof(check)) != 0) {
3985 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
3986 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
3987 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
3988 } else {
3989 TRACE_(d3d_caps)("PBO test successful\n");
3993 /* Certain applications(Steam) complain if we report an outdated driver version. In general,
3994 * reporting a driver version is moot because we are not the Windows driver, and we have different
3995 * bugs, features, etc.
3997 * If a card is not found in this table, the gl driver version is reported
3999 struct driver_version_information {
4000 WORD vendor; /* reported PCI card vendor ID */
4001 WORD card; /* reported PCI card device ID */
4002 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
4003 WORD hipart_hi, hipart_lo; /* driver hiword to report */
4004 WORD lopart_hi, lopart_lo; /* driver loword to report */
4007 static const struct driver_version_information driver_version_table[] = {
4008 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
4009 * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown
4010 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
4011 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
4013 * All version numbers used below are from the Linux nvidia drivers.
4015 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 },
4016 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 },
4017 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 },
4018 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 },
4019 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 },
4020 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 4, 3 },
4021 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 4, 3 },
4022 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 4, 3 },
4023 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7341 },
4024 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7341 },
4025 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7341 },
4026 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8044 },
4027 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8044 },
4028 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8044 },
4029 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8044 },
4030 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8044 },
4031 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8044 },
4032 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8044 },
4033 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8044 },
4034 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8044 },
4035 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8044 },
4036 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8044 },
4037 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8044 },
4038 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8044 },
4039 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8044 },
4040 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8044 },
4041 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8044 },
4042 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8044 },
4043 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8044 },
4044 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8044 },
4046 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
4047 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 },
4048 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 },
4049 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 },
4050 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 },
4051 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 },
4052 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 },
4053 {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 6, 14, 10, 6764 },
4054 {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 6, 14, 10, 6764 },
4055 {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 6, 14, 10, 6764 },
4056 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 },
4058 /* TODO: Add information about legacy ATI hardware, Intel and other cards */
4061 static BOOL match_ati_r300_to_500(const WineD3D_GL_Info *gl_info) {
4062 if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
4063 if(gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
4064 if(gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
4065 if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
4066 return FALSE;
4069 static BOOL match_geforce5(const WineD3D_GL_Info *gl_info) {
4070 if(gl_info->gl_vendor == VENDOR_NVIDIA) {
4071 if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
4072 return TRUE;
4075 return FALSE;
4078 static BOOL match_apple_intel(const WineD3D_GL_Info *gl_info) {
4079 return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info);
4082 static BOOL match_apple_nonr500ati(const WineD3D_GL_Info *gl_info) {
4083 if(!match_apple(gl_info)) return FALSE;
4084 if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
4085 if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
4086 return TRUE;
4089 static BOOL match_fglrx(const WineD3D_GL_Info *gl_info) {
4090 if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
4091 if(match_apple(gl_info)) return FALSE;
4092 if(strstr(gl_info->gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers */
4093 return TRUE;
4096 static BOOL match_dx10_capable(const WineD3D_GL_Info *gl_info) {
4097 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
4098 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
4099 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
4100 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
4101 * hardcoded
4103 * dx10 cards usually have 64 varyings
4105 return gl_info->max_glsl_varyings > 44;
4108 static void quirk_arb_constants(WineD3D_GL_Info *gl_info) {
4109 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL\n", gl_info->vs_arb_constantsF);
4110 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
4111 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL\n", gl_info->ps_arb_constantsF);
4112 gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
4115 static void quirk_apple_glsl_constants(WineD3D_GL_Info *gl_info) {
4116 quirk_arb_constants(gl_info);
4117 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
4118 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
4119 * allow 48 different offsets or other helper immediate values
4121 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use\n");
4122 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
4125 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
4126 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
4127 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
4128 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
4129 * most games, but avoids the crash
4131 * A more sophisticated way would be to find all units that need texture coordinates and enable
4132 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
4133 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
4135 * Note that disabling the extension entirely does not gain predictability because there is no point
4136 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension.
4138 static void quirk_one_point_sprite(WineD3D_GL_Info *gl_info) {
4139 if(gl_info->supported[ARB_POINT_SPRITE]) {
4140 TRACE("Limiting point sprites to one texture unit\n");
4141 gl_info->max_point_sprite_units = 1;
4145 static void quirk_ati_dx9(WineD3D_GL_Info *gl_info) {
4146 quirk_arb_constants(gl_info);
4148 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
4149 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
4150 * If real NP2 textures are used, the driver falls back to software. We could just remove the
4151 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
4152 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
4153 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
4154 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
4156 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
4157 * has this extension promoted to core. The extension loading code sets this extension supported
4158 * due to that, so this code works on fglrx as well.
4160 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
4161 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
4162 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
4164 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
4165 * it is generally more efficient. Reserve just 8 constants
4167 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use\n");
4168 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
4171 static void quirk_no_np2(WineD3D_GL_Info *gl_info) {
4172 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
4173 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
4174 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
4175 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
4176 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
4177 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
4179 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
4180 * triggering the software fallback. There is not much we can do here apart from disabling the
4181 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
4182 * in IWineD3DImpl_FillGLCaps).
4183 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
4184 * post-processing effects in the game "Max Payne 2").
4185 * The behaviour can be verified through a simple test app attached in bugreport #14724.
4187 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
4188 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
4189 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
4192 static void quirk_texcoord_w(WineD3D_GL_Info *gl_info) {
4193 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
4194 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
4195 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
4196 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
4197 * according to the spec.
4199 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
4200 * makes the shader slower and eats instruction slots which should be available to the d3d app.
4202 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
4203 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
4204 * this workaround is activated on cards that do not need it, it won't break things, just affect
4205 * performance negatively.
4207 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
4208 gl_info->set_texcoord_w = TRUE;
4211 static void quirk_clip_varying(WineD3D_GL_Info *gl_info) {
4212 gl_info->glsl_clip_varying = TRUE;
4215 struct driver_quirk quirk_table[] = {
4217 match_ati_r300_to_500,
4218 quirk_ati_dx9,
4219 "ATI GLSL constant and normalized texrect quirk"
4221 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
4222 * used it falls back to software. While the compiler can detect if the shader uses all declared
4223 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
4224 * using relative addressing falls back to software.
4226 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
4229 match_apple,
4230 quirk_apple_glsl_constants,
4231 "Apple GLSL uniform override"
4234 match_geforce5,
4235 quirk_no_np2,
4236 "Geforce 5 NP2 disable"
4239 match_apple_intel,
4240 quirk_texcoord_w,
4241 "Init texcoord .w for Apple Intel GPU driver"
4244 match_apple_nonr500ati,
4245 quirk_texcoord_w,
4246 "Init texcoord .w for Apple ATI >= r600 GPU driver"
4249 match_fglrx,
4250 quirk_one_point_sprite,
4251 "Fglrx point sprite crash workaround"
4254 match_dx10_capable,
4255 quirk_clip_varying,
4256 "Reserved varying for gl_ClipPos"
4260 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
4261 unsigned int i;
4263 for(i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); i++) {
4264 if(!quirk_table[i].match(gl_info)) continue;
4265 TRACE_(d3d_caps)("Applying driver quirk \"%s\"\n", quirk_table[i].description);
4266 quirk_table[i].apply(gl_info);
4269 /* Find out if PBOs work as they are supposed to */
4270 test_pbo_functionality(gl_info);
4272 /* Fixup the driver version */
4273 for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
4274 if(gl_info->gl_vendor == driver_version_table[i].vendor &&
4275 gl_info->gl_card == driver_version_table[i].card) {
4276 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
4278 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
4279 driver_version_table[i].lopart_lo);
4280 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
4281 driver_version_table[i].hipart_lo);
4282 strcpy(gl_info->driver_description, driver_version_table[i].description);
4283 break;
4288 static void WINE_GLAPI invalid_func(const void *data)
4290 ERR("Invalid vertex attribute function called\n");
4291 DebugBreak();
4294 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4296 ERR("Invalid texcoord function called\n");
4297 DebugBreak();
4300 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4301 * the extension detection and are used in drawStridedSlow
4303 static void WINE_GLAPI position_d3dcolor(const void *data)
4305 DWORD pos = *((const DWORD *)data);
4307 FIXME("Add a test for fixed function position from d3dcolor type\n");
4308 glVertex4s(D3DCOLOR_B_R(pos),
4309 D3DCOLOR_B_G(pos),
4310 D3DCOLOR_B_B(pos),
4311 D3DCOLOR_B_A(pos));
4314 static void WINE_GLAPI position_float4(const void *data)
4316 const GLfloat *pos = data;
4318 if (pos[3] < eps && pos[3] > -eps)
4319 glVertex3fv(pos);
4320 else {
4321 float w = 1.0 / pos[3];
4323 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4327 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4329 DWORD diffuseColor = *((const DWORD *)data);
4331 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4332 D3DCOLOR_B_G(diffuseColor),
4333 D3DCOLOR_B_B(diffuseColor),
4334 D3DCOLOR_B_A(diffuseColor));
4337 static void WINE_GLAPI specular_d3dcolor(const void *data)
4339 DWORD specularColor = *((const DWORD *)data);
4340 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4341 D3DCOLOR_B_G(specularColor),
4342 D3DCOLOR_B_B(specularColor)};
4344 specular_func_3ubv(d);
4347 static void WINE_GLAPI warn_no_specular_func(const void *data)
4349 WARN("GL_EXT_secondary_color not supported\n");
4352 static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
4354 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4355 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4356 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4357 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4358 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4359 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4360 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4361 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4362 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4363 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4364 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4365 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4366 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4367 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4368 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4369 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4370 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4372 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4373 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4374 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4375 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4376 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4377 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4378 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4379 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4380 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4381 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4382 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4383 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4384 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4385 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4386 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4387 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4388 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4390 /* No 4 component entry points here */
4391 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4392 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4393 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4394 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4395 } else {
4396 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4398 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4399 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4400 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4401 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4402 } else {
4403 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4405 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4406 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4407 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4408 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4409 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4410 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4411 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4412 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4413 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4414 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4415 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4416 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4418 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4419 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4421 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4422 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4423 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4424 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4425 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4426 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4427 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4428 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4429 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4430 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4431 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4432 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4433 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4434 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4435 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4436 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4437 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4439 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4440 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4441 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4442 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4443 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4444 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4445 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4446 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4447 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4448 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4449 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4450 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4451 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4452 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4453 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4454 if (GL_SUPPORT(NV_HALF_FLOAT))
4456 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4457 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4458 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4459 } else {
4460 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4461 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4465 BOOL InitAdapters(IWineD3DImpl *This)
4467 static HMODULE mod_gl;
4468 BOOL ret;
4469 int ps_selected_mode, vs_selected_mode;
4471 /* No need to hold any lock. The calling library makes sure only one thread calls
4472 * wined3d simultaneously
4475 TRACE("Initializing adapters\n");
4477 if(!mod_gl) {
4478 #ifdef USE_WIN32_OPENGL
4479 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4480 mod_gl = LoadLibraryA("opengl32.dll");
4481 if(!mod_gl) {
4482 ERR("Can't load opengl32.dll!\n");
4483 goto nogl_adapter;
4485 #else
4486 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4487 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4488 mod_gl = GetModuleHandleA("gdi32.dll");
4489 #endif
4492 /* Load WGL core functions from opengl32.dll */
4493 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4494 WGL_FUNCS_GEN;
4495 #undef USE_WGL_FUNC
4497 if(!pwglGetProcAddress) {
4498 ERR("Unable to load wglGetProcAddress!\n");
4499 goto nogl_adapter;
4502 /* Dynamically load all GL core functions */
4503 GL_FUNCS_GEN;
4504 #undef USE_GL_FUNC
4506 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4507 * otherwise because we have to use winex11.drv's override
4509 #ifdef USE_WIN32_OPENGL
4510 glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4511 glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4512 #else
4513 glFinish = (void*)pwglGetProcAddress("wglFinish");
4514 glFlush = (void*)pwglGetProcAddress("wglFlush");
4515 #endif
4517 glEnableWINE = glEnable;
4518 glDisableWINE = glDisable;
4520 /* For now only one default adapter */
4522 struct WineD3DAdapter *adapter = &This->adapters[0];
4523 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
4524 int iPixelFormat;
4525 int res;
4526 int i;
4527 WineD3D_PixelFormat *cfgs;
4528 DISPLAY_DEVICEW DisplayDevice;
4529 HDC hdc;
4531 TRACE("Initializing default adapter\n");
4532 adapter->num = 0;
4533 adapter->monitorPoint.x = -1;
4534 adapter->monitorPoint.y = -1;
4536 if (!WineD3D_CreateFakeGLContext()) {
4537 ERR("Failed to get a gl context for default adapter\n");
4538 WineD3D_ReleaseFakeGLContext();
4539 goto nogl_adapter;
4542 ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
4543 if(!ret) {
4544 ERR("Failed to initialize gl caps for default adapter\n");
4545 WineD3D_ReleaseFakeGLContext();
4546 goto nogl_adapter;
4548 ret = initPixelFormats(&adapter->gl_info);
4549 if(!ret) {
4550 ERR("Failed to init gl formats\n");
4551 WineD3D_ReleaseFakeGLContext();
4552 goto nogl_adapter;
4555 hdc = pwglGetCurrentDC();
4556 if(!hdc) {
4557 ERR("Failed to get gl HDC\n");
4558 WineD3D_ReleaseFakeGLContext();
4559 goto nogl_adapter;
4562 adapter->driver = "Display";
4563 adapter->description = "Direct3D HAL";
4565 /* Use the VideoRamSize registry setting when set */
4566 if(wined3d_settings.emulated_textureram)
4567 adapter->TextureRam = wined3d_settings.emulated_textureram;
4568 else
4569 adapter->TextureRam = adapter->gl_info.vidmem;
4570 adapter->UsedTextureRam = 0;
4571 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4573 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4574 DisplayDevice.cb = sizeof(DisplayDevice);
4575 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4576 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4577 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4579 if(GL_SUPPORT(WGL_ARB_PIXEL_FORMAT))
4581 int attribute;
4582 int attribs[10];
4583 int values[10];
4584 int nAttribs = 0;
4586 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4587 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4589 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4590 cfgs = adapter->cfgs;
4591 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4592 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4593 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4594 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4595 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4596 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4597 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4598 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4599 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4600 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4602 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4604 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4606 if(!res)
4607 continue;
4609 /* Cache the pixel format */
4610 cfgs->iPixelFormat = iPixelFormat;
4611 cfgs->redSize = values[0];
4612 cfgs->greenSize = values[1];
4613 cfgs->blueSize = values[2];
4614 cfgs->alphaSize = values[3];
4615 cfgs->depthSize = values[4];
4616 cfgs->stencilSize = values[5];
4617 cfgs->windowDrawable = values[6];
4618 cfgs->iPixelType = values[7];
4619 cfgs->doubleBuffer = values[8];
4620 cfgs->auxBuffers = values[9];
4622 cfgs->pbufferDrawable = FALSE;
4623 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4624 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4625 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4626 int value;
4627 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4628 cfgs->pbufferDrawable = value;
4631 cfgs->numSamples = 0;
4632 /* Check multisample support */
4633 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4634 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4635 int value[2];
4636 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4637 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4638 * value[1] = number of multi sample buffers*/
4639 if(value[0])
4640 cfgs->numSamples = value[1];
4644 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
4645 cfgs++;
4648 else
4650 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4651 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4652 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4654 cfgs = adapter->cfgs;
4655 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4657 PIXELFORMATDESCRIPTOR ppfd;
4659 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4660 if(!res)
4661 continue;
4663 /* We only want HW acceleration using an OpenGL ICD driver.
4664 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4665 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4667 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4669 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4670 continue;
4673 cfgs->iPixelFormat = iPixelFormat;
4674 cfgs->redSize = ppfd.cRedBits;
4675 cfgs->greenSize = ppfd.cGreenBits;
4676 cfgs->blueSize = ppfd.cBlueBits;
4677 cfgs->alphaSize = ppfd.cAlphaBits;
4678 cfgs->depthSize = ppfd.cDepthBits;
4679 cfgs->stencilSize = ppfd.cStencilBits;
4680 cfgs->pbufferDrawable = 0;
4681 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4682 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4683 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4684 cfgs->auxBuffers = ppfd.cAuxBuffers;
4685 cfgs->numSamples = 0;
4687 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
4688 cfgs++;
4689 adapter->nCfgs++;
4692 /* Yikes we haven't found any suitable formats. This should only happen in case of GDI software rendering which we can't use anyway as its 3D functionality is very, very limited */
4693 if(!adapter->nCfgs)
4695 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4697 WineD3D_ReleaseFakeGLContext();
4698 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4699 goto nogl_adapter;
4703 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4704 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4705 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4706 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4707 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4708 * driver is allowed to consume more bits EXCEPT for stencil bits.
4710 * Mark an adapter with this broken stencil behavior.
4712 adapter->brokenStencil = TRUE;
4713 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4715 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4716 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4717 adapter->brokenStencil = FALSE;
4718 break;
4722 fixup_extensions(&adapter->gl_info);
4723 add_gl_compat_wrappers(&adapter->gl_info);
4725 WineD3D_ReleaseFakeGLContext();
4727 select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4728 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
4729 fillGLAttribFuncs(&adapter->gl_info);
4730 adapter->opengl = TRUE;
4732 This->adapter_count = 1;
4733 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4735 return TRUE;
4737 nogl_adapter:
4738 /* Initialize an adapter for ddraw-only memory counting */
4739 memset(This->adapters, 0, sizeof(This->adapters));
4740 This->adapters[0].num = 0;
4741 This->adapters[0].opengl = FALSE;
4742 This->adapters[0].monitorPoint.x = -1;
4743 This->adapters[0].monitorPoint.y = -1;
4745 This->adapters[0].driver = "Display";
4746 This->adapters[0].description = "WineD3D DirectDraw Emulation";
4747 if(wined3d_settings.emulated_textureram) {
4748 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4749 } else {
4750 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4753 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4755 This->adapter_count = 1;
4756 return FALSE;
4759 /**********************************************************
4760 * IWineD3D VTbl follows
4761 **********************************************************/
4763 const IWineD3DVtbl IWineD3D_Vtbl =
4765 /* IUnknown */
4766 IWineD3DImpl_QueryInterface,
4767 IWineD3DImpl_AddRef,
4768 IWineD3DImpl_Release,
4769 /* IWineD3D */
4770 IWineD3DImpl_GetParent,
4771 IWineD3DImpl_GetAdapterCount,
4772 IWineD3DImpl_RegisterSoftwareDevice,
4773 IWineD3DImpl_GetAdapterMonitor,
4774 IWineD3DImpl_GetAdapterModeCount,
4775 IWineD3DImpl_EnumAdapterModes,
4776 IWineD3DImpl_GetAdapterDisplayMode,
4777 IWineD3DImpl_GetAdapterIdentifier,
4778 IWineD3DImpl_CheckDeviceMultiSampleType,
4779 IWineD3DImpl_CheckDepthStencilMatch,
4780 IWineD3DImpl_CheckDeviceType,
4781 IWineD3DImpl_CheckDeviceFormat,
4782 IWineD3DImpl_CheckDeviceFormatConversion,
4783 IWineD3DImpl_GetDeviceCaps,
4784 IWineD3DImpl_CreateDevice