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
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 */
46 const char *extension_string;
47 GL_SupportedExt extension;
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 },
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 },
65 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
66 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
67 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
68 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
69 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
70 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
71 {"GL_ARB_imaging", ARB_IMAGING, 0 },
72 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
73 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
74 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
75 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
76 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
77 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
78 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
79 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
80 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
81 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
82 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
83 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
84 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
85 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
86 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
87 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
88 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
89 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
90 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
91 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
92 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
93 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
96 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
97 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
98 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
99 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
100 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
101 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
102 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
103 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
104 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
105 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
106 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
107 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
108 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
109 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
110 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
111 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
112 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
113 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
114 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
115 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
116 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
117 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
118 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
119 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
120 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
121 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
122 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
125 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
126 {"GL_NV_fence", NV_FENCE, 0 },
127 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
128 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
129 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
130 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
131 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
132 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
133 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
134 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
135 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
136 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
137 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
138 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
139 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
140 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
141 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
142 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
143 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
146 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
149 /**********************************************************
150 * Utility functions follow
151 **********************************************************/
153 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
154 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
155 WINED3DDEVTYPE DeviceType);
156 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
157 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
160 const int minLookup[MAX_LOOKUPS] =
162 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
165 const int maxLookup[MAX_LOOKUPS] =
167 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
170 DWORD *stateLookup[MAX_LOOKUPS];
172 struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
173 const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
175 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
176 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
177 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
178 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
181 GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
182 const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
184 GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
187 /* drawStridedSlow attributes */
188 glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
189 glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
190 glAttribFunc specular_func_3ubv;
191 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
192 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
193 glMultiTexCoordFunc multi_texcoord_funcs[WINED3DDECLTYPE_UNUSED];
196 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
197 * i.e., there is no GL Context - Get a default rendering context to enable the
198 * function query some info from GL.
201 static int wined3d_fake_gl_context_ref = 0;
202 static BOOL wined3d_fake_gl_context_foreign;
203 static BOOL wined3d_fake_gl_context_available = FALSE;
204 static HDC wined3d_fake_gl_context_hdc = NULL;
205 static HWND wined3d_fake_gl_context_hwnd = NULL;
207 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
208 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
210 0, 0, &wined3d_fake_gl_context_cs,
211 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
212 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
213 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
215 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
217 static void WineD3D_ReleaseFakeGLContext(void) {
220 EnterCriticalSection(&wined3d_fake_gl_context_cs);
222 if(!wined3d_fake_gl_context_available) {
223 TRACE_(d3d_caps)("context not available\n");
224 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
228 glCtx = pwglGetCurrentContext();
230 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
231 if (0 == (--wined3d_fake_gl_context_ref) ) {
232 if(!wined3d_fake_gl_context_foreign && glCtx) {
233 TRACE_(d3d_caps)("destroying fake GL context\n");
234 pwglMakeCurrent(NULL, NULL);
235 pwglDeleteContext(glCtx);
237 if(wined3d_fake_gl_context_hdc)
238 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
239 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
240 if(wined3d_fake_gl_context_hwnd)
241 DestroyWindow(wined3d_fake_gl_context_hwnd);
242 wined3d_fake_gl_context_hwnd = NULL;
243 wined3d_fake_gl_context_available = FALSE;
245 assert(wined3d_fake_gl_context_ref >= 0);
247 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
250 static BOOL WineD3D_CreateFakeGLContext(void) {
253 EnterCriticalSection(&wined3d_fake_gl_context_cs);
255 TRACE("getting context...\n");
256 if(wined3d_fake_gl_context_ref > 0) goto ret;
257 assert(0 == wined3d_fake_gl_context_ref);
259 wined3d_fake_gl_context_foreign = TRUE;
261 glCtx = pwglGetCurrentContext();
263 PIXELFORMATDESCRIPTOR pfd;
266 wined3d_fake_gl_context_foreign = FALSE;
268 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
269 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
270 if(!wined3d_fake_gl_context_hwnd) {
271 ERR("HWND creation failed!\n");
274 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
275 if(!wined3d_fake_gl_context_hdc) {
276 ERR("GetDC failed!\n");
280 /* PixelFormat selection */
281 ZeroMemory(&pfd, sizeof(pfd));
282 pfd.nSize = sizeof(pfd);
284 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
285 pfd.iPixelType = PFD_TYPE_RGBA;
287 pfd.iLayerType = PFD_MAIN_PLANE;
289 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
291 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
292 ERR("Can't find a suitable iPixelFormat\n");
295 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
296 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
298 /* Create a GL context */
299 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
301 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
305 /* Make it the current GL context */
306 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
307 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
313 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
314 wined3d_fake_gl_context_ref++;
315 wined3d_fake_gl_context_available = TRUE;
316 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
319 if(wined3d_fake_gl_context_hdc)
320 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
321 wined3d_fake_gl_context_hdc = NULL;
322 if(wined3d_fake_gl_context_hwnd)
323 DestroyWindow(wined3d_fake_gl_context_hwnd);
324 wined3d_fake_gl_context_hwnd = NULL;
325 if(glCtx) pwglDeleteContext(glCtx);
326 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
330 /* Adjust the amount of used texture memory */
331 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
332 struct WineD3DAdapter *adapter = D3DDevice->adapter;
334 adapter->UsedTextureRam += glram;
335 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
336 return adapter->UsedTextureRam;
339 /**********************************************************
340 * IUnknown parts follows
341 **********************************************************/
343 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
345 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
347 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
348 if (IsEqualGUID(riid, &IID_IUnknown)
349 || IsEqualGUID(riid, &IID_IWineD3DBase)
350 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
351 IUnknown_AddRef(iface);
356 return E_NOINTERFACE;
359 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
360 IWineD3DImpl *This = (IWineD3DImpl *)iface;
361 ULONG refCount = InterlockedIncrement(&This->ref);
363 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
367 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
368 IWineD3DImpl *This = (IWineD3DImpl *)iface;
370 TRACE("(%p) : Releasing from %d\n", This, This->ref);
371 ref = InterlockedDecrement(&This->ref);
375 for (i = 0; i < This->adapter_count; ++i)
377 HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
379 HeapFree(GetProcessHeap(), 0, This);
385 /* Set the shader type for this device, depending on the given capabilities,
386 * the device type, and the user preferences in wined3d_settings */
388 static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
390 if (wined3d_settings.vs_mode == VS_NONE) {
391 *vs_selected = SHADER_NONE;
392 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
393 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
394 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
395 * shaders only on this card. */
396 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
397 *vs_selected = SHADER_ARB;
399 *vs_selected = SHADER_GLSL;
400 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
401 *vs_selected = SHADER_ARB;
403 *vs_selected = SHADER_NONE;
406 if (wined3d_settings.ps_mode == PS_NONE) {
407 *ps_selected = SHADER_NONE;
408 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
409 *ps_selected = SHADER_GLSL;
410 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
411 *ps_selected = SHADER_ARB;
412 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
413 *ps_selected = SHADER_ATI;
415 *ps_selected = SHADER_NONE;
419 /** Select the number of report maximum shader constants based on the selected shader modes */
420 static void select_shader_max_constants(
421 int ps_selected_mode,
422 int vs_selected_mode,
423 WineD3D_GL_Info *gl_info) {
425 switch (vs_selected_mode) {
427 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
428 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
431 /* We have to subtract any other PARAMs that we might use in our shader programs.
432 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
433 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
434 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
437 gl_info->max_vshader_constantsF = 0;
441 switch (ps_selected_mode) {
443 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
444 * In theory the texbem instruction may need one more shader constant too. But lets assume
445 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
446 * and lets not take away a uniform needlessly from all other shaders.
448 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
451 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
452 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
454 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
457 gl_info->max_pshader_constantsF = 0;
462 /**********************************************************
463 * IWineD3D parts follows
464 **********************************************************/
466 static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info)
470 const char *testcode =
472 "PARAM C[66] = { program.env[0..65] };\n"
474 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
475 "ARL A0.x, zero.x;\n"
476 "MOV result.position, C[A0.x + 65];\n"
480 GL_EXTCALL(glGenProgramsARB(1, &prog));
482 ERR("Failed to create an ARB offset limit test program\n");
484 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
485 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
486 strlen(testcode), testcode));
487 if(glGetError() != 0) {
488 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
489 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
491 } else TRACE("OpenGL implementation allows offsets > 63\n");
493 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
494 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
495 checkGLcall("ARB vp offset limit test cleanup\n");
500 static DWORD ver_for_ext(GL_SupportedExt ext)
503 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
504 if(EXTENSION_MAP[i].extension == ext) {
505 return EXTENSION_MAP[i].version;
511 static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
512 const char *GL_Extensions = NULL;
513 const char *WGL_Extensions = NULL;
514 const char *gl_string = NULL;
515 const char *gl_string_cursor = NULL;
517 GLfloat gl_floatv[2];
518 int major = 1, minor = 0;
519 BOOL return_value = TRUE;
522 unsigned int vidmem=0;
524 TRACE_(d3d_caps)("(%p)\n", gl_info);
528 gl_string = (const char *) glGetString(GL_RENDERER);
529 if (!gl_string) gl_string = "None";
530 strcpy(gl_info->gl_renderer, gl_string);
532 gl_string = (const char *) glGetString(GL_VENDOR);
533 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
534 if (gl_string != NULL) {
535 /* Fill in the GL vendor */
536 if (strstr(gl_string, "NVIDIA")) {
537 gl_info->gl_vendor = VENDOR_NVIDIA;
538 } else if (strstr(gl_string, "ATI")) {
539 gl_info->gl_vendor = VENDOR_ATI;
540 } else if (strstr(gl_string, "Intel(R)") ||
541 strstr(gl_info->gl_renderer, "Intel(R)") ||
542 strstr(gl_string, "Intel Inc.")) {
543 gl_info->gl_vendor = VENDOR_INTEL;
544 } else if (strstr(gl_string, "Mesa")) {
545 gl_info->gl_vendor = VENDOR_MESA;
547 gl_info->gl_vendor = VENDOR_WINE;
550 gl_info->gl_vendor = VENDOR_WINE;
554 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
556 /* Parse the GL_VERSION field into major and minor information */
557 gl_string = (const char *) glGetString(GL_VERSION);
558 if (gl_string != NULL) {
560 /* First, parse the generic opengl version. This is supposed not to be convoluted with
561 * driver specific information
563 gl_string_cursor = gl_string;
564 major = atoi(gl_string_cursor);
566 ERR("Invalid opengl major version: %d\n", major);
568 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
571 if (*gl_string_cursor++ != '.') {
572 ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
574 minor = atoi(gl_string_cursor);
575 TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
576 gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
578 /* Now parse the driver specific string which we'll report to the app */
579 switch (gl_info->gl_vendor) {
581 gl_string_cursor = strstr(gl_string, "NVIDIA");
582 if (!gl_string_cursor) {
583 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
587 gl_string_cursor = strstr(gl_string_cursor, " ");
588 if (!gl_string_cursor) {
589 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
593 while (*gl_string_cursor == ' ') {
597 if (!*gl_string_cursor) {
598 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
602 major = atoi(gl_string_cursor);
603 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
607 if (*gl_string_cursor++ != '.') {
608 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
612 minor = atoi(gl_string_cursor);
613 minor = major*100+minor;
620 gl_string_cursor = strchr(gl_string, '-');
621 if (gl_string_cursor) {
625 /* Check if version number is of the form x.y.z */
626 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
628 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
630 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
632 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
635 /* Mark version number as malformed */
637 gl_string_cursor = 0;
640 if (!gl_string_cursor)
641 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
643 major = *gl_string_cursor - '0';
644 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
649 /* Apple and Mesa version strings look differently, but both provide intel drivers */
650 if(strstr(gl_string, "APPLE")) {
651 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
652 * We only need the first part, and use the APPLE as identification
655 gl_string_cursor = gl_string;
656 major = atoi(gl_string_cursor);
657 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
661 if (*gl_string_cursor++ != '.') {
662 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
666 minor = atoi(gl_string_cursor);
671 gl_string_cursor = strstr(gl_string, "Mesa");
672 gl_string_cursor = strstr(gl_string_cursor, " ");
673 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
674 if (*gl_string_cursor) {
678 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
679 tmp[cursor++] = *gl_string_cursor;
685 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
689 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
690 tmp[cursor++] = *gl_string_cursor;
702 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
703 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
704 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
705 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
707 FIXME("OpenGL driver did not return version information\n");
708 gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
709 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
712 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
715 * Initialize openGL extension related variables
716 * with Default values
718 memset(gl_info->supported, 0, sizeof(gl_info->supported));
719 gl_info->max_buffers = 1;
720 gl_info->max_textures = 1;
721 gl_info->max_texture_stages = 1;
722 gl_info->max_fragment_samplers = 1;
723 gl_info->max_vertex_samplers = 0;
724 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
725 gl_info->max_sampler_stages = 1;
726 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
727 gl_info->ps_arb_max_temps = 0;
728 gl_info->ps_arb_max_instructions = 0;
729 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
730 gl_info->vs_arb_max_temps = 0;
731 gl_info->vs_arb_max_instructions = 0;
732 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
733 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
734 gl_info->vs_glsl_constantsF = 0;
735 gl_info->ps_glsl_constantsF = 0;
736 gl_info->vs_arb_constantsF = 0;
737 gl_info->ps_arb_constantsF = 0;
739 /* Retrieve opengl defaults */
740 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
741 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
742 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
744 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
745 gl_info->max_lights = gl_max;
746 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
748 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
749 gl_info->max_texture_size = gl_max;
750 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
752 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
753 gl_info->max_pointsizemin = gl_floatv[0];
754 gl_info->max_pointsize = gl_floatv[1];
755 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
757 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
758 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
759 TRACE_(d3d_caps)("GL_Extensions reported:\n");
761 if (NULL == GL_Extensions) {
762 ERR(" GL_Extensions returns NULL\n");
764 while (*GL_Extensions != 0x00) {
769 while (isspace(*GL_Extensions)) GL_Extensions++;
770 Start = GL_Extensions;
771 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
775 len = GL_Extensions - Start;
776 if (len == 0 || len >= sizeof(ThisExtn))
779 memcpy(ThisExtn, Start, len);
780 ThisExtn[len] = '\0';
781 TRACE_(d3d_caps)("- %s\n", ThisExtn);
783 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
784 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
785 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
786 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
794 /* Now work out what GL support this card really has */
795 #define USE_GL_FUNC(type, pfn, ext, replace) { \
796 DWORD ver = ver_for_ext(ext); \
797 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
798 else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
799 else gl_info->pfn = NULL; \
804 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
809 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
810 * loading the functions, otherwise the code above will load the extension entry points instead of the
811 * core functions, which may not work
813 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
814 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
815 EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
816 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
817 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
821 if (gl_info->supported[APPLE_FENCE]) {
822 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
823 * The apple extension interacts with some other apple exts. Disable the NV
824 * extension if the apple one is support to prevent confusion in other parts
827 gl_info->supported[NV_FENCE] = FALSE;
829 if (gl_info->supported[APPLE_FLOAT_PIXELS]) {
830 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
832 * The enums are the same:
833 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
834 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
835 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
836 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
837 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
839 if(!gl_info->supported[ARB_TEXTURE_FLOAT]) {
840 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n");
841 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
843 if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) {
844 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n");
845 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
848 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
849 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
850 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
852 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
853 if(gl_info->supported[NV_REGISTER_COMBINERS]) {
854 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
855 * are supported. The nv extensions provide the same functionality as the
856 * ATI one, and a bit more(signed pixelformats)
858 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
861 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
862 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
863 gl_info->max_buffers = gl_max;
864 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
866 if (gl_info->supported[ARB_MULTITEXTURE]) {
867 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
868 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
869 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
871 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
873 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
874 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
876 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
878 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
880 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
882 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
883 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
885 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
887 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
889 if (gl_info->supported[ARB_VERTEX_SHADER]) {
891 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
892 gl_info->max_vertex_samplers = tmp;
893 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
894 gl_info->max_combined_samplers = tmp;
896 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
897 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
898 * an issue because then the sampler setup only depends on the two shaders. If a pixel
899 * shader is used with fixed function vertex processing we're fine too because fixed function
900 * vertex processing doesn't use any samplers. If fixed function fragment processing is
901 * used we have to make sure that all vertex sampler setups are valid together with all
902 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
903 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
904 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
905 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
906 * a fixed function pipeline anymore.
908 * So this is just a check to check that our assumption holds true. If not, write a warning
909 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
911 if(gl_info->max_vertex_samplers &&
912 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
913 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
914 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
915 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
916 if( gl_info->max_combined_samplers > MAX_TEXTURES )
917 gl_info->max_vertex_samplers =
918 gl_info->max_combined_samplers - MAX_TEXTURES;
920 gl_info->max_vertex_samplers = 0;
923 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
925 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
926 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
928 if (gl_info->supported[ARB_VERTEX_BLEND]) {
929 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
930 gl_info->max_blends = gl_max;
931 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
933 if (gl_info->supported[EXT_TEXTURE3D]) {
934 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
935 gl_info->max_texture3d_size = gl_max;
936 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
938 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
939 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
940 gl_info->max_anisotropy = gl_max;
941 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
943 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
944 gl_info->ps_arb_version = PS_VERSION_11;
945 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
946 gl_info->ps_arb_constantsF = gl_max;
947 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
948 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
949 gl_info->ps_arb_max_temps = gl_max;
950 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
951 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
952 gl_info->ps_arb_max_instructions = gl_max;
953 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
955 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
956 gl_info->vs_arb_version = VS_VERSION_11;
957 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
958 gl_info->vs_arb_constantsF = gl_max;
959 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
960 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
961 gl_info->vs_arb_max_temps = gl_max;
962 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
963 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
964 gl_info->vs_arb_max_instructions = gl_max;
965 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
967 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
969 if (gl_info->supported[ARB_VERTEX_SHADER]) {
970 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
971 gl_info->vs_glsl_constantsF = gl_max / 4;
972 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
974 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
975 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
976 gl_info->ps_glsl_constantsF = gl_max / 4;
977 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
978 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
979 gl_info->max_glsl_varyings = gl_max;
980 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
982 if (gl_info->supported[EXT_VERTEX_SHADER]) {
983 gl_info->vs_ati_version = VS_VERSION_11;
985 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
986 gl_info->vs_nv_version = VS_VERSION_30;
987 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
988 gl_info->vs_nv_version = VS_VERSION_20;
989 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
990 gl_info->vs_nv_version = VS_VERSION_11;
991 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
992 gl_info->vs_nv_version = VS_VERSION_10;
994 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
995 gl_info->ps_nv_version = PS_VERSION_30;
996 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
997 gl_info->ps_nv_version = PS_VERSION_20;
999 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) {
1000 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
1002 gl_info->max_shininess = 128.0;
1004 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
1005 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
1006 * This saves a few redundant glDisable calls
1008 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1010 if(gl_info->supported[ATI_FRAGMENT_SHADER]) {
1011 /* Disable NV_register_combiners and fragment shader if this is supported.
1012 * generally the NV extensions are preferred over the ATI ones, and this
1013 * extension is disabled if register_combiners and texture_shader2 are both
1014 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1015 * fragment processing support
1017 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1018 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1019 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1020 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1021 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
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 PBuffer offscreen rendering mode.\n");
1035 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
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
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
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) {
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 GTX - highend */
1092 if(strstr(gl_info->gl_renderer, "GTX 280")) {
1093 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1096 /* Geforce9 - highend */
1097 else if(strstr(gl_info->gl_renderer, "9800")) {
1098 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1101 /* Geforce9 - midend */
1102 else if(strstr(gl_info->gl_renderer, "9600")) {
1103 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1104 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1106 /* Geforce8 - highend */
1107 else if (strstr(gl_info->gl_renderer, "8800")) {
1108 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1109 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1111 /* Geforce8 - midend mobile */
1112 else if(strstr(gl_info->gl_renderer, "8600 M")) {
1113 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1116 /* Geforce8 - midend */
1117 else if(strstr(gl_info->gl_renderer, "8600") ||
1118 strstr(gl_info->gl_renderer, "8700"))
1120 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1123 /* Geforce8 - lowend */
1124 else if(strstr(gl_info->gl_renderer, "8300") ||
1125 strstr(gl_info->gl_renderer, "8400") ||
1126 strstr(gl_info->gl_renderer, "8500"))
1128 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1129 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1131 /* Geforce7 - highend */
1132 else if(strstr(gl_info->gl_renderer, "7800") ||
1133 strstr(gl_info->gl_renderer, "7900") ||
1134 strstr(gl_info->gl_renderer, "7950") ||
1135 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1136 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1138 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1139 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1141 /* Geforce7 midend */
1142 else if(strstr(gl_info->gl_renderer, "7600") ||
1143 strstr(gl_info->gl_renderer, "7700")) {
1144 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1145 vidmem = 256; /* The 7600 uses 256-512MB */
1146 /* Geforce7 lower medium */
1147 } else if(strstr(gl_info->gl_renderer, "7400")) {
1148 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1149 vidmem = 256; /* The 7400 uses 256-512MB */
1151 /* Geforce7 lowend */
1152 else if(strstr(gl_info->gl_renderer, "7300")) {
1153 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1154 vidmem = 256; /* Mac Pros with this card have 256 MB */
1156 /* Geforce6 highend */
1157 else if(strstr(gl_info->gl_renderer, "6800"))
1159 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1160 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1162 /* Geforce6 - midend */
1163 else if(strstr(gl_info->gl_renderer, "6600") ||
1164 strstr(gl_info->gl_renderer, "6610") ||
1165 strstr(gl_info->gl_renderer, "6700"))
1167 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1168 vidmem = 128; /* A 6600GT has 128-256MB */
1170 /* Geforce6/7 lowend */
1172 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1175 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1176 /* GeforceFX - highend */
1177 if (strstr(gl_info->gl_renderer, "5800") ||
1178 strstr(gl_info->gl_renderer, "5900") ||
1179 strstr(gl_info->gl_renderer, "5950") ||
1180 strstr(gl_info->gl_renderer, "Quadro FX"))
1182 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1183 vidmem = 256; /* 5800-5900 cards use 256MB */
1185 /* GeforceFX - midend */
1186 else if(strstr(gl_info->gl_renderer, "5600") ||
1187 strstr(gl_info->gl_renderer, "5650") ||
1188 strstr(gl_info->gl_renderer, "5700") ||
1189 strstr(gl_info->gl_renderer, "5750"))
1191 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1192 vidmem = 128; /* A 5600 uses 128-256MB */
1194 /* GeforceFX - lowend */
1196 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1197 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1199 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1200 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1201 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1202 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1205 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1206 vidmem = 64; /* Geforce3 cards have 64-128MB */
1208 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1209 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1210 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1211 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1213 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1214 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1215 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1217 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1218 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1219 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1222 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1223 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1226 if (strstr(gl_info->gl_renderer, "TNT2")) {
1227 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1228 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1231 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1232 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1237 if(WINE_D3D9_CAPABLE(gl_info)) {
1238 /* Radeon R6xx HD2900/HD3800 - highend */
1239 if (strstr(gl_info->gl_renderer, "HD 2900") ||
1240 strstr(gl_info->gl_renderer, "HD 3870") ||
1241 strstr(gl_info->gl_renderer, "HD 3850"))
1243 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1244 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1246 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1247 else if (strstr(gl_info->gl_renderer, "HD 2600") ||
1248 strstr(gl_info->gl_renderer, "HD 3830") ||
1249 strstr(gl_info->gl_renderer, "HD 3690") ||
1250 strstr(gl_info->gl_renderer, "HD 3650"))
1252 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1253 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1255 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1256 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1257 strstr(gl_info->gl_renderer, "HD 2400") ||
1258 strstr(gl_info->gl_renderer, "HD 3470") ||
1259 strstr(gl_info->gl_renderer, "HD 3450") ||
1260 strstr(gl_info->gl_renderer, "HD 3430"))
1262 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1263 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1265 /* Radeon R6xx/R7xx integrated */
1266 else if (strstr(gl_info->gl_renderer, "HD 3100") ||
1267 strstr(gl_info->gl_renderer, "HD 3200") ||
1268 strstr(gl_info->gl_renderer, "HD 3300"))
1270 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1271 vidmem = 128; /* 128MB */
1274 else if (strstr(gl_info->gl_renderer, "X1600") ||
1275 strstr(gl_info->gl_renderer, "X1650") ||
1276 strstr(gl_info->gl_renderer, "X1800") ||
1277 strstr(gl_info->gl_renderer, "X1900") ||
1278 strstr(gl_info->gl_renderer, "X1950"))
1280 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1281 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1283 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1284 else if(strstr(gl_info->gl_renderer, "X700") ||
1285 strstr(gl_info->gl_renderer, "X800") ||
1286 strstr(gl_info->gl_renderer, "X850") ||
1287 strstr(gl_info->gl_renderer, "X1300") ||
1288 strstr(gl_info->gl_renderer, "X1400") ||
1289 strstr(gl_info->gl_renderer, "X1450") ||
1290 strstr(gl_info->gl_renderer, "X1550"))
1292 gl_info->gl_card = CARD_ATI_RADEON_X700;
1293 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1295 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1296 else if(strstr(gl_info->gl_renderer, "Radeon Xpress"))
1298 gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M;
1299 vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1303 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1304 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1306 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1307 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1308 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1309 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1310 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1311 vidmem = 32; /* There are models with up to 64MB */
1313 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1314 vidmem = 16; /* There are 16-32MB models */
1318 if (strstr(gl_info->gl_renderer, "GMA 950") ||
1319 strstr(gl_info->gl_renderer, "945GM")) {
1320 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1321 gl_info->gl_card = CARD_INTEL_I945GM;
1323 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1324 gl_info->gl_card = CARD_INTEL_I915GM;
1325 } else if (strstr(gl_info->gl_renderer, "915G")) {
1326 gl_info->gl_card = CARD_INTEL_I915G;
1327 } else if (strstr(gl_info->gl_renderer, "865G")) {
1328 gl_info->gl_card = CARD_INTEL_I865G;
1329 } else if (strstr(gl_info->gl_renderer, "855G")) {
1330 gl_info->gl_card = CARD_INTEL_I855G;
1331 } else if (strstr(gl_info->gl_renderer, "830G")) {
1332 gl_info->gl_card = CARD_INTEL_I830G;
1334 gl_info->gl_card = CARD_INTEL_I915G;
1340 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1341 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1342 * them a good generic choice.
1344 gl_info->gl_vendor = VENDOR_NVIDIA;
1345 if(WINE_D3D9_CAPABLE(gl_info))
1346 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1347 else if(WINE_D3D8_CAPABLE(gl_info))
1348 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1349 else if(WINE_D3D7_CAPABLE(gl_info))
1350 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1351 else if(WINE_D3D6_CAPABLE(gl_info))
1352 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1354 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1356 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1358 /* If we have an estimate use it, else default to 64MB; */
1360 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1362 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1364 /* Load all the lookup tables */
1365 for (i = 0; i < MAX_LOOKUPS; i++) {
1366 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1369 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1370 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1371 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1372 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1373 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1374 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1375 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1376 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1377 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1378 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1380 magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
1381 magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
1382 magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
1383 magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1384 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1387 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1388 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
1389 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
1390 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
1391 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1392 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1393 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1394 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1395 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1396 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
1397 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1398 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
1399 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1400 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
1401 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1403 /* TODO: config lookups */
1405 /* Make sure there's an active HDC else the WGL extensions will fail */
1406 hdc = pwglGetCurrentDC();
1408 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1409 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1411 if (NULL == WGL_Extensions) {
1412 ERR(" WGL_Extensions returns NULL\n");
1414 while (*WGL_Extensions != 0x00) {
1419 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1420 Start = WGL_Extensions;
1421 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1425 len = WGL_Extensions - Start;
1426 if (len == 0 || len >= sizeof(ThisExtn))
1429 memcpy(ThisExtn, Start, len);
1430 ThisExtn[len] = '\0';
1431 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1433 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1434 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1435 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1437 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
1438 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
1439 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
1441 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1442 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1443 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1450 return return_value;
1453 /**********************************************************
1454 * IWineD3D implementation follows
1455 **********************************************************/
1457 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1458 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1460 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
1462 return This->adapter_count;
1465 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1466 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1467 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1471 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1472 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1474 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1476 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1480 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1483 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1484 of the same bpp but different resolutions */
1486 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1487 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1488 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1489 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1491 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1495 /* TODO: Store modes per adapter and read it from the adapter structure */
1496 if (Adapter == 0) { /* Display */
1500 if (!DEBUG_SINGLE_MODE) {
1503 ZeroMemory(&DevModeW, sizeof(DevModeW));
1504 DevModeW.dmSize = sizeof(DevModeW);
1505 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1509 case WINED3DFMT_UNKNOWN:
1510 /* This is for D3D8, do not enumerate P8 here */
1511 if (DevModeW.dmBitsPerPel == 32 ||
1512 DevModeW.dmBitsPerPel == 16) i++;
1514 case WINED3DFMT_X8R8G8B8:
1515 if (DevModeW.dmBitsPerPel == 32) i++;
1517 case WINED3DFMT_R5G6B5:
1518 if (DevModeW.dmBitsPerPel == 16) i++;
1521 if (DevModeW.dmBitsPerPel == 8) i++;
1524 /* Skip other modes as they do not match the requested format */
1533 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1536 FIXME_(d3d_caps)("Adapter not primary display\n");
1541 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1542 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1543 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1544 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1546 /* Validate the parameters as much as possible */
1547 if (NULL == pMode ||
1548 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1549 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1550 return WINED3DERR_INVALIDCALL;
1553 /* TODO: Store modes per adapter and read it from the adapter structure */
1554 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1560 ZeroMemory(&DevModeW, sizeof(DevModeW));
1561 DevModeW.dmSize = sizeof(DevModeW);
1563 /* If we are filtering to a specific format (D3D9), then need to skip
1564 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1565 just count through the ones with valid bit depths */
1566 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1569 case WINED3DFMT_UNKNOWN:
1570 /* This is D3D8. Do not enumerate P8 here */
1571 if (DevModeW.dmBitsPerPel == 32 ||
1572 DevModeW.dmBitsPerPel == 16) i++;
1574 case WINED3DFMT_X8R8G8B8:
1575 if (DevModeW.dmBitsPerPel == 32) i++;
1577 case WINED3DFMT_R5G6B5:
1578 if (DevModeW.dmBitsPerPel == 16) i++;
1581 if (DevModeW.dmBitsPerPel == 8) i++;
1584 /* Modes that don't match what we support can get an early-out */
1585 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1586 return WINED3DERR_INVALIDCALL;
1591 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1592 return WINED3DERR_INVALIDCALL;
1596 /* Now get the display mode via the calculated index */
1597 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1598 pMode->Width = DevModeW.dmPelsWidth;
1599 pMode->Height = DevModeW.dmPelsHeight;
1600 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1601 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1602 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1604 if (Format == WINED3DFMT_UNKNOWN) {
1605 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1607 pMode->Format = Format;
1610 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1611 return WINED3DERR_INVALIDCALL;
1614 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1615 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1616 DevModeW.dmBitsPerPel);
1618 } else if (DEBUG_SINGLE_MODE) {
1619 /* Return one setting of the format requested */
1620 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1622 pMode->Height = 600;
1623 pMode->RefreshRate = 60;
1624 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1626 FIXME_(d3d_caps)("Adapter not primary display\n");
1632 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1633 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1634 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1636 if (NULL == pMode ||
1637 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1638 return WINED3DERR_INVALIDCALL;
1641 if (Adapter == 0) { /* Display */
1645 ZeroMemory(&DevModeW, sizeof(DevModeW));
1646 DevModeW.dmSize = sizeof(DevModeW);
1648 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1649 pMode->Width = DevModeW.dmPelsWidth;
1650 pMode->Height = DevModeW.dmPelsHeight;
1651 bpp = DevModeW.dmBitsPerPel;
1652 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1653 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1655 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1658 pMode->Format = pixelformat_for_depth(bpp);
1660 FIXME_(d3d_caps)("Adapter not primary display\n");
1663 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1664 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1668 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1669 and fields being inserted in the middle, a new structure is used in place */
1670 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1671 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1672 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1674 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1676 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1677 return WINED3DERR_INVALIDCALL;
1680 /* Return the information requested */
1681 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1682 strcpy(pIdentifier->Driver, This->adapters[Adapter].driver);
1683 strcpy(pIdentifier->Description, This->adapters[Adapter].description);
1685 /* Note dx8 doesn't supply a DeviceName */
1686 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1687 pIdentifier->DriverVersion->u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
1688 pIdentifier->DriverVersion->u.LowPart = This->adapters[Adapter].gl_info.driver_version;
1689 *(pIdentifier->VendorId) = This->adapters[Adapter].gl_info.gl_vendor;
1690 *(pIdentifier->DeviceId) = This->adapters[Adapter].gl_info.gl_card;
1691 *(pIdentifier->SubSysId) = 0;
1692 *(pIdentifier->Revision) = 0;
1693 *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID;
1695 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1697 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
1698 *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id;
1701 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1703 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
1704 *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id;
1707 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1708 *(pIdentifier->WHQLLevel) = 0;
1710 *(pIdentifier->WHQLLevel) = 1;
1716 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_GL_Info *gl_info,
1717 const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format)
1719 short redSize, greenSize, blueSize, alphaSize, colorBits;
1724 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
1725 if (!getColorBits(gl_info, Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
1727 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1731 if(cfg->redSize < redSize)
1734 if(cfg->greenSize < greenSize)
1737 if(cfg->blueSize < blueSize)
1740 if(cfg->alphaSize < alphaSize)
1744 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
1745 if(Format == WINED3DFMT_R16_FLOAT)
1746 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1747 if(Format == WINED3DFMT_R16G16_FLOAT)
1748 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1749 if(Format == WINED3DFMT_R16G16B16A16_FLOAT)
1750 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
1751 if(Format == WINED3DFMT_R32_FLOAT)
1752 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1753 if(Format == WINED3DFMT_R32G32_FLOAT)
1754 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1755 if(Format == WINED3DFMT_R32G32B32A32_FLOAT)
1756 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
1758 /* Probably a color index mode */
1765 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_GL_Info *gl_info,
1766 const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format)
1768 short depthSize, stencilSize;
1769 BOOL lockable = FALSE;
1774 if (!getDepthStencilBits(gl_info, Format, &depthSize, &stencilSize))
1776 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1780 if((Format == WINED3DFMT_D16_LOCKABLE) || (Format == WINED3DFMT_D32F_LOCKABLE))
1783 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
1784 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
1785 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
1786 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
1789 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
1790 * allow more stencil bits than requested. */
1791 if(cfg->stencilSize < stencilSize)
1797 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1798 WINED3DFORMAT AdapterFormat,
1799 WINED3DFORMAT RenderTargetFormat,
1800 WINED3DFORMAT DepthStencilFormat) {
1801 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1803 const WineD3D_PixelFormat *cfgs;
1804 const struct WineD3DAdapter *adapter;
1807 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1809 DeviceType, debug_d3ddevicetype(DeviceType),
1810 AdapterFormat, debug_d3dformat(AdapterFormat),
1811 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1812 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1814 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1815 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1816 return WINED3DERR_INVALIDCALL;
1819 adapter = &This->adapters[Adapter];
1820 cfgs = adapter->cfgs;
1821 nCfgs = adapter->nCfgs;
1822 for (it = 0; it < nCfgs; ++it) {
1823 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], RenderTargetFormat))
1825 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], DepthStencilFormat))
1827 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1832 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1834 return WINED3DERR_NOTAVAILABLE;
1837 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1838 WINED3DFORMAT SurfaceFormat,
1839 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1841 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1842 const struct GlPixelFormatDesc *glDesc;
1843 const struct WineD3DAdapter *adapter;
1845 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1848 DeviceType, debug_d3ddevicetype(DeviceType),
1849 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1854 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1855 return WINED3DERR_INVALIDCALL;
1858 /* TODO: handle Windowed, add more quality levels */
1860 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1862 /* By default multisampling is disabled right now as it causes issues
1863 * on some Nvidia driver versions and it doesn't work well in combination
1865 if(!wined3d_settings.allow_multisampling)
1866 return WINED3DERR_NOTAVAILABLE;
1868 adapter = &This->adapters[Adapter];
1869 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
1870 if (!glDesc) return WINED3DERR_INVALIDCALL;
1872 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
1874 const WineD3D_PixelFormat *cfgs;
1876 cfgs = adapter->cfgs;
1877 nCfgs = adapter->nCfgs;
1878 for(i=0; i<nCfgs; i++) {
1879 if(cfgs[i].numSamples != MultiSampleType)
1882 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], SurfaceFormat))
1885 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1888 *pQualityLevels = 1; /* Guess at a value! */
1892 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
1893 short redSize, greenSize, blueSize, alphaSize, colorBits;
1895 const WineD3D_PixelFormat *cfgs;
1897 if (!getColorBits(&adapter->gl_info, SurfaceFormat, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
1899 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
1900 return WINED3DERR_NOTAVAILABLE;
1903 cfgs = adapter->cfgs;
1904 nCfgs = adapter->nCfgs;
1905 for(i=0; i<nCfgs; i++) {
1906 if(cfgs[i].numSamples != MultiSampleType)
1908 if(cfgs[i].redSize != redSize)
1910 if(cfgs[i].greenSize != greenSize)
1912 if(cfgs[i].blueSize != blueSize)
1914 if(cfgs[i].alphaSize != alphaSize)
1917 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1920 *pQualityLevels = 1; /* Guess at a value! */
1924 return WINED3DERR_NOTAVAILABLE;
1927 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1928 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1930 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1931 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1934 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1937 DeviceType, debug_d3ddevicetype(DeviceType),
1938 DisplayFormat, debug_d3dformat(DisplayFormat),
1939 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1942 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1943 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1944 return WINED3DERR_INVALIDCALL;
1947 /* The task of this function is to check whether a certain display / backbuffer format
1948 * combination is available on the given adapter. In fullscreen mode microsoft specified
1949 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
1950 * and display format should match exactly.
1951 * In windowed mode format conversion can occur and this depends on the driver. When format
1952 * conversion is done, this function should nevertheless fail and applications need to use
1953 * CheckDeviceFormatConversion.
1954 * At the moment we assume that fullscreen and windowed have the same capabilities */
1956 /* There are only 4 display formats */
1957 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
1958 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
1959 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
1960 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
1962 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
1963 return WINED3DERR_NOTAVAILABLE;
1966 /* If the requested DisplayFormat is not available, don't continue */
1967 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
1969 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
1970 return WINED3DERR_NOTAVAILABLE;
1973 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
1974 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
1975 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
1976 return WINED3DERR_NOTAVAILABLE;
1979 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
1980 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
1981 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1982 return WINED3DERR_NOTAVAILABLE;
1985 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
1986 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
1987 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1988 return WINED3DERR_NOTAVAILABLE;
1991 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
1992 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
1993 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1994 return WINED3DERR_NOTAVAILABLE;
1997 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
1998 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
1999 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2000 return WINED3DERR_NOTAVAILABLE;
2003 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2004 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2006 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2012 /* Check if we support bumpmapping for a format */
2013 static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
2014 WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2016 const struct fragment_pipeline *fp;
2017 const struct GlPixelFormatDesc *glDesc;
2019 switch(CheckFormat) {
2020 case WINED3DFMT_R8G8_SNORM:
2021 case WINED3DFMT_R16G16_SNORM:
2022 case WINED3DFMT_L6V5U5:
2023 case WINED3DFMT_X8L8V8U8:
2024 case WINED3DFMT_R8G8B8A8_SNORM:
2025 /* Ask the fixed function pipeline implementation if it can deal
2026 * with the conversion. If we've got a GL extension giving native
2027 * support this will be an identity conversion. */
2028 glDesc = getFormatDescEntry(CheckFormat, &adapter->gl_info);
2029 fp = select_fragment_implementation(adapter, DeviceType);
2030 if (fp->color_fixup_supported(glDesc->color_fixup))
2032 TRACE_(d3d_caps)("[OK]\n");
2035 TRACE_(d3d_caps)("[FAILED]\n");
2039 TRACE_(d3d_caps)("[FAILED]\n");
2044 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2045 static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
2046 WINED3DFORMAT DisplayFormat, WINED3DFORMAT DepthStencilFormat)
2049 const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2051 /* Fail if we weren't able to get a description of the format */
2052 if (!glDesc) return FALSE;
2054 /* Only allow depth/stencil formats */
2055 if(!(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
2058 /* Walk through all WGL pixel formats to find a match */
2059 for (it = 0; it < adapter->nCfgs; ++it)
2061 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2062 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, DisplayFormat))
2064 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, DepthStencilFormat))
2074 static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, WINED3DFORMAT CheckFormat)
2076 const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(CheckFormat, &adapter->gl_info);
2078 /* Fail if we weren't able to get a description of the format */
2079 if (!glDesc) return FALSE;
2081 /* The flags entry of a format contains the filtering capability */
2082 if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING)
2088 /* Check the render target capabilities of a format */
2089 static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
2090 WINED3DFORMAT AdapterFormat, WINED3DFORMAT CheckFormat)
2092 const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(CheckFormat, &adapter->gl_info);
2094 /* Fail if we weren't able to get a description of the format */
2095 if (!glDesc) return FALSE;
2097 /* Filter out non-RT formats */
2098 if(!(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET))
2101 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2102 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2104 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2105 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2107 getColorBits(&adapter->gl_info, AdapterFormat,
2108 &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2109 getColorBits(&adapter->gl_info, CheckFormat,
2110 &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2112 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2113 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2114 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2115 TRACE_(d3d_caps)("[FAILED]\n");
2119 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2120 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2121 for (it = 0; it < adapter->nCfgs; ++it)
2123 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2124 &cfgs[it], CheckFormat))
2126 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2130 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2131 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2132 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2135 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2136 for (it = 0; it < adapter->nCfgs; ++it)
2138 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2139 &cfgs[it], CheckFormat))
2141 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2145 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2146 /* For now return TRUE for FBOs until we have some proper checks.
2147 * Note that this function will only be called when the format is around for texturing. */
2153 static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, WINED3DFORMAT CheckFormat)
2155 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2157 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2158 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2159 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2163 switch (CheckFormat) {
2164 case WINED3DFMT_A8R8G8B8:
2165 case WINED3DFMT_X8R8G8B8:
2166 case WINED3DFMT_A4R4G4B4:
2168 case WINED3DFMT_A8L8:
2169 case WINED3DFMT_DXT1:
2170 case WINED3DFMT_DXT2:
2171 case WINED3DFMT_DXT3:
2172 case WINED3DFMT_DXT4:
2173 case WINED3DFMT_DXT5:
2174 TRACE_(d3d_caps)("[OK]\n");
2178 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
2184 static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
2185 WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2187 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2188 * doing the color fixup in shaders.
2189 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2190 if((CheckFormat == WINED3DFMT_X8R8G8B8) || (CheckFormat == WINED3DFMT_A8R8G8B8)) {
2191 int vs_selected_mode;
2192 int ps_selected_mode;
2193 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2195 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2196 TRACE_(d3d_caps)("[OK]\n");
2201 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(CheckFormat));
2205 /* Check if a format support blending in combination with pixel shaders */
2206 static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter, WINED3DFORMAT CheckFormat)
2208 const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(CheckFormat, &adapter->gl_info);
2210 /* Fail if we weren't able to get a description of the format */
2211 if (!glDesc) return FALSE;
2213 /* The flags entry of a format contains the post pixel shader blending capability */
2214 if(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
2220 static BOOL CheckWrapAndMipCapability(UINT Adapter, WINED3DFORMAT CheckFormat) {
2221 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2222 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2223 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2224 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2225 * capability anyway.
2227 * For now lets report this on all formats, but in the future we may want to
2228 * restrict it to some should games need that
2233 /* Check if a texture format is supported on the given adapter */
2234 static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
2235 WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2237 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2238 const shader_backend_t *shader_backend;
2239 const struct fragment_pipeline *fp;
2240 const struct GlPixelFormatDesc *glDesc;
2242 switch (CheckFormat) {
2245 * supported: RGB(A) formats
2247 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2248 case WINED3DFMT_A8R8G8B8:
2249 case WINED3DFMT_X8R8G8B8:
2250 case WINED3DFMT_R5G6B5:
2251 case WINED3DFMT_X1R5G5B5:
2252 case WINED3DFMT_A1R5G5B5:
2253 case WINED3DFMT_A4R4G4B4:
2254 case WINED3DFMT_A8_UNORM:
2255 case WINED3DFMT_X4R4G4B4:
2256 case WINED3DFMT_R8G8B8A8_UNORM:
2257 case WINED3DFMT_X8B8G8R8:
2258 case WINED3DFMT_A2R10G10B10:
2259 case WINED3DFMT_R10G10B10A2_UNORM:
2260 case WINED3DFMT_R16G16_UNORM:
2261 TRACE_(d3d_caps)("[OK]\n");
2264 case WINED3DFMT_R3G3B2:
2265 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2269 * supported: Palettized
2272 TRACE_(d3d_caps)("[OK]\n");
2274 /* No Windows driver offers A8P8, so don't offer it either */
2275 case WINED3DFMT_A8P8:
2279 * Supported: (Alpha)-Luminance
2282 case WINED3DFMT_A8L8:
2283 case WINED3DFMT_L16:
2284 TRACE_(d3d_caps)("[OK]\n");
2287 /* Not supported on Windows, thus disabled */
2288 case WINED3DFMT_A4L4:
2289 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2293 * Supported: Depth/Stencil formats
2295 case WINED3DFMT_D16_LOCKABLE:
2296 case WINED3DFMT_D16_UNORM:
2297 case WINED3DFMT_D15S1:
2298 case WINED3DFMT_D24X8:
2299 case WINED3DFMT_D24X4S4:
2300 case WINED3DFMT_D24S8:
2301 case WINED3DFMT_D24FS8:
2302 case WINED3DFMT_D32:
2303 case WINED3DFMT_D32F_LOCKABLE:
2307 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2308 * GL_NV_texture_shader). Emulated by shaders
2310 case WINED3DFMT_R8G8_SNORM:
2311 case WINED3DFMT_X8L8V8U8:
2312 case WINED3DFMT_L6V5U5:
2313 case WINED3DFMT_R8G8B8A8_SNORM:
2314 case WINED3DFMT_R16G16_SNORM:
2315 /* Ask the shader backend if it can deal with the conversion. If
2316 * we've got a GL extension giving native support this will be an
2317 * identity conversion. */
2318 glDesc = getFormatDescEntry(CheckFormat, &adapter->gl_info);
2319 shader_backend = select_shader_backend(adapter, DeviceType);
2320 if (shader_backend->shader_color_fixup_supported(glDesc->color_fixup))
2322 TRACE_(d3d_caps)("[OK]\n");
2325 TRACE_(d3d_caps)("[FAILED]\n");
2328 case WINED3DFMT_DXT1:
2329 case WINED3DFMT_DXT2:
2330 case WINED3DFMT_DXT3:
2331 case WINED3DFMT_DXT4:
2332 case WINED3DFMT_DXT5:
2333 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2334 TRACE_(d3d_caps)("[OK]\n");
2337 TRACE_(d3d_caps)("[FAILED]\n");
2342 * Odd formats - not supported
2344 case WINED3DFMT_VERTEXDATA:
2345 case WINED3DFMT_R16_UINT:
2346 case WINED3DFMT_R32_UINT:
2347 case WINED3DFMT_R16G16B16A16_SNORM:
2348 case WINED3DFMT_A2W10V10U10:
2349 case WINED3DFMT_W11V11U10:
2350 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2354 * WINED3DFMT_CxV8U8: Not supported right now
2356 case WINED3DFMT_CxV8U8:
2357 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2361 case WINED3DFMT_UYVY:
2362 case WINED3DFMT_YUY2:
2363 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2364 TRACE_(d3d_caps)("[OK]\n");
2367 TRACE_(d3d_caps)("[FAILED]\n");
2369 case WINED3DFMT_YV12:
2370 TRACE_(d3d_caps)("[FAILED]\n");
2374 case WINED3DFMT_R16G16B16A16_UNORM:
2375 case WINED3DFMT_A8R3G3B2:
2376 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2379 /* Floating point formats */
2380 case WINED3DFMT_R16_FLOAT:
2381 case WINED3DFMT_R16G16B16A16_FLOAT:
2382 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2383 TRACE_(d3d_caps)("[OK]\n");
2386 TRACE_(d3d_caps)("[FAILED]\n");
2389 case WINED3DFMT_R32_FLOAT:
2390 case WINED3DFMT_R32G32B32A32_FLOAT:
2391 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2392 TRACE_(d3d_caps)("[OK]\n");
2395 TRACE_(d3d_caps)("[FAILED]\n");
2398 case WINED3DFMT_R16G16_FLOAT:
2399 case WINED3DFMT_R32G32_FLOAT:
2400 if(GL_SUPPORT(ARB_TEXTURE_RG)) {
2401 TRACE_(d3d_caps)("[OK]\n");
2404 TRACE_(d3d_caps)("[FAILED]\n");
2407 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2408 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2409 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2410 * We can do instancing with all shader versions, but we need vertex shaders.
2412 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2413 * to enable instancing. WineD3D doesn't need that and just ignores it.
2415 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2417 case WINEMAKEFOURCC('I','N','S','T'):
2418 TRACE("ATI Instancing check hack\n");
2419 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2420 TRACE_(d3d_caps)("[OK]\n");
2423 TRACE_(d3d_caps)("[FAILED]\n");
2426 /* Some weird FOURCC formats */
2427 case WINED3DFMT_R8G8_B8G8:
2428 case WINED3DFMT_G8R8_G8B8:
2429 case WINED3DFMT_MULTI2_ARGB8:
2430 TRACE_(d3d_caps)("[FAILED]\n");
2433 /* Vendor specific formats */
2434 case WINED3DFMT_ATI2N:
2435 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2436 glDesc = getFormatDescEntry(CheckFormat, &adapter->gl_info);
2437 shader_backend = select_shader_backend(adapter, DeviceType);
2438 fp = select_fragment_implementation(adapter, DeviceType);
2439 if (shader_backend->shader_color_fixup_supported(glDesc->color_fixup)
2440 && fp->color_fixup_supported(glDesc->color_fixup))
2442 TRACE_(d3d_caps)("[OK]\n");
2446 TRACE_(d3d_caps)("[OK]\n");
2449 TRACE_(d3d_caps)("[FAILED]\n");
2452 case WINED3DFMT_NVHU:
2453 case WINED3DFMT_NVHS:
2454 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2455 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2456 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2457 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2458 * Applications have to deal with not having NVHS and NVHU.
2460 TRACE_(d3d_caps)("[FAILED]\n");
2463 case WINED3DFMT_UNKNOWN:
2467 ERR("Unhandled format=%s\n", debug_d3dformat(CheckFormat));
2473 static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, WINED3DFORMAT AdapterFormat,
2474 WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType)
2476 const struct GlPixelFormatDesc *format_desc;
2477 const struct blit_shader *blitter;
2479 if(SurfaceType == SURFACE_GDI) {
2480 switch(CheckFormat) {
2481 case WINED3DFMT_R8G8B8:
2482 case WINED3DFMT_A8R8G8B8:
2483 case WINED3DFMT_X8R8G8B8:
2484 case WINED3DFMT_R5G6B5:
2485 case WINED3DFMT_X1R5G5B5:
2486 case WINED3DFMT_A1R5G5B5:
2487 case WINED3DFMT_A4R4G4B4:
2488 case WINED3DFMT_R3G3B2:
2489 case WINED3DFMT_A8_UNORM:
2490 case WINED3DFMT_A8R3G3B2:
2491 case WINED3DFMT_X4R4G4B4:
2492 case WINED3DFMT_R10G10B10A2_UNORM:
2493 case WINED3DFMT_R8G8B8A8_UNORM:
2494 case WINED3DFMT_X8B8G8R8:
2495 case WINED3DFMT_R16G16_UNORM:
2496 case WINED3DFMT_A2R10G10B10:
2497 case WINED3DFMT_R16G16B16A16_UNORM:
2499 TRACE_(d3d_caps)("[OK]\n");
2502 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
2507 /* All format that are supported for textures are supported for surfaces as well */
2508 if(CheckTextureCapability(adapter, DeviceType, CheckFormat)) return TRUE;
2509 /* All depth stencil formats are supported on surfaces */
2510 if(CheckDepthStencilCapability(adapter, AdapterFormat, CheckFormat)) return TRUE;
2512 /* If opengl can't process the format natively, the blitter may be able to convert it */
2513 format_desc = getFormatDescEntry(CheckFormat, &adapter->gl_info);
2514 blitter = select_blit_implementation(adapter, DeviceType);
2515 if (blitter->color_fixup_supported(format_desc->color_fixup))
2517 TRACE_(d3d_caps)("[OK]\n");
2521 /* Reject other formats */
2522 TRACE_(d3d_caps)("[FAILED]\n");
2526 static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, WINED3DFORMAT CheckFormat)
2528 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2530 if (!GL_LIMITS(vertex_samplers)) {
2531 TRACE_(d3d_caps)("[FAILED]\n");
2535 switch (CheckFormat) {
2536 case WINED3DFMT_R32G32B32A32_FLOAT:
2537 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2538 TRACE_(d3d_caps)("[FAILED]\n");
2541 TRACE_(d3d_caps)("[OK]\n");
2545 TRACE_(d3d_caps)("[FAILED]\n");
2551 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2552 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
2553 WINED3DSURFTYPE SurfaceType) {
2554 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2555 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
2556 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2557 DWORD UsageCaps = 0;
2559 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
2562 DeviceType, debug_d3ddevicetype(DeviceType),
2563 AdapterFormat, debug_d3dformat(AdapterFormat),
2564 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
2565 RType, debug_d3dresourcetype(RType),
2566 CheckFormat, debug_d3dformat(CheckFormat));
2568 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2569 return WINED3DERR_INVALIDCALL;
2572 if(RType == WINED3DRTYPE_CUBETEXTURE) {
2574 if(SurfaceType != SURFACE_OPENGL) {
2575 TRACE("[FAILED]\n");
2576 return WINED3DERR_NOTAVAILABLE;
2579 /* Cubetexture allows:
2580 * - D3DUSAGE_AUTOGENMIPMAP
2581 * - D3DUSAGE_DEPTHSTENCIL
2582 * - D3DUSAGE_DYNAMIC
2583 * - D3DUSAGE_NONSECURE (d3d9ex)
2584 * - D3DUSAGE_RENDERTARGET
2585 * - D3DUSAGE_SOFTWAREPROCESSING
2586 * - D3DUSAGE_QUERY_WRAPANDMIP
2588 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2589 /* Check if the texture format is around */
2590 if (CheckTextureCapability(adapter, DeviceType, CheckFormat))
2592 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2593 /* Check for automatic mipmap generation support */
2594 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2595 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2597 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2598 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2602 /* Always report dynamic locking */
2603 if(Usage & WINED3DUSAGE_DYNAMIC)
2604 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2606 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2607 if(CheckRenderTargetCapability(adapter, AdapterFormat, CheckFormat))
2609 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2611 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2612 return WINED3DERR_NOTAVAILABLE;
2616 /* Always report software processing */
2617 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2618 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2620 /* Check QUERY_FILTER support */
2621 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2622 if (CheckFilterCapability(adapter, CheckFormat))
2624 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2626 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2627 return WINED3DERR_NOTAVAILABLE;
2631 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2632 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2633 if (CheckPostPixelShaderBlendingCapability(adapter, CheckFormat))
2635 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2637 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2638 return WINED3DERR_NOTAVAILABLE;
2642 /* Check QUERY_SRGBREAD support */
2643 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2644 if (CheckSrgbReadCapability(adapter, CheckFormat))
2646 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2648 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2649 return WINED3DERR_NOTAVAILABLE;
2653 /* Check QUERY_SRGBWRITE support */
2654 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2655 if (CheckSrgbWriteCapability(adapter, DeviceType, CheckFormat))
2657 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2659 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2660 return WINED3DERR_NOTAVAILABLE;
2664 /* Check QUERY_VERTEXTEXTURE support */
2665 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2666 if (CheckVertexTextureCapability(adapter, CheckFormat))
2668 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2670 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2671 return WINED3DERR_NOTAVAILABLE;
2675 /* Check QUERY_WRAPANDMIP support */
2676 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2677 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2678 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2680 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2681 return WINED3DERR_NOTAVAILABLE;
2685 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
2686 return WINED3DERR_NOTAVAILABLE;
2689 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
2690 return WINED3DERR_NOTAVAILABLE;
2692 } else if(RType == WINED3DRTYPE_SURFACE) {
2694 * - D3DUSAGE_DEPTHSTENCIL
2695 * - D3DUSAGE_NONSECURE (d3d9ex)
2696 * - D3DUSAGE_RENDERTARGET
2699 if (CheckSurfaceCapability(adapter, AdapterFormat, DeviceType, CheckFormat, SurfaceType))
2701 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2702 if (CheckDepthStencilCapability(adapter, AdapterFormat, CheckFormat))
2704 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2706 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
2707 return WINED3DERR_NOTAVAILABLE;
2711 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2712 if (CheckRenderTargetCapability(adapter, AdapterFormat, CheckFormat))
2714 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2716 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2717 return WINED3DERR_NOTAVAILABLE;
2721 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2722 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2723 if (CheckPostPixelShaderBlendingCapability(adapter, CheckFormat))
2725 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2727 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2728 return WINED3DERR_NOTAVAILABLE;
2732 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
2733 return WINED3DERR_NOTAVAILABLE;
2736 } else if(RType == WINED3DRTYPE_TEXTURE) {
2738 * - D3DUSAGE_AUTOGENMIPMAP
2739 * - D3DUSAGE_DEPTHSTENCIL
2741 * - D3DUSAGE_DYNAMIC
2742 * - D3DUSAGE_NONSECURE (d3d9ex)
2743 * - D3DUSAGE_RENDERTARGET
2744 * - D3DUSAGE_SOFTWAREPROCESSING
2745 * - D3DUSAGE_TEXTAPI (d3d9ex)
2746 * - D3DUSAGE_QUERY_WRAPANDMIP
2749 if(SurfaceType != SURFACE_OPENGL) {
2750 TRACE("[FAILED]\n");
2751 return WINED3DERR_NOTAVAILABLE;
2754 /* Check if the texture format is around */
2755 if (CheckTextureCapability(adapter, DeviceType, CheckFormat))
2757 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2758 /* Check for automatic mipmap generation support */
2759 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2760 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2762 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2763 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2767 /* Always report dynamic locking */
2768 if(Usage & WINED3DUSAGE_DYNAMIC)
2769 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2771 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2772 if (CheckRenderTargetCapability(adapter, AdapterFormat, CheckFormat))
2774 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2776 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2777 return WINED3DERR_NOTAVAILABLE;
2781 /* Always report software processing */
2782 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2783 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2785 /* Check QUERY_FILTER support */
2786 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2787 if (CheckFilterCapability(adapter, CheckFormat))
2789 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2791 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2792 return WINED3DERR_NOTAVAILABLE;
2796 /* Check QUERY_LEGACYBUMPMAP support */
2797 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
2798 if (CheckBumpMapCapability(adapter, DeviceType, CheckFormat))
2800 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
2802 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
2803 return WINED3DERR_NOTAVAILABLE;
2807 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2808 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2809 if (CheckPostPixelShaderBlendingCapability(adapter, CheckFormat))
2811 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2813 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2814 return WINED3DERR_NOTAVAILABLE;
2818 /* Check QUERY_SRGBREAD support */
2819 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2820 if (CheckSrgbReadCapability(adapter, CheckFormat))
2822 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2824 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2825 return WINED3DERR_NOTAVAILABLE;
2829 /* Check QUERY_SRGBWRITE support */
2830 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2831 if (CheckSrgbWriteCapability(adapter, DeviceType, CheckFormat))
2833 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2835 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2836 return WINED3DERR_NOTAVAILABLE;
2840 /* Check QUERY_VERTEXTEXTURE support */
2841 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2842 if (CheckVertexTextureCapability(adapter, CheckFormat))
2844 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2846 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2847 return WINED3DERR_NOTAVAILABLE;
2851 /* Check QUERY_WRAPANDMIP support */
2852 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2853 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2854 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2856 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2857 return WINED3DERR_NOTAVAILABLE;
2861 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2862 if (CheckDepthStencilCapability(adapter, AdapterFormat, CheckFormat))
2864 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2866 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
2867 return WINED3DERR_NOTAVAILABLE;
2871 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
2872 return WINED3DERR_NOTAVAILABLE;
2874 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
2875 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
2876 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
2878 * Volumetexture allows:
2879 * - D3DUSAGE_DYNAMIC
2880 * - D3DUSAGE_NONSECURE (d3d9ex)
2881 * - D3DUSAGE_SOFTWAREPROCESSING
2882 * - D3DUSAGE_QUERY_WRAPANDMIP
2885 if(SurfaceType != SURFACE_OPENGL) {
2886 TRACE("[FAILED]\n");
2887 return WINED3DERR_NOTAVAILABLE;
2890 /* Check volume texture and volume usage caps */
2891 if(GL_SUPPORT(EXT_TEXTURE3D)) {
2892 if (!CheckTextureCapability(adapter, DeviceType, CheckFormat))
2894 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
2895 return WINED3DERR_NOTAVAILABLE;
2898 /* Always report dynamic locking */
2899 if(Usage & WINED3DUSAGE_DYNAMIC)
2900 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2902 /* Always report software processing */
2903 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2904 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2906 /* Check QUERY_FILTER support */
2907 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2908 if (CheckFilterCapability(adapter, CheckFormat))
2910 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2912 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2913 return WINED3DERR_NOTAVAILABLE;
2917 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2918 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2919 if (CheckPostPixelShaderBlendingCapability(adapter, CheckFormat))
2921 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2923 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2924 return WINED3DERR_NOTAVAILABLE;
2928 /* Check QUERY_SRGBREAD support */
2929 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2930 if (CheckSrgbReadCapability(adapter, CheckFormat))
2932 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2934 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2935 return WINED3DERR_NOTAVAILABLE;
2939 /* Check QUERY_SRGBWRITE support */
2940 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2941 if (CheckSrgbWriteCapability(adapter, DeviceType, CheckFormat))
2943 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2945 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2946 return WINED3DERR_NOTAVAILABLE;
2950 /* Check QUERY_VERTEXTEXTURE support */
2951 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2952 if (CheckVertexTextureCapability(adapter, CheckFormat))
2954 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2956 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2957 return WINED3DERR_NOTAVAILABLE;
2961 /* Check QUERY_WRAPANDMIP support */
2962 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2963 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2964 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2966 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2967 return WINED3DERR_NOTAVAILABLE;
2971 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
2972 return WINED3DERR_NOTAVAILABLE;
2975 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
2976 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
2977 * app needing one of those formats, don't advertize them to avoid leading apps into
2978 * temptation. The windows drivers don't support most of those formats on volumes anyway,
2981 switch(CheckFormat) {
2983 case WINED3DFMT_A4L4:
2984 case WINED3DFMT_R32_FLOAT:
2985 case WINED3DFMT_R16_FLOAT:
2986 case WINED3DFMT_X8L8V8U8:
2987 case WINED3DFMT_L6V5U5:
2988 case WINED3DFMT_R16G16_UNORM:
2989 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2990 return WINED3DERR_NOTAVAILABLE;
2992 case WINED3DFMT_R8G8B8A8_SNORM:
2993 case WINED3DFMT_R16G16_SNORM:
2994 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2995 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2996 return WINED3DERR_NOTAVAILABLE;
3000 case WINED3DFMT_R8G8_SNORM:
3001 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3002 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3003 return WINED3DERR_NOTAVAILABLE;
3007 case WINED3DFMT_DXT1:
3008 case WINED3DFMT_DXT2:
3009 case WINED3DFMT_DXT3:
3010 case WINED3DFMT_DXT4:
3011 case WINED3DFMT_DXT5:
3012 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3013 * compressed texture results in an error. While the D3D refrast does
3014 * support s3tc volumes, at least the nvidia windows driver does not, so
3015 * we're free not to support this format.
3017 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3018 return WINED3DERR_NOTAVAILABLE;
3021 /* Do nothing, continue with checking the format below */
3024 } else if((RType == WINED3DRTYPE_INDEXBUFFER) || (RType == WINED3DRTYPE_VERTEXBUFFER)){
3025 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3026 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3027 return WINED3DERR_NOTAVAILABLE;
3030 /* This format is nothing special and it is supported perfectly.
3031 * However, ati and nvidia driver on windows do not mark this format as
3032 * supported (tested with the dxCapsViewer) and pretending to
3033 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
3034 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
3035 * Enable it on dx7. It will need additional checking on dx10 when we support it.
3037 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
3038 TRACE_(d3d_caps)("[FAILED]\n");
3039 return WINED3DERR_NOTAVAILABLE;
3042 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3043 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3044 * usage flags match. */
3045 if(UsageCaps == Usage) {
3047 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3048 return WINED3DOK_NOAUTOGEN;
3050 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);
3051 return WINED3DERR_NOTAVAILABLE;
3055 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3056 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3057 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3059 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3062 DeviceType, debug_d3ddevicetype(DeviceType),
3063 SourceFormat, debug_d3dformat(SourceFormat),
3064 TargetFormat, debug_d3dformat(TargetFormat));
3068 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3070 const shader_backend_t *ret;
3071 int vs_selected_mode;
3072 int ps_selected_mode;
3074 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3075 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3076 ret = &glsl_shader_backend;
3077 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3078 ret = &arb_program_shader_backend;
3080 ret = &none_shader_backend;
3085 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
3086 WINED3DDEVTYPE DeviceType)
3088 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3089 int vs_selected_mode;
3090 int ps_selected_mode;
3092 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3093 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3094 return &arbfp_fragment_pipeline;
3095 } else if(ps_selected_mode == SHADER_ATI) {
3096 return &atifs_fragment_pipeline;
3097 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3098 return &nvts_fragment_pipeline;
3099 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3100 return &nvrc_fragment_pipeline;
3102 return &ffp_fragment_pipeline;
3106 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3108 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3109 int vs_selected_mode;
3110 int ps_selected_mode;
3112 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3113 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3120 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3121 subset of a D3DCAPS9 structure. However, it has to come via a void *
3122 as the d3d8 interface cannot import the d3d9 header */
3123 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3125 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3126 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3127 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3128 int vs_selected_mode;
3129 int ps_selected_mode;
3130 struct shader_caps shader_caps;
3131 struct fragment_caps fragment_caps;
3132 const shader_backend_t *shader_backend;
3133 const struct fragment_pipeline *frag_pipeline = NULL;
3134 DWORD ckey_caps, blit_caps, fx_caps;
3136 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3138 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3139 return WINED3DERR_INVALIDCALL;
3142 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3144 /* This function should *not* be modifying GL caps
3145 * TODO: move the functionality where it belongs */
3146 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
3148 /* ------------------------------------------------
3149 The following fields apply to both d3d8 and d3d9
3150 ------------------------------------------------ */
3151 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3152 pCaps->AdapterOrdinal = Adapter;
3155 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3156 WINED3DCAPS2_FULLSCREENGAMMA |
3157 WINED3DCAPS2_DYNAMICTEXTURES;
3158 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3159 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3162 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3163 WINED3DCAPS3_COPY_TO_VIDMEM |
3164 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3166 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3167 WINED3DPRESENT_INTERVAL_ONE;
3169 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3170 WINED3DCURSORCAPS_LOWRES;
3172 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3173 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3174 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3175 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3176 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3177 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3178 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3179 WINED3DDEVCAPS_PUREDEVICE |
3180 WINED3DDEVCAPS_HWRASTERIZATION |
3181 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3182 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3183 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3184 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3185 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3186 WINED3DDEVCAPS_RTPATCHES;
3188 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3189 WINED3DPMISCCAPS_CULLCCW |
3190 WINED3DPMISCCAPS_CULLCW |
3191 WINED3DPMISCCAPS_COLORWRITEENABLE |
3192 WINED3DPMISCCAPS_CLIPTLVERTS |
3193 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3194 WINED3DPMISCCAPS_MASKZ |
3195 WINED3DPMISCCAPS_BLENDOP |
3196 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3198 WINED3DPMISCCAPS_NULLREFERENCE
3199 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3200 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3201 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3202 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3204 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3205 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3207 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3208 WINED3DPRASTERCAPS_PAT |
3209 WINED3DPRASTERCAPS_WFOG |
3210 WINED3DPRASTERCAPS_ZFOG |
3211 WINED3DPRASTERCAPS_FOGVERTEX |
3212 WINED3DPRASTERCAPS_FOGTABLE |
3213 WINED3DPRASTERCAPS_STIPPLE |
3214 WINED3DPRASTERCAPS_SUBPIXEL |
3215 WINED3DPRASTERCAPS_ZTEST |
3216 WINED3DPRASTERCAPS_SCISSORTEST |
3217 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3218 WINED3DPRASTERCAPS_DEPTHBIAS;
3220 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3221 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3222 WINED3DPRASTERCAPS_ZBIAS |
3223 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3225 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3226 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3229 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3230 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3231 WINED3DPRASTERCAPS_ANTIALIASEDGES
3232 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3233 WINED3DPRASTERCAPS_WBUFFER */
3235 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3236 WINED3DPCMPCAPS_EQUAL |
3237 WINED3DPCMPCAPS_GREATER |
3238 WINED3DPCMPCAPS_GREATEREQUAL |
3239 WINED3DPCMPCAPS_LESS |
3240 WINED3DPCMPCAPS_LESSEQUAL |
3241 WINED3DPCMPCAPS_NEVER |
3242 WINED3DPCMPCAPS_NOTEQUAL;
3244 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3245 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3246 WINED3DPBLENDCAPS_DESTALPHA |
3247 WINED3DPBLENDCAPS_DESTCOLOR |
3248 WINED3DPBLENDCAPS_INVDESTALPHA |
3249 WINED3DPBLENDCAPS_INVDESTCOLOR |
3250 WINED3DPBLENDCAPS_INVSRCALPHA |
3251 WINED3DPBLENDCAPS_INVSRCCOLOR |
3252 WINED3DPBLENDCAPS_ONE |
3253 WINED3DPBLENDCAPS_SRCALPHA |
3254 WINED3DPBLENDCAPS_SRCALPHASAT |
3255 WINED3DPBLENDCAPS_SRCCOLOR |
3256 WINED3DPBLENDCAPS_ZERO;
3258 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3259 WINED3DPBLENDCAPS_DESTCOLOR |
3260 WINED3DPBLENDCAPS_INVDESTALPHA |
3261 WINED3DPBLENDCAPS_INVDESTCOLOR |
3262 WINED3DPBLENDCAPS_INVSRCALPHA |
3263 WINED3DPBLENDCAPS_INVSRCCOLOR |
3264 WINED3DPBLENDCAPS_ONE |
3265 WINED3DPBLENDCAPS_SRCALPHA |
3266 WINED3DPBLENDCAPS_SRCCOLOR |
3267 WINED3DPBLENDCAPS_ZERO;
3268 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3269 * according to the glBlendFunc manpage
3271 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3272 * legacy settings for srcblend only
3275 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3276 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3277 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3281 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3282 WINED3DPCMPCAPS_EQUAL |
3283 WINED3DPCMPCAPS_GREATER |
3284 WINED3DPCMPCAPS_GREATEREQUAL |
3285 WINED3DPCMPCAPS_LESS |
3286 WINED3DPCMPCAPS_LESSEQUAL |
3287 WINED3DPCMPCAPS_NEVER |
3288 WINED3DPCMPCAPS_NOTEQUAL;
3290 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3291 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3292 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3293 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3294 WINED3DPSHADECAPS_COLORFLATRGB |
3295 WINED3DPSHADECAPS_FOGFLAT |
3296 WINED3DPSHADECAPS_FOGGOURAUD |
3297 WINED3DPSHADECAPS_SPECULARFLATRGB;
3299 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3300 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3301 WINED3DPTEXTURECAPS_TRANSPARENCY |
3302 WINED3DPTEXTURECAPS_BORDER |
3303 WINED3DPTEXTURECAPS_MIPMAP |
3304 WINED3DPTEXTURECAPS_PROJECTED |
3305 WINED3DPTEXTURECAPS_PERSPECTIVE;
3307 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3308 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3309 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3312 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3313 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3314 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3315 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3318 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3319 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3320 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3321 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3325 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3326 WINED3DPTFILTERCAPS_MAGFPOINT |
3327 WINED3DPTFILTERCAPS_MINFLINEAR |
3328 WINED3DPTFILTERCAPS_MINFPOINT |
3329 WINED3DPTFILTERCAPS_MIPFLINEAR |
3330 WINED3DPTFILTERCAPS_MIPFPOINT |
3331 WINED3DPTFILTERCAPS_LINEAR |
3332 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3333 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3334 WINED3DPTFILTERCAPS_MIPLINEAR |
3335 WINED3DPTFILTERCAPS_MIPNEAREST |
3336 WINED3DPTFILTERCAPS_NEAREST;
3338 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3339 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3340 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3343 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3344 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3345 WINED3DPTFILTERCAPS_MAGFPOINT |
3346 WINED3DPTFILTERCAPS_MINFLINEAR |
3347 WINED3DPTFILTERCAPS_MINFPOINT |
3348 WINED3DPTFILTERCAPS_MIPFLINEAR |
3349 WINED3DPTFILTERCAPS_MIPFPOINT |
3350 WINED3DPTFILTERCAPS_LINEAR |
3351 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3352 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3353 WINED3DPTFILTERCAPS_MIPLINEAR |
3354 WINED3DPTFILTERCAPS_MIPNEAREST |
3355 WINED3DPTFILTERCAPS_NEAREST;
3357 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3358 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3359 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3362 pCaps->CubeTextureFilterCaps = 0;
3364 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3365 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3366 WINED3DPTFILTERCAPS_MAGFPOINT |
3367 WINED3DPTFILTERCAPS_MINFLINEAR |
3368 WINED3DPTFILTERCAPS_MINFPOINT |
3369 WINED3DPTFILTERCAPS_MIPFLINEAR |
3370 WINED3DPTFILTERCAPS_MIPFPOINT |
3371 WINED3DPTFILTERCAPS_LINEAR |
3372 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3373 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3374 WINED3DPTFILTERCAPS_MIPLINEAR |
3375 WINED3DPTFILTERCAPS_MIPNEAREST |
3376 WINED3DPTFILTERCAPS_NEAREST;
3378 pCaps->VolumeTextureFilterCaps = 0;
3380 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3381 WINED3DPTADDRESSCAPS_CLAMP |
3382 WINED3DPTADDRESSCAPS_WRAP;
3384 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3385 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3387 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3388 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3390 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3391 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3394 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3395 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3396 WINED3DPTADDRESSCAPS_CLAMP |
3397 WINED3DPTADDRESSCAPS_WRAP;
3398 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3399 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3401 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3402 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3404 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3405 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3408 pCaps->VolumeTextureAddressCaps = 0;
3410 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3411 WINED3DLINECAPS_ZTEST |
3412 WINED3DLINECAPS_BLEND |
3413 WINED3DLINECAPS_ALPHACMP |
3414 WINED3DLINECAPS_FOG;
3415 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3416 * idea how generating the smoothing alpha values works; the result is different
3419 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3420 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3422 if(GL_SUPPORT(EXT_TEXTURE3D))
3423 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3425 pCaps->MaxVolumeExtent = 0;
3427 pCaps->MaxTextureRepeat = 32768;
3428 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3429 pCaps->MaxVertexW = 1.0;
3431 pCaps->GuardBandLeft = 0;
3432 pCaps->GuardBandTop = 0;
3433 pCaps->GuardBandRight = 0;
3434 pCaps->GuardBandBottom = 0;
3436 pCaps->ExtentsAdjust = 0;
3438 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3439 WINED3DSTENCILCAPS_INCRSAT |
3440 WINED3DSTENCILCAPS_INVERT |
3441 WINED3DSTENCILCAPS_KEEP |
3442 WINED3DSTENCILCAPS_REPLACE |
3443 WINED3DSTENCILCAPS_ZERO;
3444 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3445 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3446 WINED3DSTENCILCAPS_INCR;
3448 if ( This->dxVersion > 8 &&
3449 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
3450 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
3451 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3454 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3456 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3457 pCaps->MaxActiveLights = GL_LIMITS(lights);
3459 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3460 pCaps->MaxVertexBlendMatrixIndex = 0;
3462 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3463 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3466 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3467 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3468 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3469 WINED3DVTXPCAPS_LOCALVIEWER |
3470 WINED3DVTXPCAPS_VERTEXFOG |
3471 WINED3DVTXPCAPS_TEXGEN;
3473 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3475 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3476 pCaps->MaxVertexIndex = 0xFFFFF;
3477 pCaps->MaxStreams = MAX_STREAMS;
3478 pCaps->MaxStreamStride = 1024;
3480 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3481 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3482 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3483 pCaps->MaxNpatchTessellationLevel = 0;
3484 pCaps->MasterAdapterOrdinal = 0;
3485 pCaps->AdapterOrdinalInGroup = 0;
3486 pCaps->NumberOfAdaptersInGroup = 1;
3488 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3490 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3491 WINED3DPTFILTERCAPS_MAGFPOINT |
3492 WINED3DPTFILTERCAPS_MINFLINEAR |
3493 WINED3DPTFILTERCAPS_MAGFLINEAR;
3494 pCaps->VertexTextureFilterCaps = 0;
3496 memset(&shader_caps, 0, sizeof(shader_caps));
3497 shader_backend = select_shader_backend(adapter, DeviceType);
3498 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
3500 memset(&fragment_caps, 0, sizeof(fragment_caps));
3501 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
3502 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
3504 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
3505 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
3507 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
3508 * Ignore shader model capabilities if disabled in config
3510 if(vs_selected_mode == SHADER_NONE) {
3511 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
3512 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
3513 pCaps->MaxVertexShaderConst = 0;
3515 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
3516 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
3519 if(ps_selected_mode == SHADER_NONE) {
3520 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
3521 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
3522 pCaps->PixelShader1xMaxValue = 0.0;
3524 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
3525 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
3528 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
3529 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
3530 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
3532 pCaps->VS20Caps = shader_caps.VS20Caps;
3533 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
3534 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
3535 pCaps->PS20Caps = shader_caps.PS20Caps;
3536 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
3537 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
3539 /* The following caps are shader specific, but they are things we cannot detect, or which
3540 * are the same among all shader models. So to avoid code duplication set the shader version
3541 * specific, but otherwise constant caps here
3543 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
3544 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3545 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
3546 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
3547 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3548 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.vs_arb_max_temps);
3549 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
3551 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
3552 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
3553 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
3554 pCaps->VS20Caps.Caps = 0;
3555 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
3556 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.vs_arb_max_temps);
3557 pCaps->VS20Caps.StaticFlowControlDepth = 1;
3559 pCaps->MaxVShaderInstructionsExecuted = 65535;
3560 pCaps->MaxVertexShader30InstructionSlots = 0;
3561 } else { /* VS 1.x */
3562 pCaps->VS20Caps.Caps = 0;
3563 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
3564 pCaps->VS20Caps.NumTemps = 0;
3565 pCaps->VS20Caps.StaticFlowControlDepth = 0;
3567 pCaps->MaxVShaderInstructionsExecuted = 0;
3568 pCaps->MaxVertexShader30InstructionSlots = 0;
3571 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
3572 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3573 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
3575 /* 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 */
3576 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
3577 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
3578 WINED3DPS20CAPS_PREDICATION |
3579 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
3580 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
3581 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3582 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.ps_arb_max_temps);
3583 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
3584 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
3586 pCaps->MaxPShaderInstructionsExecuted = 65535;
3587 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
3588 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
3589 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
3590 pCaps->PS20Caps.Caps = 0;
3591 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
3592 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.ps_arb_max_temps);
3593 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
3594 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
3596 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
3597 pCaps->MaxPixelShader30InstructionSlots = 0;
3598 } else { /* PS 1.x */
3599 pCaps->PS20Caps.Caps = 0;
3600 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
3601 pCaps->PS20Caps.NumTemps = 0;
3602 pCaps->PS20Caps.StaticFlowControlDepth = 0;
3603 pCaps->PS20Caps.NumInstructionSlots = 0;
3605 pCaps->MaxPShaderInstructionsExecuted = 0;
3606 pCaps->MaxPixelShader30InstructionSlots = 0;
3609 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
3610 /* OpenGL supports all the formats below, perhaps not always
3611 * without conversion, but it supports them.
3612 * Further GLSL doesn't seem to have an official unsigned type so
3613 * don't advertise it yet as I'm not sure how we handle it.
3614 * We might need to add some clamping in the shader engine to
3616 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
3617 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
3618 WINED3DDTCAPS_UBYTE4N |
3619 WINED3DDTCAPS_SHORT2N |
3620 WINED3DDTCAPS_SHORT4N;
3621 if (GL_SUPPORT(NV_HALF_FLOAT)) {
3622 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
3623 WINED3DDTCAPS_FLOAT16_4;
3626 pCaps->DeclTypes = 0;
3628 /* Set DirectDraw helper Caps */
3629 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
3630 WINEDDCKEYCAPS_SRCBLT;
3631 fx_caps = WINEDDFXCAPS_BLTALPHA |
3632 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
3633 WINEDDFXCAPS_BLTMIRRORUPDOWN |
3634 WINEDDFXCAPS_BLTROTATION90 |
3635 WINEDDFXCAPS_BLTSHRINKX |
3636 WINEDDFXCAPS_BLTSHRINKXN |
3637 WINEDDFXCAPS_BLTSHRINKY |
3638 WINEDDFXCAPS_BLTSHRINKXN |
3639 WINEDDFXCAPS_BLTSTRETCHX |
3640 WINEDDFXCAPS_BLTSTRETCHXN |
3641 WINEDDFXCAPS_BLTSTRETCHY |
3642 WINEDDFXCAPS_BLTSTRETCHYN;
3643 blit_caps = WINEDDCAPS_BLT |
3644 WINEDDCAPS_BLTCOLORFILL |
3645 WINEDDCAPS_BLTDEPTHFILL |
3646 WINEDDCAPS_BLTSTRETCH |
3647 WINEDDCAPS_CANBLTSYSMEM |
3648 WINEDDCAPS_CANCLIP |
3649 WINEDDCAPS_CANCLIPSTRETCHED |
3650 WINEDDCAPS_COLORKEY |
3651 WINEDDCAPS_COLORKEYHWASSIST |
3652 WINEDDCAPS_ALIGNBOUNDARYSRC;
3654 /* Fill the ddraw caps structure */
3655 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
3656 WINEDDCAPS_PALETTE |
3658 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
3659 WINEDDCAPS2_NOPAGELOCKREQUIRED |
3660 WINEDDCAPS2_PRIMARYGAMMA |
3661 WINEDDCAPS2_WIDESURFACES |
3662 WINEDDCAPS2_CANRENDERWINDOWED;
3663 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
3664 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
3665 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
3666 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
3667 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
3668 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
3669 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
3670 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
3671 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
3673 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
3674 WINEDDSCAPS_BACKBUFFER |
3676 WINEDDSCAPS_FRONTBUFFER |
3677 WINEDDSCAPS_OFFSCREENPLAIN |
3678 WINEDDSCAPS_PALETTE |
3679 WINEDDSCAPS_PRIMARYSURFACE |
3680 WINEDDSCAPS_SYSTEMMEMORY |
3681 WINEDDSCAPS_VIDEOMEMORY |
3682 WINEDDSCAPS_VISIBLE;
3683 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
3685 /* Set D3D caps if OpenGL is available. */
3686 if (adapter->opengl)
3688 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
3689 WINEDDSCAPS_MIPMAP |
3690 WINEDDSCAPS_TEXTURE |
3691 WINEDDSCAPS_ZBUFFER;
3692 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
3698 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
3699 and fields being inserted in the middle, a new structure is used in place */
3700 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
3701 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
3702 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
3704 IWineD3DDeviceImpl *object = NULL;
3705 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3706 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3707 WINED3DDISPLAYMODE mode;
3708 const struct fragment_pipeline *frag_pipeline = NULL;
3710 struct fragment_caps ffp_caps;
3713 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
3714 * number and create a device without a 3D adapter for 2D only operation.
3716 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
3717 return WINED3DERR_INVALIDCALL;
3720 /* Create a WineD3DDevice object */
3721 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
3722 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
3723 TRACE("Created WineD3DDevice object @ %p\n", object);
3724 if (NULL == object) {
3725 return WINED3DERR_OUTOFVIDEOMEMORY;
3728 /* Set up initial COM information */
3729 object->lpVtbl = &IWineD3DDevice_Vtbl;
3731 object->wineD3D = iface;
3732 object->adapter = This->adapter_count ? adapter : NULL;
3733 IWineD3D_AddRef(object->wineD3D);
3734 object->parent = parent;
3735 object->device_parent = device_parent;
3736 list_init(&object->resources);
3737 list_init(&object->shaders);
3739 if(This->dxVersion == 7) {
3740 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
3742 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
3744 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
3746 /* Set the state up as invalid until the device is fully created */
3747 object->state = WINED3DERR_DRIVERINTERNALERROR;
3749 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
3750 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
3752 /* Save the creation parameters */
3753 object->createParms.AdapterOrdinal = Adapter;
3754 object->createParms.DeviceType = DeviceType;
3755 object->createParms.hFocusWindow = hFocusWindow;
3756 object->createParms.BehaviorFlags = BehaviourFlags;
3758 /* Initialize other useful values */
3759 object->adapterNo = Adapter;
3760 object->devType = DeviceType;
3762 select_shader_mode(&adapter->gl_info, DeviceType,
3763 &object->ps_selected_mode, &object->vs_selected_mode);
3764 object->shader_backend = select_shader_backend(adapter, DeviceType);
3766 memset(&ffp_caps, 0, sizeof(ffp_caps));
3767 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
3768 object->frag_pipe = frag_pipeline;
3769 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
3770 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
3771 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
3772 hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
3773 ffp_vertexstate_template, frag_pipeline, misc_state_template);
3776 IWineD3D_Release(object->wineD3D);
3777 HeapFree(GetProcessHeap(), 0, object);
3782 object->blitter = select_blit_implementation(adapter, DeviceType);
3784 /* set the state of the device to valid */
3785 object->state = WINED3D_OK;
3787 /* Get the initial screen setup for ddraw */
3788 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
3790 object->ddraw_width = mode.Width;
3791 object->ddraw_height = mode.Height;
3792 object->ddraw_format = mode.Format;
3794 for(i = 0; i < PATCHMAP_SIZE; i++) {
3795 list_init(&object->patches[i]);
3798 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
3803 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
3804 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3805 IUnknown_AddRef(This->parent);
3806 *pParent = This->parent;
3810 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
3811 IUnknown* surfaceParent;
3812 TRACE("(%p) call back\n", pSurface);
3814 /* Now, release the parent, which will take care of cleaning up the surface for us */
3815 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
3816 IUnknown_Release(surfaceParent);
3817 return IUnknown_Release(surfaceParent);
3820 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
3821 IUnknown* volumeParent;
3822 TRACE("(%p) call back\n", pVolume);
3824 /* Now, release the parent, which will take care of cleaning up the volume for us */
3825 IWineD3DVolume_GetParent(pVolume, &volumeParent);
3826 IUnknown_Release(volumeParent);
3827 return IUnknown_Release(volumeParent);
3830 static BOOL implementation_is_apple(const WineD3D_GL_Info *gl_info)
3832 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
3833 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
3834 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
3836 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
3837 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
3838 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
3839 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
3840 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
3841 * the chance that other implementations support them is rather small since Win32 QuickTime uses
3842 * DirectDraw, not OpenGL.
3844 if(gl_info->supported[APPLE_FENCE] &&
3845 gl_info->supported[APPLE_CLIENT_STORAGE] &&
3846 gl_info->supported[APPLE_FLUSH_RENDER] &&
3847 gl_info->supported[APPLE_YCBCR_422]) {
3848 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
3849 TRACE_(d3d_caps)("Activating MacOS fixups\n");
3852 TRACE_(d3d_caps)("Apple extensions are not supported\n");
3853 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
3858 static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
3859 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
3860 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
3861 * all the texture. This function detects this bug by its symptom and disables PBOs
3862 * if the test fails.
3864 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
3865 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
3866 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
3867 * read back is compared to the original. If they are equal PBOs are assumed to work,
3868 * otherwise the PBO extension is disabled.
3870 GLuint texture, pbo;
3871 static const unsigned int pattern[] = {
3872 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
3873 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
3874 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
3875 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
3877 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
3879 if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
3880 /* No PBO -> No point in testing them */
3884 while(glGetError());
3885 glGenTextures(1, &texture);
3886 glBindTexture(GL_TEXTURE_2D, texture);
3887 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
3888 checkGLcall("Specifying the PBO test texture\n");
3890 GL_EXTCALL(glGenBuffersARB(1, &pbo));
3891 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
3892 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
3893 checkGLcall("Specifying the PBO test pbo\n");
3895 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3896 checkGLcall("Loading the PBO test texture\n");
3898 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
3899 glFinish(); /* just to be sure */
3901 memset(check, 0, sizeof(check));
3902 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
3903 checkGLcall("Reading back the PBO test texture\n");
3905 glDeleteTextures(1, &texture);
3906 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
3907 checkGLcall("PBO test cleanup\n");
3909 if(memcmp(check, pattern, sizeof(check)) != 0) {
3910 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
3911 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
3912 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
3914 TRACE_(d3d_caps)("PBO test successful\n");
3918 /* Certain applications(Steam) complain if we report an outdated driver version. In general,
3919 * reporting a driver version is moot because we are not the Windows driver, and we have different
3920 * bugs, features, etc.
3922 * If a card is not found in this table, the gl driver version is reported
3924 struct driver_version_information {
3925 WORD vendor; /* reported PCI card vendor ID */
3926 WORD card; /* reported PCI card device ID */
3927 WORD hipart_hi, hipart_lo; /* driver hiword to report */
3928 WORD lopart_hi, lopart_lo; /* driver loword to report */
3931 static const struct driver_version_information driver_version_table[] = {
3932 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (177.x)*/
3933 /* GeforceFX support is up to 173.x, Geforce2MX/3/4 up to 96.x, TNT/Geforce1/2 up to 71.x */
3934 /* Note that version numbers >100 lets say 123.45 use >= x.y.11.2345 and not x.y.10.12345 */
3935 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 11, 7341 },
3936 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 11, 7341 },
3937 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 11, 7341 },
3938 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 11, 7341 },
3939 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 11, 7341 },
3940 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 11, 7341 },
3941 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 11, 7341 },
3942 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 11, 7341 },
3943 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 11, 7341 },
3944 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 11, 7341 },
3945 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 11, 7341 },
3946 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 11, 7341 },
3947 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 11, 7341 },
3948 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 11, 7341 },
3949 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, 7, 15, 11, 7341 },
3950 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, 7, 15, 11, 7341 },
3951 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, 7, 15, 11, 7341 },
3953 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
3954 {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 },
3955 {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 },
3956 {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 },
3957 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 },
3958 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 },
3959 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 },
3961 /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */
3964 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
3966 BOOL apple = implementation_is_apple(gl_info);
3969 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
3970 * used it falls back to software. While the compiler can detect if the shader uses all declared
3971 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
3972 * using relative addressing falls back to software.
3974 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
3976 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
3977 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
3979 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
3980 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
3981 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
3984 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
3985 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
3986 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
3987 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
3988 * according to the spec.
3990 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
3991 * makes the shader slower and eats instruction slots which should be available to the d3d app.
3993 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
3994 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
3995 * this workaround is activated on cards that do not need it, it won't break things, just affect
3996 * performance negatively.
3998 if(gl_info->gl_vendor == VENDOR_INTEL ||
3999 (gl_info->gl_vendor == VENDOR_ATI && gl_info->gl_card != CARD_ATI_RADEON_X1600)) {
4000 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
4001 gl_info->set_texcoord_w = TRUE;
4005 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
4006 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
4007 * If real NP2 textures are used, the driver falls back to software. We could just remove the
4008 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
4009 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
4010 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
4011 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
4013 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
4014 * has this extension promoted to core. The extension loading code sets this extension supported
4015 * due to that, so this code works on fglrx as well.
4017 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
4018 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
4019 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
4020 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
4021 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
4022 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
4023 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
4027 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
4028 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
4029 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
4030 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
4031 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
4032 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
4034 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
4035 * triggering the software fallback. There is not much we can do here apart from disabling the
4036 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
4037 * in IWineD3DImpl_FillGLCaps).
4038 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
4039 * post-processing effects in the game "Max Payne 2").
4040 * The behaviour can be verified through a simple test app attached in bugreport #14724.
4042 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_NVIDIA) {
4043 if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
4044 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
4045 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
4046 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
4050 /* Find out if PBOs work as they are supposed to */
4051 test_pbo_functionality(gl_info);
4053 /* Fixup the driver version */
4054 for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
4055 if(gl_info->gl_vendor == driver_version_table[i].vendor &&
4056 gl_info->gl_card == driver_version_table[i].card) {
4057 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
4059 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
4060 driver_version_table[i].lopart_lo);
4061 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
4062 driver_version_table[i].hipart_lo);
4068 static void WINE_GLAPI invalid_func(const void *data)
4070 ERR("Invalid vertex attribute function called\n");
4074 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4076 ERR("Invalid texcoord function called\n");
4080 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4081 * the extension detection and are used in drawStridedSlow
4083 static void WINE_GLAPI position_d3dcolor(const void *data)
4085 DWORD pos = *((const DWORD *)data);
4087 FIXME("Add a test for fixed function position from d3dcolor type\n");
4088 glVertex4s(D3DCOLOR_B_R(pos),
4094 static void WINE_GLAPI position_float4(const void *data)
4096 const GLfloat *pos = data;
4098 if (pos[3] < eps && pos[3] > -eps)
4101 float w = 1.0 / pos[3];
4103 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4107 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4109 DWORD diffuseColor = *((const DWORD *)data);
4111 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4112 D3DCOLOR_B_G(diffuseColor),
4113 D3DCOLOR_B_B(diffuseColor),
4114 D3DCOLOR_B_A(diffuseColor));
4117 static void WINE_GLAPI specular_d3dcolor(const void *data)
4119 DWORD specularColor = *((const DWORD *)data);
4120 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4121 D3DCOLOR_B_G(specularColor),
4122 D3DCOLOR_B_B(specularColor)};
4124 specular_func_3ubv(d);
4127 static void WINE_GLAPI warn_no_specular_func(const void *data)
4129 WARN("GL_EXT_secondary_color not supported\n");
4132 static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
4134 position_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4135 position_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4136 position_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glVertex3fv;
4137 position_funcs[WINED3DDECLTYPE_FLOAT4] = position_float4;
4138 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = position_d3dcolor;
4139 position_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4140 position_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4141 position_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glVertex2sv;
4142 position_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4143 position_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4144 position_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4145 position_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4146 position_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4147 position_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4148 position_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4149 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4150 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4152 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4153 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4154 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glColor3fv;
4155 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glColor4fv;
4156 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = diffuse_d3dcolor;
4157 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4158 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4159 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4160 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (glAttribFunc)glColor4ubv;
4161 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4162 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (glAttribFunc)glColor4sv;
4163 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4164 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (glAttribFunc)glColor4usv;
4165 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4166 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4167 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4168 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4170 /* No 4 component entry points here */
4171 specular_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4172 specular_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4173 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4174 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4176 specular_funcs[WINED3DDECLTYPE_FLOAT3] = warn_no_specular_func;
4178 specular_funcs[WINED3DDECLTYPE_FLOAT4] = invalid_func;
4179 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4180 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4181 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = specular_d3dcolor;
4183 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = warn_no_specular_func;
4185 specular_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4186 specular_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4187 specular_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4188 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4189 specular_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4190 specular_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4191 specular_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4192 specular_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4193 specular_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4194 specular_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4195 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4196 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4198 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4199 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4201 normal_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4202 normal_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4203 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glNormal3fv;
4204 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4205 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
4206 normal_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4207 normal_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4208 normal_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4209 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4210 normal_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4211 normal_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4212 normal_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4213 normal_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4214 normal_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4215 normal_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4216 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4217 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4219 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4220 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4221 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4222 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4223 multi_texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_texcoord_func;
4224 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_texcoord_func;
4225 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4226 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4227 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_texcoord_func;
4228 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_texcoord_func;
4229 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_texcoord_func;
4230 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_texcoord_func;
4231 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_texcoord_func;
4232 multi_texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_texcoord_func;
4233 multi_texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_texcoord_func;
4234 if (GL_SUPPORT(NV_HALF_FLOAT))
4236 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4237 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4239 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_texcoord_func;
4240 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_texcoord_func;
4244 BOOL InitAdapters(IWineD3DImpl *This)
4246 static HMODULE mod_gl;
4248 int ps_selected_mode, vs_selected_mode;
4250 /* No need to hold any lock. The calling library makes sure only one thread calls
4251 * wined3d simultaneously
4254 TRACE("Initializing adapters\n");
4257 #ifdef USE_WIN32_OPENGL
4258 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4259 mod_gl = LoadLibraryA("opengl32.dll");
4261 ERR("Can't load opengl32.dll!\n");
4265 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4266 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4267 mod_gl = GetModuleHandleA("gdi32.dll");
4271 /* Load WGL core functions from opengl32.dll */
4272 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4276 if(!pwglGetProcAddress) {
4277 ERR("Unable to load wglGetProcAddress!\n");
4281 /* Dynamically load all GL core functions */
4285 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4286 * otherwise because we have to use winex11.drv's override
4288 #ifdef USE_WIN32_OPENGL
4289 glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4290 glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4292 glFinish = (void*)pwglGetProcAddress("wglFinish");
4293 glFlush = (void*)pwglGetProcAddress("wglFlush");
4296 glEnableWINE = glEnable;
4297 glDisableWINE = glDisable;
4299 /* For now only one default adapter */
4301 struct WineD3DAdapter *adapter = &This->adapters[0];
4302 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
4309 WineD3D_PixelFormat *cfgs;
4311 DISPLAY_DEVICEW DisplayDevice;
4314 TRACE("Initializing default adapter\n");
4316 adapter->monitorPoint.x = -1;
4317 adapter->monitorPoint.y = -1;
4319 if (!WineD3D_CreateFakeGLContext()) {
4320 ERR("Failed to get a gl context for default adapter\n");
4321 WineD3D_ReleaseFakeGLContext();
4325 ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
4327 ERR("Failed to initialize gl caps for default adapter\n");
4328 WineD3D_ReleaseFakeGLContext();
4331 ret = initPixelFormats(&adapter->gl_info);
4333 ERR("Failed to init gl formats\n");
4334 WineD3D_ReleaseFakeGLContext();
4338 hdc = pwglGetCurrentDC();
4340 ERR("Failed to get gl HDC\n");
4341 WineD3D_ReleaseFakeGLContext();
4345 adapter->driver = "Display";
4346 adapter->description = "Direct3D HAL";
4348 /* Use the VideoRamSize registry setting when set */
4349 if(wined3d_settings.emulated_textureram)
4350 adapter->TextureRam = wined3d_settings.emulated_textureram;
4352 adapter->TextureRam = adapter->gl_info.vidmem;
4353 adapter->UsedTextureRam = 0;
4354 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4356 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4357 DisplayDevice.cb = sizeof(DisplayDevice);
4358 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4359 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4360 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4362 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4363 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4365 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4366 cfgs = adapter->cfgs;
4367 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4368 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4369 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4370 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4371 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4372 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4373 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4374 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4375 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4376 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4378 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4380 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4385 /* Cache the pixel format */
4386 cfgs->iPixelFormat = iPixelFormat;
4387 cfgs->redSize = values[0];
4388 cfgs->greenSize = values[1];
4389 cfgs->blueSize = values[2];
4390 cfgs->alphaSize = values[3];
4391 cfgs->depthSize = values[4];
4392 cfgs->stencilSize = values[5];
4393 cfgs->windowDrawable = values[6];
4394 cfgs->iPixelType = values[7];
4395 cfgs->doubleBuffer = values[8];
4396 cfgs->auxBuffers = values[9];
4398 cfgs->pbufferDrawable = FALSE;
4399 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4400 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4401 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4403 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4404 cfgs->pbufferDrawable = value;
4407 cfgs->numSamples = 0;
4408 /* Check multisample support */
4409 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4410 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4412 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4413 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4414 * value[1] = number of multi sample buffers*/
4416 cfgs->numSamples = value[1];
4420 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);
4424 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4425 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4426 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4427 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4428 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4429 * driver is allowed to consume more bits EXCEPT for stencil bits.
4431 * Mark an adapter with this broken stencil behavior.
4433 adapter->brokenStencil = TRUE;
4434 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4436 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4437 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4438 adapter->brokenStencil = FALSE;
4443 fixup_extensions(&adapter->gl_info);
4444 add_gl_compat_wrappers(&adapter->gl_info);
4446 WineD3D_ReleaseFakeGLContext();
4448 select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4449 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
4450 fillGLAttribFuncs(&adapter->gl_info);
4451 init_type_lookup(&adapter->gl_info);
4452 adapter->opengl = TRUE;
4454 This->adapter_count = 1;
4455 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4460 /* Initialize an adapter for ddraw-only memory counting */
4461 memset(This->adapters, 0, sizeof(This->adapters));
4462 This->adapters[0].num = 0;
4463 This->adapters[0].opengl = FALSE;
4464 This->adapters[0].monitorPoint.x = -1;
4465 This->adapters[0].monitorPoint.y = -1;
4467 This->adapters[0].driver = "Display";
4468 This->adapters[0].description = "WineD3D DirectDraw Emulation";
4469 if(wined3d_settings.emulated_textureram) {
4470 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4472 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4475 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4477 This->adapter_count = 1;
4481 /**********************************************************
4482 * IWineD3D VTbl follows
4483 **********************************************************/
4485 const IWineD3DVtbl IWineD3D_Vtbl =
4488 IWineD3DImpl_QueryInterface,
4489 IWineD3DImpl_AddRef,
4490 IWineD3DImpl_Release,
4492 IWineD3DImpl_GetParent,
4493 IWineD3DImpl_GetAdapterCount,
4494 IWineD3DImpl_RegisterSoftwareDevice,
4495 IWineD3DImpl_GetAdapterMonitor,
4496 IWineD3DImpl_GetAdapterModeCount,
4497 IWineD3DImpl_EnumAdapterModes,
4498 IWineD3DImpl_GetAdapterDisplayMode,
4499 IWineD3DImpl_GetAdapterIdentifier,
4500 IWineD3DImpl_CheckDeviceMultiSampleType,
4501 IWineD3DImpl_CheckDepthStencilMatch,
4502 IWineD3DImpl_CheckDeviceType,
4503 IWineD3DImpl_CheckDeviceFormat,
4504 IWineD3DImpl_CheckDeviceFormatConversion,
4505 IWineD3DImpl_GetDeviceCaps,
4506 IWineD3DImpl_CreateDevice