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 /* The d3d device ID */
40 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
42 /* Extension detection */
44 const char *extension_string;
45 GL_SupportedExt extension;
49 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
50 {"GL_APPLE_fence", APPLE_FENCE, 0 },
51 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
52 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
53 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
56 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
57 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
58 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
59 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
60 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
63 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
64 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
65 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
66 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
67 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
68 {"GL_ARB_imaging", ARB_IMAGING, 0 },
69 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
70 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
71 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
72 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
73 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
74 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
75 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
76 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
77 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
78 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
79 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
80 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
81 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
82 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
83 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
84 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
85 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
86 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
87 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
88 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
89 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
92 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
93 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
94 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
95 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
96 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
97 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
98 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
99 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
100 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
101 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
102 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
103 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
104 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
105 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
106 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
107 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
108 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
109 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
110 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
111 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
112 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
113 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
114 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
115 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
116 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
119 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
120 {"GL_NV_fence", NV_FENCE, 0 },
121 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
122 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
123 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
124 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
125 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
126 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
127 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
128 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
129 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
130 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
131 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
132 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
133 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
134 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
135 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
136 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
137 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
140 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
143 /**********************************************************
144 * Utility functions follow
145 **********************************************************/
148 static int numAdapters = 0;
149 static struct WineD3DAdapter Adapters[1];
151 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
152 static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
153 static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType);
154 static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
157 int minLookup[MAX_LOOKUPS];
158 int maxLookup[MAX_LOOKUPS];
159 DWORD *stateLookup[MAX_LOOKUPS];
161 struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
162 const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
164 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
165 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
166 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
167 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
170 GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
171 const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
173 GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
176 /* drawStridedSlow attributes */
177 glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
178 glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
179 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
180 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
181 glMultiTexCoordFunc multi_texcoord_funcs[WINED3DDECLTYPE_UNUSED];
182 glAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
185 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
186 * i.e., there is no GL Context - Get a default rendering context to enable the
187 * function query some info from GL.
190 static int wined3d_fake_gl_context_ref = 0;
191 static BOOL wined3d_fake_gl_context_foreign;
192 static BOOL wined3d_fake_gl_context_available = FALSE;
193 static HDC wined3d_fake_gl_context_hdc = NULL;
194 static HWND wined3d_fake_gl_context_hwnd = NULL;
196 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
197 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
199 0, 0, &wined3d_fake_gl_context_cs,
200 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
201 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
202 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
204 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
206 static void WineD3D_ReleaseFakeGLContext(void) {
209 EnterCriticalSection(&wined3d_fake_gl_context_cs);
211 if(!wined3d_fake_gl_context_available) {
212 TRACE_(d3d_caps)("context not available\n");
213 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
217 glCtx = pwglGetCurrentContext();
219 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
220 if (0 == (--wined3d_fake_gl_context_ref) ) {
221 if(!wined3d_fake_gl_context_foreign && glCtx) {
222 TRACE_(d3d_caps)("destroying fake GL context\n");
223 pwglMakeCurrent(NULL, NULL);
224 pwglDeleteContext(glCtx);
226 if(wined3d_fake_gl_context_hdc)
227 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
228 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
229 if(wined3d_fake_gl_context_hwnd)
230 DestroyWindow(wined3d_fake_gl_context_hwnd);
231 wined3d_fake_gl_context_hwnd = NULL;
232 wined3d_fake_gl_context_available = FALSE;
234 assert(wined3d_fake_gl_context_ref >= 0);
236 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
239 static BOOL WineD3D_CreateFakeGLContext(void) {
242 EnterCriticalSection(&wined3d_fake_gl_context_cs);
244 TRACE("getting context...\n");
245 if(wined3d_fake_gl_context_ref > 0) goto ret;
246 assert(0 == wined3d_fake_gl_context_ref);
248 wined3d_fake_gl_context_foreign = TRUE;
250 glCtx = pwglGetCurrentContext();
252 PIXELFORMATDESCRIPTOR pfd;
255 wined3d_fake_gl_context_foreign = FALSE;
257 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
258 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
259 if(!wined3d_fake_gl_context_hwnd) {
260 ERR("HWND creation failed!\n");
263 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
264 if(!wined3d_fake_gl_context_hdc) {
265 ERR("GetDC failed!\n");
269 /* PixelFormat selection */
270 ZeroMemory(&pfd, sizeof(pfd));
271 pfd.nSize = sizeof(pfd);
273 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
274 pfd.iPixelType = PFD_TYPE_RGBA;
276 pfd.iLayerType = PFD_MAIN_PLANE;
278 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
280 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
281 ERR("Can't find a suitable iPixelFormat\n");
284 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
285 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
287 /* Create a GL context */
288 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
290 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
294 /* Make it the current GL context */
295 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
296 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
302 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
303 wined3d_fake_gl_context_ref++;
304 wined3d_fake_gl_context_available = TRUE;
305 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
308 if(wined3d_fake_gl_context_hdc)
309 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
310 wined3d_fake_gl_context_hdc = NULL;
311 if(wined3d_fake_gl_context_hwnd)
312 DestroyWindow(wined3d_fake_gl_context_hwnd);
313 wined3d_fake_gl_context_hwnd = NULL;
314 if(glCtx) pwglDeleteContext(glCtx);
315 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
319 /* Adjust the amount of used texture memory */
320 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
321 UINT Adapter = D3DDevice->adapterNo;
323 Adapters[Adapter].UsedTextureRam += glram;
324 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
325 return Adapters[Adapter].UsedTextureRam;
328 /**********************************************************
329 * IUnknown parts follows
330 **********************************************************/
332 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
336 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 if (IsEqualGUID(riid, &IID_IUnknown)
338 || IsEqualGUID(riid, &IID_IWineD3DBase)
339 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340 IUnknown_AddRef(iface);
345 return E_NOINTERFACE;
348 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
349 IWineD3DImpl *This = (IWineD3DImpl *)iface;
350 ULONG refCount = InterlockedIncrement(&This->ref);
352 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
356 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
357 IWineD3DImpl *This = (IWineD3DImpl *)iface;
359 TRACE("(%p) : Releasing from %d\n", This, This->ref);
360 ref = InterlockedDecrement(&This->ref);
362 HeapFree(GetProcessHeap(), 0, This);
368 /* Set the shader type for this device, depending on the given capabilities,
369 * the device type, and the user preferences in wined3d_settings */
371 void select_shader_mode(
372 WineD3D_GL_Info *gl_info,
373 WINED3DDEVTYPE DeviceType,
377 if (wined3d_settings.vs_mode == VS_NONE) {
378 *vs_selected = SHADER_NONE;
379 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
380 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
381 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
382 * shaders only on this card. */
383 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
384 *vs_selected = SHADER_ARB;
386 *vs_selected = SHADER_GLSL;
387 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
388 *vs_selected = SHADER_ARB;
390 *vs_selected = SHADER_NONE;
393 if (wined3d_settings.ps_mode == PS_NONE) {
394 *ps_selected = SHADER_NONE;
395 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
396 *ps_selected = SHADER_GLSL;
397 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
398 *ps_selected = SHADER_ARB;
399 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
400 *ps_selected = SHADER_ATI;
402 *ps_selected = SHADER_NONE;
406 /** Select the number of report maximum shader constants based on the selected shader modes */
407 static void select_shader_max_constants(
408 int ps_selected_mode,
409 int vs_selected_mode,
410 WineD3D_GL_Info *gl_info) {
412 switch (vs_selected_mode) {
414 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
415 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
418 /* We have to subtract any other PARAMs that we might use in our shader programs.
419 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
420 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
421 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
424 gl_info->max_vshader_constantsF = 0;
428 switch (ps_selected_mode) {
430 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
431 * In theory the texbem instruction may need one more shader constant too. But lets assume
432 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
433 * and lets not take away a uniform needlessly from all other shaders.
435 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
438 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
439 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
441 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
444 gl_info->max_pshader_constantsF = 0;
449 /**********************************************************
450 * IWineD3D parts follows
451 **********************************************************/
453 #define GLINFO_LOCATION (*gl_info)
454 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
457 const char *testcode =
459 "PARAM C[66] = { program.env[0..65] };\n"
461 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
462 "ARL A0.x, zero.x;\n"
463 "MOV result.position, C[A0.x + 65];\n"
467 GL_EXTCALL(glGenProgramsARB(1, &prog));
469 ERR("Failed to create an ARB offset limit test program\n");
471 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
472 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
473 strlen(testcode), testcode));
474 if(glGetError() != 0) {
475 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
476 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
478 } else TRACE("OpenGL implementation allows offsets > 63\n");
480 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
481 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
482 checkGLcall("ARB vp offset limit test cleanup\n");
487 static DWORD ver_for_ext(GL_SupportedExt ext)
490 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
491 if(EXTENSION_MAP[i].extension == ext) {
492 return EXTENSION_MAP[i].version;
498 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
499 const char *GL_Extensions = NULL;
500 const char *WGL_Extensions = NULL;
501 const char *gl_string = NULL;
502 const char *gl_string_cursor = NULL;
504 GLfloat gl_floatv[2];
505 int major = 1, minor = 0;
506 BOOL return_value = TRUE;
509 unsigned int vidmem=0;
511 TRACE_(d3d_caps)("(%p)\n", gl_info);
515 gl_string = (const char *) glGetString(GL_RENDERER);
516 if (NULL == gl_string)
518 strcpy(gl_info->gl_renderer, gl_string);
520 gl_string = (const char *) glGetString(GL_VENDOR);
521 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
522 if (gl_string != NULL) {
523 /* Fill in the GL vendor */
524 if (strstr(gl_string, "NVIDIA")) {
525 gl_info->gl_vendor = VENDOR_NVIDIA;
526 } else if (strstr(gl_string, "ATI")) {
527 gl_info->gl_vendor = VENDOR_ATI;
528 } else if (strstr(gl_string, "Intel(R)") ||
529 strstr(gl_info->gl_renderer, "Intel(R)") ||
530 strstr(gl_string, "Intel Inc.")) {
531 gl_info->gl_vendor = VENDOR_INTEL;
532 } else if (strstr(gl_string, "Mesa")) {
533 gl_info->gl_vendor = VENDOR_MESA;
535 gl_info->gl_vendor = VENDOR_WINE;
538 gl_info->gl_vendor = VENDOR_WINE;
542 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
544 /* Parse the GL_VERSION field into major and minor information */
545 gl_string = (const char *) glGetString(GL_VERSION);
546 if (gl_string != NULL) {
548 /* First, parse the generic opengl version. This is supposed not to be convoluted with
549 * driver specific information
551 gl_string_cursor = gl_string;
552 major = atoi(gl_string_cursor);
554 ERR("Invalid opengl major version: %d\n", major);
556 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
559 if (*gl_string_cursor++ != '.') {
560 ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
562 minor = atoi(gl_string_cursor);
563 TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
564 gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
566 /* Now parse the driver specific string which we'll report to the app */
567 switch (gl_info->gl_vendor) {
569 gl_string_cursor = strstr(gl_string, "NVIDIA");
570 if (!gl_string_cursor) {
571 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
575 gl_string_cursor = strstr(gl_string_cursor, " ");
576 if (!gl_string_cursor) {
577 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
581 while (*gl_string_cursor == ' ') {
585 if (!*gl_string_cursor) {
586 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
590 major = atoi(gl_string_cursor);
591 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
595 if (*gl_string_cursor++ != '.') {
596 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
600 minor = atoi(gl_string_cursor);
601 minor = major*100+minor;
608 gl_string_cursor = strchr(gl_string, '-');
609 if (gl_string_cursor) {
613 /* Check if version number is of the form x.y.z */
614 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
616 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
618 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
620 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
623 /* Mark version number as malformed */
625 gl_string_cursor = 0;
628 if (!gl_string_cursor)
629 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
631 major = *gl_string_cursor - '0';
632 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
637 /* Apple and Mesa version strings look differently, but both provide intel drivers */
638 if(strstr(gl_string, "APPLE")) {
639 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
640 * We only need the first part, and use the APPLE as identification
643 gl_string_cursor = gl_string;
644 major = atoi(gl_string_cursor);
645 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
649 if (*gl_string_cursor++ != '.') {
650 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
654 minor = atoi(gl_string_cursor);
659 gl_string_cursor = strstr(gl_string, "Mesa");
660 gl_string_cursor = strstr(gl_string_cursor, " ");
661 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
662 if (*gl_string_cursor) {
666 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
667 tmp[cursor++] = *gl_string_cursor;
673 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
677 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
678 tmp[cursor++] = *gl_string_cursor;
690 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
691 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
692 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
693 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
695 FIXME("OpenGL driver did not return version information\n");
696 gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
697 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
700 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
703 * Initialize openGL extension related variables
704 * with Default values
706 memset(gl_info->supported, 0, sizeof(gl_info->supported));
707 gl_info->max_buffers = 1;
708 gl_info->max_textures = 1;
709 gl_info->max_texture_stages = 1;
710 gl_info->max_fragment_samplers = 1;
711 gl_info->max_vertex_samplers = 0;
712 gl_info->max_combined_samplers = 0;
713 gl_info->max_sampler_stages = 1;
714 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
715 gl_info->ps_arb_max_temps = 0;
716 gl_info->ps_arb_max_instructions = 0;
717 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
718 gl_info->vs_arb_max_temps = 0;
719 gl_info->vs_arb_max_instructions = 0;
720 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
721 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
722 gl_info->vs_glsl_constantsF = 0;
723 gl_info->ps_glsl_constantsF = 0;
724 gl_info->vs_arb_constantsF = 0;
725 gl_info->ps_arb_constantsF = 0;
727 /* Retrieve opengl defaults */
728 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
729 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
730 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
732 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
733 gl_info->max_lights = gl_max;
734 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
736 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
737 gl_info->max_texture_size = gl_max;
738 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
740 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
741 gl_info->max_pointsizemin = gl_floatv[0];
742 gl_info->max_pointsize = gl_floatv[1];
743 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
745 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
746 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
747 TRACE_(d3d_caps)("GL_Extensions reported:\n");
749 if (NULL == GL_Extensions) {
750 ERR(" GL_Extensions returns NULL\n");
752 while (*GL_Extensions != 0x00) {
757 while (isspace(*GL_Extensions)) GL_Extensions++;
758 Start = GL_Extensions;
759 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
763 len = GL_Extensions - Start;
764 if (len == 0 || len >= sizeof(ThisExtn))
767 memcpy(ThisExtn, Start, len);
768 ThisExtn[len] = '\0';
769 TRACE_(d3d_caps)("- %s\n", ThisExtn);
771 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
772 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
773 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
774 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
782 /* Now work out what GL support this card really has */
783 #define USE_GL_FUNC(type, pfn, ext, replace) { \
784 DWORD ver = ver_for_ext(ext); \
785 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
786 else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
787 else gl_info->pfn = NULL; \
792 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
797 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
798 * loading the functions, otherwise the code above will load the extension entry points instead of the
799 * core functions, which may not work
801 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
802 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
803 EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
804 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
805 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
809 if (gl_info->supported[APPLE_FENCE]) {
810 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
811 * The apple extension interacts with some other apple exts. Disable the NV
812 * extension if the apple one is support to prevent confusion in other parts
815 gl_info->supported[NV_FENCE] = FALSE;
817 if (gl_info->supported[APPLE_FLOAT_PIXELS]) {
818 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
820 * The enums are the same:
821 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
822 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
823 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
824 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
825 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
827 if(!gl_info->supported[ARB_TEXTURE_FLOAT]) {
828 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n");
829 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
831 if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) {
832 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n");
833 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
836 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
837 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
838 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
840 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
841 if(gl_info->supported[NV_REGISTER_COMBINERS]) {
842 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
843 * are supported. The nv extensions provide the same functionality as the
844 * ATI one, and a bit more(signed pixelformats)
846 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
849 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
850 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
851 gl_info->max_buffers = gl_max;
852 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
854 if (gl_info->supported[ARB_MULTITEXTURE]) {
855 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
856 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
857 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
859 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
861 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
862 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
864 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
866 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
868 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
870 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
871 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
873 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
875 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
877 if (gl_info->supported[ARB_VERTEX_SHADER]) {
879 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
880 gl_info->max_vertex_samplers = tmp;
881 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
882 gl_info->max_combined_samplers = tmp;
884 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
885 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
886 * an issue because then the sampler setup only depends on the two shaders. If a pixel
887 * shader is used with fixed function vertex processing we're fine too because fixed function
888 * vertex processing doesn't use any samplers. If fixed function fragment processing is
889 * used we have to make sure that all vertex sampler setups are valid together with all
890 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
891 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
892 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
893 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
894 * a fixed function pipeline anymore.
896 * So this is just a check to check that our assumption holds true. If not, write a warning
897 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
899 if(gl_info->max_vertex_samplers &&
900 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
901 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
902 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
903 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
904 if( gl_info->max_combined_samplers > MAX_TEXTURES )
905 gl_info->max_vertex_samplers =
906 gl_info->max_combined_samplers - MAX_TEXTURES;
908 gl_info->max_vertex_samplers = 0;
911 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
913 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
914 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
916 if (gl_info->supported[ARB_VERTEX_BLEND]) {
917 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
918 gl_info->max_blends = gl_max;
919 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
921 if (gl_info->supported[EXT_TEXTURE3D]) {
922 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
923 gl_info->max_texture3d_size = gl_max;
924 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
926 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
927 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
928 gl_info->max_anisotropy = gl_max;
929 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
931 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
932 gl_info->ps_arb_version = PS_VERSION_11;
933 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
934 gl_info->ps_arb_constantsF = gl_max;
935 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
936 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
937 gl_info->ps_arb_max_temps = gl_max;
938 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
939 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
940 gl_info->ps_arb_max_instructions = gl_max;
941 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
943 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
944 gl_info->vs_arb_version = VS_VERSION_11;
945 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
946 gl_info->vs_arb_constantsF = gl_max;
947 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
948 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
949 gl_info->vs_arb_max_temps = gl_max;
950 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
951 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
952 gl_info->vs_arb_max_instructions = gl_max;
953 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
955 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
957 if (gl_info->supported[ARB_VERTEX_SHADER]) {
958 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
959 gl_info->vs_glsl_constantsF = gl_max / 4;
960 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
962 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
963 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
964 gl_info->ps_glsl_constantsF = gl_max / 4;
965 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
966 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
967 gl_info->max_glsl_varyings = gl_max;
968 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
970 if (gl_info->supported[EXT_VERTEX_SHADER]) {
971 gl_info->vs_ati_version = VS_VERSION_11;
973 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
974 gl_info->vs_nv_version = VS_VERSION_30;
975 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
976 gl_info->vs_nv_version = VS_VERSION_20;
977 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
978 gl_info->vs_nv_version = VS_VERSION_11;
979 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
980 gl_info->vs_nv_version = VS_VERSION_10;
982 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
983 gl_info->ps_nv_version = PS_VERSION_30;
984 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
985 gl_info->ps_nv_version = PS_VERSION_20;
987 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) {
988 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
990 gl_info->max_shininess = 128.0;
992 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
993 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
994 * This saves a few redundant glDisable calls
996 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
998 if(gl_info->supported[ATI_FRAGMENT_SHADER]) {
999 /* Disable NV_register_combiners and fragment shader if this is supported.
1000 * generally the NV extensions are preferred over the ATI ones, and this
1001 * extension is disabled if register_combiners and texture_shader2 are both
1002 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1003 * fragment processing support
1005 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1006 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1007 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1008 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1009 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1013 checkGLcall("extension detection\n");
1015 /* In some cases the number of texture stages can be larger than the number
1016 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1017 * shaders), but 8 texture stages (register combiners). */
1018 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1020 /* We can only use ORM_FBO when the hardware supports it. */
1021 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1022 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
1023 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
1026 /* MRTs are currently only supported when FBOs are used. */
1027 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1028 gl_info->max_buffers = 1;
1031 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
1032 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
1033 * in case of the latest videocards in the number of pixel/vertex pipelines.
1035 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
1036 * rendering. Various games use this information to get a rough estimation of the features of the card
1037 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
1038 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
1039 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
1042 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
1043 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
1044 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
1045 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
1046 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1047 * is used for rendering which is not always the case). This would work but it is not very portable. Second
1048 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1051 * As said most games only use the PCI id to get an indication of the capabilities of the card.
1052 * It doesn't really matter if the given id is the correct one if we return the id of a card with
1053 * similar 3d features.
1055 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
1056 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1057 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1058 * won't pass we return a default card. This way is better than maintaining a full card database as even
1059 * without a full database we can return a card with similar features. Second the size of the database
1060 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
1061 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
1062 * to distinguishes between different models from that family.
1064 * The code also selects a default amount of video memory which we will use for an estimation of the amount
1065 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
1066 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
1067 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
1068 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
1069 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1070 * memory behind our backs if really needed.
1071 * Note that the amount of video memory can be overruled using a registry setting.
1073 switch (gl_info->gl_vendor) {
1075 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1076 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1078 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1079 /* Geforce GTX - highend */
1080 if(strstr(gl_info->gl_renderer, "GTX 280")) {
1081 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1084 /* Geforce9 - highend */
1085 else if(strstr(gl_info->gl_renderer, "9800")) {
1086 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1089 /* Geforce9 - midend */
1090 else if(strstr(gl_info->gl_renderer, "9600")) {
1091 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1092 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1094 /* Geforce8 - highend */
1095 else if (strstr(gl_info->gl_renderer, "8800")) {
1096 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1097 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1099 /* Geforce8 - midend mobile */
1100 else if(strstr(gl_info->gl_renderer, "8600 M")) {
1101 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1104 /* Geforce8 - midend */
1105 else if(strstr(gl_info->gl_renderer, "8600") ||
1106 strstr(gl_info->gl_renderer, "8700"))
1108 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1111 /* Geforce8 - lowend */
1112 else if(strstr(gl_info->gl_renderer, "8300") ||
1113 strstr(gl_info->gl_renderer, "8400") ||
1114 strstr(gl_info->gl_renderer, "8500"))
1116 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1117 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1119 /* Geforce7 - highend */
1120 else if(strstr(gl_info->gl_renderer, "7800") ||
1121 strstr(gl_info->gl_renderer, "7900") ||
1122 strstr(gl_info->gl_renderer, "7950") ||
1123 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1124 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1126 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1127 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1129 /* Geforce7 midend */
1130 else if(strstr(gl_info->gl_renderer, "7600") ||
1131 strstr(gl_info->gl_renderer, "7700")) {
1132 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1133 vidmem = 256; /* The 7600 uses 256-512MB */
1134 /* Geforce7 lower medium */
1135 } else if(strstr(gl_info->gl_renderer, "7400")) {
1136 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1137 vidmem = 256; /* The 7400 uses 256-512MB */
1139 /* Geforce7 lowend */
1140 else if(strstr(gl_info->gl_renderer, "7300")) {
1141 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1142 vidmem = 256; /* Mac Pros with this card have 256 MB */
1144 /* Geforce6 highend */
1145 else if(strstr(gl_info->gl_renderer, "6800"))
1147 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1148 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1150 /* Geforce6 - midend */
1151 else if(strstr(gl_info->gl_renderer, "6600") ||
1152 strstr(gl_info->gl_renderer, "6610") ||
1153 strstr(gl_info->gl_renderer, "6700"))
1155 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1156 vidmem = 128; /* A 6600GT has 128-256MB */
1158 /* Geforce6/7 lowend */
1160 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1163 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1164 /* GeforceFX - highend */
1165 if (strstr(gl_info->gl_renderer, "5800") ||
1166 strstr(gl_info->gl_renderer, "5900") ||
1167 strstr(gl_info->gl_renderer, "5950") ||
1168 strstr(gl_info->gl_renderer, "Quadro FX"))
1170 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1171 vidmem = 256; /* 5800-5900 cards use 256MB */
1173 /* GeforceFX - midend */
1174 else if(strstr(gl_info->gl_renderer, "5600") ||
1175 strstr(gl_info->gl_renderer, "5650") ||
1176 strstr(gl_info->gl_renderer, "5700") ||
1177 strstr(gl_info->gl_renderer, "5750"))
1179 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1180 vidmem = 128; /* A 5600 uses 128-256MB */
1182 /* GeforceFX - lowend */
1184 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1185 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1187 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1188 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1189 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1190 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1193 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1194 vidmem = 64; /* Geforce3 cards have 64-128MB */
1196 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1197 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1198 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1199 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1201 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1202 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1203 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1205 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1206 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1207 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1210 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1211 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1214 if (strstr(gl_info->gl_renderer, "TNT2")) {
1215 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1216 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1219 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1220 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1225 if(WINE_D3D9_CAPABLE(gl_info)) {
1226 /* Radeon R6xx HD2900/HD3800 - highend */
1227 if (strstr(gl_info->gl_renderer, "HD 2900") ||
1228 strstr(gl_info->gl_renderer, "HD 3870") ||
1229 strstr(gl_info->gl_renderer, "HD 3850"))
1231 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1232 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1234 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1235 else if (strstr(gl_info->gl_renderer, "HD 2600") ||
1236 strstr(gl_info->gl_renderer, "HD 3830") ||
1237 strstr(gl_info->gl_renderer, "HD 3690") ||
1238 strstr(gl_info->gl_renderer, "HD 3650"))
1240 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1241 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1243 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1244 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1245 strstr(gl_info->gl_renderer, "HD 2400") ||
1246 strstr(gl_info->gl_renderer, "HD 3470") ||
1247 strstr(gl_info->gl_renderer, "HD 3450") ||
1248 strstr(gl_info->gl_renderer, "HD 3430"))
1250 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1251 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1253 /* Radeon R6xx/R7xx integrated */
1254 else if (strstr(gl_info->gl_renderer, "HD 3100") ||
1255 strstr(gl_info->gl_renderer, "HD 3200") ||
1256 strstr(gl_info->gl_renderer, "HD 3300"))
1258 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1259 vidmem = 128; /* 128MB */
1262 else if (strstr(gl_info->gl_renderer, "X1600") ||
1263 strstr(gl_info->gl_renderer, "X1650") ||
1264 strstr(gl_info->gl_renderer, "X1800") ||
1265 strstr(gl_info->gl_renderer, "X1900") ||
1266 strstr(gl_info->gl_renderer, "X1950"))
1268 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1269 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1271 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1272 else if(strstr(gl_info->gl_renderer, "X700") ||
1273 strstr(gl_info->gl_renderer, "X800") ||
1274 strstr(gl_info->gl_renderer, "X850") ||
1275 strstr(gl_info->gl_renderer, "X1300") ||
1276 strstr(gl_info->gl_renderer, "X1400") ||
1277 strstr(gl_info->gl_renderer, "X1450") ||
1278 strstr(gl_info->gl_renderer, "X1550"))
1280 gl_info->gl_card = CARD_ATI_RADEON_X700;
1281 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1285 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1286 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1288 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1289 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1290 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1291 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1292 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1293 vidmem = 32; /* There are models with up to 64MB */
1295 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1296 vidmem = 16; /* There are 16-32MB models */
1300 if (strstr(gl_info->gl_renderer, "GMA 950")) {
1301 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1302 gl_info->gl_card = CARD_INTEL_I945GM;
1304 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1305 gl_info->gl_card = CARD_INTEL_I915GM;
1306 } else if (strstr(gl_info->gl_renderer, "915G")) {
1307 gl_info->gl_card = CARD_INTEL_I915G;
1308 } else if (strstr(gl_info->gl_renderer, "865G")) {
1309 gl_info->gl_card = CARD_INTEL_I865G;
1310 } else if (strstr(gl_info->gl_renderer, "855G")) {
1311 gl_info->gl_card = CARD_INTEL_I855G;
1312 } else if (strstr(gl_info->gl_renderer, "830G")) {
1313 gl_info->gl_card = CARD_INTEL_I830G;
1315 gl_info->gl_card = CARD_INTEL_I915G;
1321 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1322 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1323 * them a good generic choice.
1325 gl_info->gl_vendor = VENDOR_NVIDIA;
1326 if(WINE_D3D9_CAPABLE(gl_info))
1327 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1328 else if(WINE_D3D8_CAPABLE(gl_info))
1329 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1330 else if(WINE_D3D7_CAPABLE(gl_info))
1331 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1332 else if(WINE_D3D6_CAPABLE(gl_info))
1333 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1335 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1337 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1339 /* If we have an estimate use it, else default to 64MB; */
1341 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1343 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1345 /* Load all the lookup tables
1346 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1347 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1348 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1350 for (i = 0; i < MAX_LOOKUPS; i++) {
1351 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1354 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1355 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1356 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1357 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1358 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1359 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1360 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1361 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1362 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1363 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1365 magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
1366 magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
1367 magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
1368 magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1369 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1372 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1373 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
1374 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
1375 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
1376 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1377 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1378 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1379 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1380 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1381 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
1382 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1383 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
1384 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1385 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
1386 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1388 /* TODO: config lookups */
1390 /* Make sure there's an active HDC else the WGL extensions will fail */
1391 hdc = pwglGetCurrentDC();
1393 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1394 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1396 if (NULL == WGL_Extensions) {
1397 ERR(" WGL_Extensions returns NULL\n");
1399 while (*WGL_Extensions != 0x00) {
1404 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1405 Start = WGL_Extensions;
1406 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1410 len = WGL_Extensions - Start;
1411 if (len == 0 || len >= sizeof(ThisExtn))
1414 memcpy(ThisExtn, Start, len);
1415 ThisExtn[len] = '\0';
1416 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1418 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1419 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1420 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1422 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1423 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1424 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1431 return return_value;
1433 #undef GLINFO_LOCATION
1435 /**********************************************************
1436 * IWineD3D implementation follows
1437 **********************************************************/
1439 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1440 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1442 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1446 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1447 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1448 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1452 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1453 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1455 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1457 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1461 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1464 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1465 of the same bpp but different resolutions */
1467 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1468 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1469 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1470 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1472 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1476 /* TODO: Store modes per adapter and read it from the adapter structure */
1477 if (Adapter == 0) { /* Display */
1481 if (!DEBUG_SINGLE_MODE) {
1484 ZeroMemory(&DevModeW, sizeof(DevModeW));
1485 DevModeW.dmSize = sizeof(DevModeW);
1486 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1490 case WINED3DFMT_UNKNOWN:
1491 /* This is for D3D8, do not enumerate P8 here */
1492 if (DevModeW.dmBitsPerPel == 32 ||
1493 DevModeW.dmBitsPerPel == 16) i++;
1495 case WINED3DFMT_X8R8G8B8:
1496 if (DevModeW.dmBitsPerPel == 32) i++;
1498 case WINED3DFMT_R5G6B5:
1499 if (DevModeW.dmBitsPerPel == 16) i++;
1502 if (DevModeW.dmBitsPerPel == 8) i++;
1505 /* Skip other modes as they do not match the requested format */
1514 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1517 FIXME_(d3d_caps)("Adapter not primary display\n");
1522 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1523 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1524 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1525 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1527 /* Validate the parameters as much as possible */
1528 if (NULL == pMode ||
1529 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1530 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1531 return WINED3DERR_INVALIDCALL;
1534 /* TODO: Store modes per adapter and read it from the adapter structure */
1535 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1541 ZeroMemory(&DevModeW, sizeof(DevModeW));
1542 DevModeW.dmSize = sizeof(DevModeW);
1544 /* If we are filtering to a specific format (D3D9), then need to skip
1545 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1546 just count through the ones with valid bit depths */
1547 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1550 case WINED3DFMT_UNKNOWN:
1551 /* This is D3D8. Do not enumerate P8 here */
1552 if (DevModeW.dmBitsPerPel == 32 ||
1553 DevModeW.dmBitsPerPel == 16) i++;
1555 case WINED3DFMT_X8R8G8B8:
1556 if (DevModeW.dmBitsPerPel == 32) i++;
1558 case WINED3DFMT_R5G6B5:
1559 if (DevModeW.dmBitsPerPel == 16) i++;
1562 if (DevModeW.dmBitsPerPel == 8) i++;
1565 /* Modes that don't match what we support can get an early-out */
1566 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1567 return WINED3DERR_INVALIDCALL;
1572 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1573 return WINED3DERR_INVALIDCALL;
1577 /* Now get the display mode via the calculated index */
1578 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1579 pMode->Width = DevModeW.dmPelsWidth;
1580 pMode->Height = DevModeW.dmPelsHeight;
1581 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1582 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1583 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1585 if (Format == WINED3DFMT_UNKNOWN) {
1586 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1588 pMode->Format = Format;
1591 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1592 return WINED3DERR_INVALIDCALL;
1595 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1596 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1597 DevModeW.dmBitsPerPel);
1599 } else if (DEBUG_SINGLE_MODE) {
1600 /* Return one setting of the format requested */
1601 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1603 pMode->Height = 600;
1604 pMode->RefreshRate = 60;
1605 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1607 FIXME_(d3d_caps)("Adapter not primary display\n");
1613 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1614 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1615 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1617 if (NULL == pMode ||
1618 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1619 return WINED3DERR_INVALIDCALL;
1622 if (Adapter == 0) { /* Display */
1626 ZeroMemory(&DevModeW, sizeof(DevModeW));
1627 DevModeW.dmSize = sizeof(DevModeW);
1629 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1630 pMode->Width = DevModeW.dmPelsWidth;
1631 pMode->Height = DevModeW.dmPelsHeight;
1632 bpp = DevModeW.dmBitsPerPel;
1633 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1634 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1636 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1639 pMode->Format = pixelformat_for_depth(bpp);
1641 FIXME_(d3d_caps)("Adapter not primary display\n");
1644 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1645 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1649 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1650 and fields being inserted in the middle, a new structure is used in place */
1651 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1652 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1653 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1655 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1657 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1658 return WINED3DERR_INVALIDCALL;
1661 /* Return the information requested */
1662 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1663 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1664 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1666 /* Note dx8 doesn't supply a DeviceName */
1667 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1668 pIdentifier->DriverVersion->u.HighPart = Adapters[Adapter].gl_info.driver_version_hipart;
1669 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.driver_version;
1670 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1671 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1672 *(pIdentifier->SubSysId) = 0;
1673 *(pIdentifier->Revision) = 0;
1674 *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID;
1676 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1678 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
1679 *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id;
1682 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1684 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
1685 *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id;
1688 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1689 *(pIdentifier->WHQLLevel) = 0;
1691 *(pIdentifier->WHQLLevel) = 1;
1697 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1698 short redSize, greenSize, blueSize, alphaSize, colorBits;
1703 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
1704 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1705 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1709 if(cfg->redSize < redSize)
1712 if(cfg->greenSize < greenSize)
1715 if(cfg->blueSize < blueSize)
1718 if(cfg->alphaSize < alphaSize)
1722 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
1723 if(Format == WINED3DFMT_R16F)
1724 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1725 if(Format == WINED3DFMT_G16R16F)
1726 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1727 if(Format == WINED3DFMT_A16B16G16R16F)
1728 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
1729 if(Format == WINED3DFMT_R32F)
1730 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1731 if(Format == WINED3DFMT_G32R32F)
1732 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1733 if(Format == WINED3DFMT_A32B32G32R32F)
1734 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
1736 /* Probably a color index mode */
1743 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1744 short depthSize, stencilSize;
1745 BOOL lockable = FALSE;
1750 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1751 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1755 if((Format == WINED3DFMT_D16_LOCKABLE) || (Format == WINED3DFMT_D32F_LOCKABLE))
1758 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
1759 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
1760 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
1761 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
1764 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
1765 * allow more stencil bits than requested. */
1766 if(cfg->stencilSize < stencilSize)
1772 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1773 WINED3DFORMAT AdapterFormat,
1774 WINED3DFORMAT RenderTargetFormat,
1775 WINED3DFORMAT DepthStencilFormat) {
1776 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1778 WineD3D_PixelFormat *cfgs;
1781 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1783 DeviceType, debug_d3ddevicetype(DeviceType),
1784 AdapterFormat, debug_d3dformat(AdapterFormat),
1785 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1786 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1788 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1789 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1790 return WINED3DERR_INVALIDCALL;
1793 cfgs = Adapters[Adapter].cfgs;
1794 nCfgs = Adapters[Adapter].nCfgs;
1795 for (it = 0; it < nCfgs; ++it) {
1796 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1797 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1798 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1803 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1805 return WINED3DERR_NOTAVAILABLE;
1808 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1809 WINED3DFORMAT SurfaceFormat,
1810 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1812 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1813 const GlPixelFormatDesc *glDesc;
1814 const StaticPixelFormatDesc *desc;
1816 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1819 DeviceType, debug_d3ddevicetype(DeviceType),
1820 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1825 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1826 return WINED3DERR_INVALIDCALL;
1829 /* TODO: handle Windowed, add more quality levels */
1831 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1833 /* By default multisampling is disabled right now as it causes issues
1834 * on some Nvidia driver versions and it doesn't work well in combination
1836 if(!wined3d_settings.allow_multisampling)
1837 return WINED3DERR_NOTAVAILABLE;
1839 desc = getFormatDescEntry(SurfaceFormat, &Adapters[Adapter].gl_info, &glDesc);
1840 if(!desc || !glDesc) {
1841 return WINED3DERR_INVALIDCALL;
1844 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
1846 WineD3D_PixelFormat *cfgs;
1848 cfgs = Adapters[Adapter].cfgs;
1849 nCfgs = Adapters[Adapter].nCfgs;
1850 for(i=0; i<nCfgs; i++) {
1851 if(cfgs[i].numSamples != MultiSampleType)
1854 if(!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[i], SurfaceFormat))
1857 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1860 *pQualityLevels = 1; /* Guess at a value! */
1864 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
1865 short redSize, greenSize, blueSize, alphaSize, colorBits;
1867 WineD3D_PixelFormat *cfgs;
1869 if(!getColorBits(SurfaceFormat, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1870 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
1871 return WINED3DERR_NOTAVAILABLE;
1874 cfgs = Adapters[Adapter].cfgs;
1875 nCfgs = Adapters[Adapter].nCfgs;
1876 for(i=0; i<nCfgs; i++) {
1877 if(cfgs[i].numSamples != MultiSampleType)
1879 if(cfgs[i].redSize != redSize)
1881 if(cfgs[i].greenSize != greenSize)
1883 if(cfgs[i].blueSize != blueSize)
1885 if(cfgs[i].alphaSize != alphaSize)
1888 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1891 *pQualityLevels = 1; /* Guess at a value! */
1895 return WINED3DERR_NOTAVAILABLE;
1898 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1899 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1901 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1902 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1905 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1908 DeviceType, debug_d3ddevicetype(DeviceType),
1909 DisplayFormat, debug_d3dformat(DisplayFormat),
1910 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1913 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1914 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1915 return WINED3DERR_INVALIDCALL;
1918 /* The task of this function is to check whether a certain display / backbuffer format
1919 * combination is available on the given adapter. In fullscreen mode microsoft specified
1920 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
1921 * and display format should match exactly.
1922 * In windowed mode format conversion can occur and this depends on the driver. When format
1923 * conversion is done, this function should nevertheless fail and applications need to use
1924 * CheckDeviceFormatConversion.
1925 * At the moment we assume that fullscreen and windowed have the same capabilities */
1927 /* There are only 4 display formats */
1928 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
1929 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
1930 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
1931 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
1933 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
1934 return WINED3DERR_NOTAVAILABLE;
1937 /* If the requested DisplayFormat is not available, don't continue */
1938 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
1940 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
1941 return WINED3DERR_NOTAVAILABLE;
1944 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
1945 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
1946 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
1947 return WINED3DERR_NOTAVAILABLE;
1950 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
1951 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
1952 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1953 return WINED3DERR_NOTAVAILABLE;
1956 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
1957 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
1958 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1959 return WINED3DERR_NOTAVAILABLE;
1962 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
1963 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
1964 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1965 return WINED3DERR_NOTAVAILABLE;
1968 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
1969 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
1970 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1971 return WINED3DERR_NOTAVAILABLE;
1974 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
1975 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
1977 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1983 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1984 /* Check if we support bumpmapping for a format */
1985 static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
1987 const struct fragment_pipeline *fp;
1988 const GlPixelFormatDesc *glDesc;
1990 switch(CheckFormat) {
1991 case WINED3DFMT_V8U8:
1992 case WINED3DFMT_V16U16:
1993 case WINED3DFMT_L6V5U5:
1994 case WINED3DFMT_X8L8V8U8:
1995 case WINED3DFMT_Q8W8V8U8:
1996 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
1997 if(glDesc->conversion_group == WINED3DFMT_UNKNOWN) {
1998 /* We have a GL extension giving native support */
1999 TRACE_(d3d_caps)("[OK]\n");
2003 /* No native support: Ask the fixed function pipeline implementation if it
2004 * can deal with the conversion
2006 fp = select_fragment_implementation(Adapter, DeviceType);
2007 if(fp->conv_supported(CheckFormat)) {
2008 TRACE_(d3d_caps)("[OK]\n");
2011 TRACE_(d3d_caps)("[FAILED]\n");
2016 TRACE_(d3d_caps)("[FAILED]\n");
2021 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2022 static BOOL CheckDepthStencilCapability(UINT Adapter, WINED3DFORMAT DisplayFormat, WINED3DFORMAT DepthStencilFormat)
2025 const GlPixelFormatDesc *glDesc;
2026 const StaticPixelFormatDesc *desc = getFormatDescEntry(DepthStencilFormat, &GLINFO_LOCATION, &glDesc);
2028 /* Fail if we weren't able to get a description of the format */
2029 if(!desc || !glDesc)
2032 /* Only allow depth/stencil formats */
2033 if(!(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
2036 /* Walk through all WGL pixel formats to find a match */
2037 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2038 WineD3D_PixelFormat *cfg = &Adapters[Adapter].cfgs[it];
2039 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(cfg, DisplayFormat)) {
2040 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(cfg, DepthStencilFormat)) {
2049 static BOOL CheckFilterCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2051 const GlPixelFormatDesc *glDesc;
2052 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2054 /* Fail if we weren't able to get a description of the format */
2055 if(!desc || !glDesc)
2058 /* The flags entry of a format contains the filtering capability */
2059 if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING)
2065 /* Check the render target capabilities of a format */
2066 static BOOL CheckRenderTargetCapability(WINED3DFORMAT AdapterFormat, WINED3DFORMAT CheckFormat)
2069 const GlPixelFormatDesc *glDesc;
2070 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2072 /* Fail if we weren't able to get a description of the format */
2073 if(!desc || !glDesc)
2076 /* Filter out non-RT formats */
2077 if(!(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET))
2080 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2081 WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs;
2083 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2084 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2086 getColorBits(AdapterFormat, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2087 getColorBits(CheckFormat, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2089 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2090 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2091 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2092 TRACE_(d3d_caps)("[FAILED]\n");
2096 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2097 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2098 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2099 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
2100 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2104 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2105 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2106 WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs;
2109 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2110 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2111 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
2112 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2116 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2117 /* For now return TRUE for FBOs until we have some proper checks.
2118 * Note that this function will only be called when the format is around for texturing. */
2124 static BOOL CheckSrgbReadCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2126 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2127 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2128 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2132 switch (CheckFormat) {
2133 case WINED3DFMT_A8R8G8B8:
2134 case WINED3DFMT_X8R8G8B8:
2135 case WINED3DFMT_A4R4G4B4:
2137 case WINED3DFMT_A8L8:
2138 case WINED3DFMT_DXT1:
2139 case WINED3DFMT_DXT2:
2140 case WINED3DFMT_DXT3:
2141 case WINED3DFMT_DXT4:
2142 case WINED3DFMT_DXT5:
2143 TRACE_(d3d_caps)("[OK]\n");
2147 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
2153 static BOOL CheckSrgbWriteCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2155 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2156 * doing the color fixup in shaders.
2157 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2158 if((CheckFormat == WINED3DFMT_X8R8G8B8) || (CheckFormat == WINED3DFMT_A8R8G8B8)) {
2159 int vs_selected_mode;
2160 int ps_selected_mode;
2161 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
2163 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2164 TRACE_(d3d_caps)("[OK]\n");
2169 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(CheckFormat));
2173 /* Check if a format support blending in combination with pixel shaders */
2174 static BOOL CheckPostPixelShaderBlendingCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2176 const GlPixelFormatDesc *glDesc;
2177 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2179 /* Fail if we weren't able to get a description of the format */
2180 if(!desc || !glDesc)
2183 /* The flags entry of a format contains the post pixel shader blending capability */
2184 if(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
2190 static BOOL CheckWrapAndMipCapability(UINT Adapter, WINED3DFORMAT CheckFormat) {
2191 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2192 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2193 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2194 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2195 * capability anyway.
2197 * For now lets report this on all formats, but in the future we may want to
2198 * restrict it to some should games need that
2203 /* Check if a texture format is supported on the given adapter */
2204 static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2206 const shader_backend_t *shader_backend;
2207 const struct fragment_pipeline *fp;
2208 const GlPixelFormatDesc *glDesc;
2210 switch (CheckFormat) {
2213 * supported: RGB(A) formats
2215 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2216 case WINED3DFMT_A8R8G8B8:
2217 case WINED3DFMT_X8R8G8B8:
2218 case WINED3DFMT_R5G6B5:
2219 case WINED3DFMT_X1R5G5B5:
2220 case WINED3DFMT_A1R5G5B5:
2221 case WINED3DFMT_A4R4G4B4:
2223 case WINED3DFMT_X4R4G4B4:
2224 case WINED3DFMT_A8B8G8R8:
2225 case WINED3DFMT_X8B8G8R8:
2226 case WINED3DFMT_A2R10G10B10:
2227 case WINED3DFMT_A2B10G10R10:
2228 case WINED3DFMT_G16R16:
2229 TRACE_(d3d_caps)("[OK]\n");
2232 case WINED3DFMT_R3G3B2:
2233 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2237 * supported: Palettized
2240 TRACE_(d3d_caps)("[OK]\n");
2242 /* No Windows driver offers A8P8, so don't offer it either */
2243 case WINED3DFMT_A8P8:
2247 * Supported: (Alpha)-Luminance
2250 case WINED3DFMT_A8L8:
2251 case WINED3DFMT_L16:
2252 TRACE_(d3d_caps)("[OK]\n");
2255 /* Not supported on Windows, thus disabled */
2256 case WINED3DFMT_A4L4:
2257 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2261 * Supported: Depth/Stencil formats
2263 case WINED3DFMT_D16_LOCKABLE:
2264 case WINED3DFMT_D16:
2265 case WINED3DFMT_D15S1:
2266 case WINED3DFMT_D24X8:
2267 case WINED3DFMT_D24X4S4:
2268 case WINED3DFMT_D24S8:
2269 case WINED3DFMT_D24FS8:
2270 case WINED3DFMT_D32:
2271 case WINED3DFMT_D32F_LOCKABLE:
2275 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2276 * GL_NV_texture_shader). Emulated by shaders
2278 case WINED3DFMT_V8U8:
2279 case WINED3DFMT_X8L8V8U8:
2280 case WINED3DFMT_L6V5U5:
2281 case WINED3DFMT_Q8W8V8U8:
2282 case WINED3DFMT_V16U16:
2283 case WINED3DFMT_W11V11U10:
2284 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2285 if(glDesc->conversion_group == WINED3DFMT_UNKNOWN) {
2286 /* We have a GL extension giving native support */
2287 TRACE_(d3d_caps)("[OK]\n");
2291 /* No native support: Ask the fixed function pipeline implementation if it
2292 * can deal with the conversion
2294 shader_backend = select_shader_backend(Adapter, DeviceType);
2295 if(shader_backend->shader_conv_supported(CheckFormat)) {
2296 TRACE_(d3d_caps)("[OK]\n");
2299 TRACE_(d3d_caps)("[FAILED]\n");
2303 case WINED3DFMT_DXT1:
2304 case WINED3DFMT_DXT2:
2305 case WINED3DFMT_DXT3:
2306 case WINED3DFMT_DXT4:
2307 case WINED3DFMT_DXT5:
2308 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2309 TRACE_(d3d_caps)("[OK]\n");
2312 TRACE_(d3d_caps)("[FAILED]\n");
2317 * Odd formats - not supported
2319 case WINED3DFMT_VERTEXDATA:
2320 case WINED3DFMT_INDEX16:
2321 case WINED3DFMT_INDEX32:
2322 case WINED3DFMT_Q16W16V16U16:
2323 case WINED3DFMT_A2W10V10U10:
2324 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2328 * WINED3DFMT_CxV8U8: Not supported right now
2330 case WINED3DFMT_CxV8U8:
2331 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2335 case WINED3DFMT_UYVY:
2336 case WINED3DFMT_YUY2:
2337 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2338 TRACE_(d3d_caps)("[OK]\n");
2341 TRACE_(d3d_caps)("[FAILED]\n");
2343 case WINED3DFMT_YV12:
2344 TRACE_(d3d_caps)("[FAILED]\n");
2348 case WINED3DFMT_A16B16G16R16:
2349 case WINED3DFMT_A8R3G3B2:
2350 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2353 /* Floating point formats */
2354 case WINED3DFMT_R16F:
2355 case WINED3DFMT_A16B16G16R16F:
2356 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2357 TRACE_(d3d_caps)("[OK]\n");
2360 TRACE_(d3d_caps)("[FAILED]\n");
2363 case WINED3DFMT_R32F:
2364 case WINED3DFMT_A32B32G32R32F:
2365 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2366 TRACE_(d3d_caps)("[OK]\n");
2369 TRACE_(d3d_caps)("[FAILED]\n");
2372 case WINED3DFMT_G16R16F:
2373 case WINED3DFMT_G32R32F:
2374 TRACE_(d3d_caps)("[FAILED]\n");
2377 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2378 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2379 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2380 * We can do instancing with all shader versions, but we need vertex shaders.
2382 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2383 * to enable instancing. WineD3D doesn't need that and just ignores it.
2385 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2387 case WINEMAKEFOURCC('I','N','S','T'):
2388 TRACE("ATI Instancing check hack\n");
2389 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2390 TRACE_(d3d_caps)("[OK]\n");
2393 TRACE_(d3d_caps)("[FAILED]\n");
2396 /* Some weird FOURCC formats */
2397 case WINED3DFMT_R8G8_B8G8:
2398 case WINED3DFMT_G8R8_G8B8:
2399 case WINED3DFMT_MULTI2_ARGB8:
2400 TRACE_(d3d_caps)("[FAILED]\n");
2403 /* Vendor specific formats */
2404 case WINED3DFMT_ATI2N:
2405 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2406 shader_backend = select_shader_backend(Adapter, DeviceType);
2407 fp = select_fragment_implementation(Adapter, DeviceType);
2408 if(shader_backend->shader_conv_supported(CheckFormat) &&
2409 fp->conv_supported(CheckFormat)) {
2410 TRACE_(d3d_caps)("[OK]\n");
2414 TRACE_(d3d_caps)("[OK]\n");
2417 TRACE_(d3d_caps)("[FAILED]\n");
2420 case WINED3DFMT_NVHU:
2421 case WINED3DFMT_NVHS:
2422 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2423 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2424 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2425 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2426 * Applications have to deal with not having NVHS and NVHU.
2428 TRACE_(d3d_caps)("[FAILED]\n");
2431 case WINED3DFMT_UNKNOWN:
2435 ERR("Unhandled format=%s\n", debug_d3dformat(CheckFormat));
2441 static BOOL CheckSurfaceCapability(UINT Adapter, WINED3DFORMAT AdapterFormat, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType) {
2442 const struct blit_shader *blitter;
2444 if(SurfaceType == SURFACE_GDI) {
2445 switch(CheckFormat) {
2446 case WINED3DFMT_R8G8B8:
2447 case WINED3DFMT_A8R8G8B8:
2448 case WINED3DFMT_X8R8G8B8:
2449 case WINED3DFMT_R5G6B5:
2450 case WINED3DFMT_X1R5G5B5:
2451 case WINED3DFMT_A1R5G5B5:
2452 case WINED3DFMT_A4R4G4B4:
2453 case WINED3DFMT_R3G3B2:
2455 case WINED3DFMT_A8R3G3B2:
2456 case WINED3DFMT_X4R4G4B4:
2457 case WINED3DFMT_A2B10G10R10:
2458 case WINED3DFMT_A8B8G8R8:
2459 case WINED3DFMT_X8B8G8R8:
2460 case WINED3DFMT_G16R16:
2461 case WINED3DFMT_A2R10G10B10:
2462 case WINED3DFMT_A16B16G16R16:
2464 TRACE_(d3d_caps)("[OK]\n");
2467 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
2472 /* All format that are supported for textures are supported for surfaces as well */
2473 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) return TRUE;
2474 /* All depth stencil formats are supported on surfaces */
2475 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) return TRUE;
2477 /* If opengl can't process the format natively, the blitter may be able to convert it */
2478 blitter = select_blit_implementation(Adapter, DeviceType);
2479 if(blitter->conv_supported(CheckFormat)) {
2480 TRACE_(d3d_caps)("[OK]\n");
2484 /* Reject other formats */
2485 TRACE_(d3d_caps)("[FAILED]\n");
2489 static BOOL CheckVertexTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2491 if (!GL_LIMITS(vertex_samplers)) {
2492 TRACE_(d3d_caps)("[FAILED]\n");
2496 switch (CheckFormat) {
2497 case WINED3DFMT_A32B32G32R32F:
2498 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2499 TRACE_(d3d_caps)("[FAILED]\n");
2502 TRACE_(d3d_caps)("[OK]\n");
2506 TRACE_(d3d_caps)("[FAILED]\n");
2512 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2513 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
2514 WINED3DSURFTYPE SurfaceType) {
2515 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2516 DWORD UsageCaps = 0;
2518 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
2521 DeviceType, debug_d3ddevicetype(DeviceType),
2522 AdapterFormat, debug_d3dformat(AdapterFormat),
2523 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
2524 RType, debug_d3dresourcetype(RType),
2525 CheckFormat, debug_d3dformat(CheckFormat));
2527 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2528 return WINED3DERR_INVALIDCALL;
2531 if(RType == WINED3DRTYPE_CUBETEXTURE) {
2533 if(SurfaceType != SURFACE_OPENGL) {
2534 TRACE("[FAILED]\n");
2535 return WINED3DERR_NOTAVAILABLE;
2538 /* Cubetexture allows:
2539 * - D3DUSAGE_AUTOGENMIPMAP
2540 * - D3DUSAGE_DEPTHSTENCIL
2541 * - D3DUSAGE_DYNAMIC
2542 * - D3DUSAGE_NONSECURE (d3d9ex)
2543 * - D3DUSAGE_RENDERTARGET
2544 * - D3DUSAGE_SOFTWAREPROCESSING
2545 * - D3DUSAGE_QUERY_WRAPANDMIP
2547 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2548 /* Check if the texture format is around */
2549 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
2550 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2551 /* Check for automatic mipmap generation support */
2552 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2553 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2555 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2556 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2560 /* Always report dynamic locking */
2561 if(Usage & WINED3DUSAGE_DYNAMIC)
2562 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2564 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2565 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2566 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2568 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2569 return WINED3DERR_NOTAVAILABLE;
2573 /* Always report software processing */
2574 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2575 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2577 /* Check QUERY_FILTER support */
2578 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2579 if(CheckFilterCapability(Adapter, CheckFormat)) {
2580 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2582 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2583 return WINED3DERR_NOTAVAILABLE;
2587 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2588 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2589 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2590 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2592 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2593 return WINED3DERR_NOTAVAILABLE;
2597 /* Check QUERY_SRGBREAD support */
2598 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2599 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2600 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2602 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2603 return WINED3DERR_NOTAVAILABLE;
2607 /* Check QUERY_SRGBWRITE support */
2608 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2609 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2610 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2612 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2613 return WINED3DERR_NOTAVAILABLE;
2617 /* Check QUERY_VERTEXTEXTURE support */
2618 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2619 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2620 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2622 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2623 return WINED3DERR_NOTAVAILABLE;
2627 /* Check QUERY_WRAPANDMIP support */
2628 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2629 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2630 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2632 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2633 return WINED3DERR_NOTAVAILABLE;
2637 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
2638 return WINED3DERR_NOTAVAILABLE;
2641 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
2642 return WINED3DERR_NOTAVAILABLE;
2644 } else if(RType == WINED3DRTYPE_SURFACE) {
2646 * - D3DUSAGE_DEPTHSTENCIL
2647 * - D3DUSAGE_NONSECURE (d3d9ex)
2648 * - D3DUSAGE_RENDERTARGET
2651 if(CheckSurfaceCapability(Adapter, AdapterFormat, DeviceType, CheckFormat, SurfaceType)) {
2652 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2653 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
2654 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2656 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
2657 return WINED3DERR_NOTAVAILABLE;
2661 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2662 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2663 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2665 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2666 return WINED3DERR_NOTAVAILABLE;
2670 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2671 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2672 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2673 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2675 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2676 return WINED3DERR_NOTAVAILABLE;
2680 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
2681 return WINED3DERR_NOTAVAILABLE;
2684 } else if(RType == WINED3DRTYPE_TEXTURE) {
2686 * - D3DUSAGE_AUTOGENMIPMAP
2687 * - D3DUSAGE_DEPTHSTENCIL
2689 * - D3DUSAGE_DYNAMIC
2690 * - D3DUSAGE_NONSECURE (d3d9ex)
2691 * - D3DUSAGE_RENDERTARGET
2692 * - D3DUSAGE_SOFTWAREPROCESSING
2693 * - D3DUSAGE_TEXTAPI (d3d9ex)
2694 * - D3DUSAGE_QUERY_WRAPANDMIP
2697 if(SurfaceType != SURFACE_OPENGL) {
2698 TRACE("[FAILED]\n");
2699 return WINED3DERR_NOTAVAILABLE;
2702 /* Check if the texture format is around */
2703 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
2704 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2705 /* Check for automatic mipmap generation support */
2706 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2707 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2709 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2710 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2714 /* Always report dynamic locking */
2715 if(Usage & WINED3DUSAGE_DYNAMIC)
2716 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2718 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2719 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2720 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2722 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2723 return WINED3DERR_NOTAVAILABLE;
2727 /* Always report software processing */
2728 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2729 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2731 /* Check QUERY_FILTER support */
2732 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2733 if(CheckFilterCapability(Adapter, CheckFormat)) {
2734 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2736 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2737 return WINED3DERR_NOTAVAILABLE;
2741 /* Check QUERY_LEGACYBUMPMAP support */
2742 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
2743 if(CheckBumpMapCapability(Adapter, DeviceType, CheckFormat)) {
2744 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
2746 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
2747 return WINED3DERR_NOTAVAILABLE;
2751 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2752 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2753 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2754 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2756 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2757 return WINED3DERR_NOTAVAILABLE;
2761 /* Check QUERY_SRGBREAD support */
2762 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2763 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2764 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2766 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2767 return WINED3DERR_NOTAVAILABLE;
2771 /* Check QUERY_SRGBWRITE support */
2772 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2773 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2774 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2776 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2777 return WINED3DERR_NOTAVAILABLE;
2781 /* Check QUERY_VERTEXTEXTURE support */
2782 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2783 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2784 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2786 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2787 return WINED3DERR_NOTAVAILABLE;
2791 /* Check QUERY_WRAPANDMIP support */
2792 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2793 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2794 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2796 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2797 return WINED3DERR_NOTAVAILABLE;
2801 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2802 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
2803 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2805 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
2806 return WINED3DERR_NOTAVAILABLE;
2810 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
2811 return WINED3DERR_NOTAVAILABLE;
2813 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
2814 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
2815 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
2817 * Volumetexture allows:
2818 * - D3DUSAGE_DYNAMIC
2819 * - D3DUSAGE_NONSECURE (d3d9ex)
2820 * - D3DUSAGE_SOFTWAREPROCESSING
2821 * - D3DUSAGE_QUERY_WRAPANDMIP
2824 if(SurfaceType != SURFACE_OPENGL) {
2825 TRACE("[FAILED]\n");
2826 return WINED3DERR_NOTAVAILABLE;
2829 /* Check volume texture and volume usage caps */
2830 if(GL_SUPPORT(EXT_TEXTURE3D)) {
2831 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat) == FALSE) {
2832 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
2833 return WINED3DERR_NOTAVAILABLE;
2836 /* Always report dynamic locking */
2837 if(Usage & WINED3DUSAGE_DYNAMIC)
2838 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2840 /* Always report software processing */
2841 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2842 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2844 /* Check QUERY_FILTER support */
2845 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2846 if(CheckFilterCapability(Adapter, CheckFormat)) {
2847 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2849 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2850 return WINED3DERR_NOTAVAILABLE;
2854 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2855 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2856 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2857 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2859 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2860 return WINED3DERR_NOTAVAILABLE;
2864 /* Check QUERY_SRGBREAD support */
2865 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2866 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2867 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2869 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2870 return WINED3DERR_NOTAVAILABLE;
2874 /* Check QUERY_SRGBWRITE support */
2875 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2876 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2877 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2879 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2880 return WINED3DERR_NOTAVAILABLE;
2884 /* Check QUERY_VERTEXTEXTURE support */
2885 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2886 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2887 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2889 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2890 return WINED3DERR_NOTAVAILABLE;
2894 /* Check QUERY_WRAPANDMIP support */
2895 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2896 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2897 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2899 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2900 return WINED3DERR_NOTAVAILABLE;
2904 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
2905 return WINED3DERR_NOTAVAILABLE;
2908 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
2909 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
2910 * app needing one of those formats, don't advertize them to avoid leading apps into
2911 * temptation. The windows drivers don't support most of those formats on volumes anyway,
2914 switch(CheckFormat) {
2916 case WINED3DFMT_A4L4:
2917 case WINED3DFMT_R32F:
2918 case WINED3DFMT_R16F:
2919 case WINED3DFMT_X8L8V8U8:
2920 case WINED3DFMT_L6V5U5:
2921 case WINED3DFMT_G16R16:
2922 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2923 return WINED3DERR_NOTAVAILABLE;
2925 case WINED3DFMT_Q8W8V8U8:
2926 case WINED3DFMT_V16U16:
2927 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2928 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2929 return WINED3DERR_NOTAVAILABLE;
2933 case WINED3DFMT_V8U8:
2934 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2935 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2936 return WINED3DERR_NOTAVAILABLE;
2940 case WINED3DFMT_DXT1:
2941 case WINED3DFMT_DXT2:
2942 case WINED3DFMT_DXT3:
2943 case WINED3DFMT_DXT4:
2944 case WINED3DFMT_DXT5:
2945 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
2946 * compressed texture results in an error. While the D3D refrast does
2947 * support s3tc volumes, at least the nvidia windows driver does not, so
2948 * we're free not to support this format.
2950 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
2951 return WINED3DERR_NOTAVAILABLE;
2954 /* Do nothing, continue with checking the format below */
2957 } else if((RType == WINED3DRTYPE_INDEXBUFFER) || (RType == WINED3DRTYPE_VERTEXBUFFER)){
2958 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
2959 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
2960 return WINED3DERR_NOTAVAILABLE;
2963 /* This format is nothing special and it is supported perfectly.
2964 * However, ati and nvidia driver on windows do not mark this format as
2965 * supported (tested with the dxCapsViewer) and pretending to
2966 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
2967 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
2968 * Enable it on dx7. It will need additional checking on dx10 when we support it.
2970 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
2971 TRACE_(d3d_caps)("[FAILED]\n");
2972 return WINED3DERR_NOTAVAILABLE;
2975 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
2976 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
2977 * usage flags match. */
2978 if(UsageCaps == Usage) {
2980 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
2981 return WINED3DOK_NOAUTOGEN;
2983 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);
2984 return WINED3DERR_NOTAVAILABLE;
2988 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2989 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2990 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2992 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2995 DeviceType, debug_d3ddevicetype(DeviceType),
2996 SourceFormat, debug_d3dformat(SourceFormat),
2997 TargetFormat, debug_d3dformat(TargetFormat));
3001 static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3002 const shader_backend_t *ret;
3003 int vs_selected_mode;
3004 int ps_selected_mode;
3006 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3007 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3008 ret = &glsl_shader_backend;
3009 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3010 ret = &arb_program_shader_backend;
3012 ret = &none_shader_backend;
3017 static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3018 int vs_selected_mode;
3019 int ps_selected_mode;
3021 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3022 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3023 return &arbfp_fragment_pipeline;
3024 } else if(ps_selected_mode == SHADER_ATI) {
3025 return &atifs_fragment_pipeline;
3026 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3027 return &nvts_fragment_pipeline;
3028 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3029 return &nvrc_fragment_pipeline;
3031 return &ffp_fragment_pipeline;
3035 static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3036 int vs_selected_mode;
3037 int ps_selected_mode;
3039 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3040 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3047 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3048 subset of a D3DCAPS9 structure. However, it has to come via a void *
3049 as the d3d8 interface cannot import the d3d9 header */
3050 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3052 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3053 int vs_selected_mode;
3054 int ps_selected_mode;
3055 struct shader_caps shader_caps;
3056 struct fragment_caps fragment_caps;
3057 const shader_backend_t *shader_backend;
3058 const struct fragment_pipeline *frag_pipeline = NULL;
3059 DWORD ckey_caps, blit_caps, fx_caps;
3061 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3063 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3064 return WINED3DERR_INVALIDCALL;
3067 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3069 /* This function should *not* be modifying GL caps
3070 * TODO: move the functionality where it belongs */
3071 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
3073 /* ------------------------------------------------
3074 The following fields apply to both d3d8 and d3d9
3075 ------------------------------------------------ */
3076 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3077 pCaps->AdapterOrdinal = Adapter;
3080 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3081 WINED3DCAPS2_FULLSCREENGAMMA |
3082 WINED3DCAPS2_DYNAMICTEXTURES;
3083 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3084 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3087 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3088 WINED3DCAPS3_COPY_TO_VIDMEM |
3089 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3091 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3092 WINED3DPRESENT_INTERVAL_ONE;
3094 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3095 WINED3DCURSORCAPS_LOWRES;
3097 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3098 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3099 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3100 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3101 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3102 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3103 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3104 WINED3DDEVCAPS_PUREDEVICE |
3105 WINED3DDEVCAPS_HWRASTERIZATION |
3106 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3107 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3108 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3109 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3110 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3111 WINED3DDEVCAPS_RTPATCHES;
3113 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3114 WINED3DPMISCCAPS_CULLCCW |
3115 WINED3DPMISCCAPS_CULLCW |
3116 WINED3DPMISCCAPS_COLORWRITEENABLE |
3117 WINED3DPMISCCAPS_CLIPTLVERTS |
3118 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3119 WINED3DPMISCCAPS_MASKZ |
3120 WINED3DPMISCCAPS_BLENDOP |
3121 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3123 WINED3DPMISCCAPS_NULLREFERENCE
3124 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3125 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3126 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3127 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3129 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3130 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3132 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3133 WINED3DPRASTERCAPS_PAT |
3134 WINED3DPRASTERCAPS_WFOG |
3135 WINED3DPRASTERCAPS_ZFOG |
3136 WINED3DPRASTERCAPS_FOGVERTEX |
3137 WINED3DPRASTERCAPS_FOGTABLE |
3138 WINED3DPRASTERCAPS_STIPPLE |
3139 WINED3DPRASTERCAPS_SUBPIXEL |
3140 WINED3DPRASTERCAPS_ZTEST |
3141 WINED3DPRASTERCAPS_SCISSORTEST |
3142 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3143 WINED3DPRASTERCAPS_DEPTHBIAS;
3145 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3146 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3147 WINED3DPRASTERCAPS_ZBIAS |
3148 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3150 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3151 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3154 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3155 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3156 WINED3DPRASTERCAPS_ANTIALIASEDGES
3157 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3158 WINED3DPRASTERCAPS_WBUFFER */
3160 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3161 WINED3DPCMPCAPS_EQUAL |
3162 WINED3DPCMPCAPS_GREATER |
3163 WINED3DPCMPCAPS_GREATEREQUAL |
3164 WINED3DPCMPCAPS_LESS |
3165 WINED3DPCMPCAPS_LESSEQUAL |
3166 WINED3DPCMPCAPS_NEVER |
3167 WINED3DPCMPCAPS_NOTEQUAL;
3169 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3170 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3171 WINED3DPBLENDCAPS_DESTALPHA |
3172 WINED3DPBLENDCAPS_DESTCOLOR |
3173 WINED3DPBLENDCAPS_INVDESTALPHA |
3174 WINED3DPBLENDCAPS_INVDESTCOLOR |
3175 WINED3DPBLENDCAPS_INVSRCALPHA |
3176 WINED3DPBLENDCAPS_INVSRCCOLOR |
3177 WINED3DPBLENDCAPS_ONE |
3178 WINED3DPBLENDCAPS_SRCALPHA |
3179 WINED3DPBLENDCAPS_SRCALPHASAT |
3180 WINED3DPBLENDCAPS_SRCCOLOR |
3181 WINED3DPBLENDCAPS_ZERO;
3183 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3184 WINED3DPBLENDCAPS_DESTCOLOR |
3185 WINED3DPBLENDCAPS_INVDESTALPHA |
3186 WINED3DPBLENDCAPS_INVDESTCOLOR |
3187 WINED3DPBLENDCAPS_INVSRCALPHA |
3188 WINED3DPBLENDCAPS_INVSRCCOLOR |
3189 WINED3DPBLENDCAPS_ONE |
3190 WINED3DPBLENDCAPS_SRCALPHA |
3191 WINED3DPBLENDCAPS_SRCCOLOR |
3192 WINED3DPBLENDCAPS_ZERO;
3193 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3194 * according to the glBlendFunc manpage
3196 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3197 * legacy settings for srcblend only
3200 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3201 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3202 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3206 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3207 WINED3DPCMPCAPS_EQUAL |
3208 WINED3DPCMPCAPS_GREATER |
3209 WINED3DPCMPCAPS_GREATEREQUAL |
3210 WINED3DPCMPCAPS_LESS |
3211 WINED3DPCMPCAPS_LESSEQUAL |
3212 WINED3DPCMPCAPS_NEVER |
3213 WINED3DPCMPCAPS_NOTEQUAL;
3215 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3216 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3217 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3218 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3219 WINED3DPSHADECAPS_COLORFLATRGB |
3220 WINED3DPSHADECAPS_FOGFLAT |
3221 WINED3DPSHADECAPS_FOGGOURAUD |
3222 WINED3DPSHADECAPS_SPECULARFLATRGB;
3224 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3225 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3226 WINED3DPTEXTURECAPS_TRANSPARENCY |
3227 WINED3DPTEXTURECAPS_BORDER |
3228 WINED3DPTEXTURECAPS_MIPMAP |
3229 WINED3DPTEXTURECAPS_PROJECTED |
3230 WINED3DPTEXTURECAPS_PERSPECTIVE;
3232 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3233 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3234 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3237 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3238 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3239 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3240 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3243 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3244 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3245 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3246 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3250 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3251 WINED3DPTFILTERCAPS_MAGFPOINT |
3252 WINED3DPTFILTERCAPS_MINFLINEAR |
3253 WINED3DPTFILTERCAPS_MINFPOINT |
3254 WINED3DPTFILTERCAPS_MIPFLINEAR |
3255 WINED3DPTFILTERCAPS_MIPFPOINT |
3256 WINED3DPTFILTERCAPS_LINEAR |
3257 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3258 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3259 WINED3DPTFILTERCAPS_MIPLINEAR |
3260 WINED3DPTFILTERCAPS_MIPNEAREST |
3261 WINED3DPTFILTERCAPS_NEAREST;
3263 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3264 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3265 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3268 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3269 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3270 WINED3DPTFILTERCAPS_MAGFPOINT |
3271 WINED3DPTFILTERCAPS_MINFLINEAR |
3272 WINED3DPTFILTERCAPS_MINFPOINT |
3273 WINED3DPTFILTERCAPS_MIPFLINEAR |
3274 WINED3DPTFILTERCAPS_MIPFPOINT |
3275 WINED3DPTFILTERCAPS_LINEAR |
3276 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3277 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3278 WINED3DPTFILTERCAPS_MIPLINEAR |
3279 WINED3DPTFILTERCAPS_MIPNEAREST |
3280 WINED3DPTFILTERCAPS_NEAREST;
3282 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3283 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3284 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3287 pCaps->CubeTextureFilterCaps = 0;
3289 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3290 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3291 WINED3DPTFILTERCAPS_MAGFPOINT |
3292 WINED3DPTFILTERCAPS_MINFLINEAR |
3293 WINED3DPTFILTERCAPS_MINFPOINT |
3294 WINED3DPTFILTERCAPS_MIPFLINEAR |
3295 WINED3DPTFILTERCAPS_MIPFPOINT |
3296 WINED3DPTFILTERCAPS_LINEAR |
3297 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3298 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3299 WINED3DPTFILTERCAPS_MIPLINEAR |
3300 WINED3DPTFILTERCAPS_MIPNEAREST |
3301 WINED3DPTFILTERCAPS_NEAREST;
3303 pCaps->VolumeTextureFilterCaps = 0;
3305 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3306 WINED3DPTADDRESSCAPS_CLAMP |
3307 WINED3DPTADDRESSCAPS_WRAP;
3309 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3310 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3312 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3313 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3315 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3316 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3319 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3320 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3321 WINED3DPTADDRESSCAPS_CLAMP |
3322 WINED3DPTADDRESSCAPS_WRAP;
3323 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3324 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3326 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3327 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3329 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3330 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3333 pCaps->VolumeTextureAddressCaps = 0;
3335 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3336 WINED3DLINECAPS_ZTEST |
3337 WINED3DLINECAPS_BLEND |
3338 WINED3DLINECAPS_ALPHACMP |
3339 WINED3DLINECAPS_FOG;
3340 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3341 * idea how generating the smoothing alpha values works; the result is different
3344 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3345 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3347 if(GL_SUPPORT(EXT_TEXTURE3D))
3348 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3350 pCaps->MaxVolumeExtent = 0;
3352 pCaps->MaxTextureRepeat = 32768;
3353 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3354 pCaps->MaxVertexW = 1.0;
3356 pCaps->GuardBandLeft = 0;
3357 pCaps->GuardBandTop = 0;
3358 pCaps->GuardBandRight = 0;
3359 pCaps->GuardBandBottom = 0;
3361 pCaps->ExtentsAdjust = 0;
3363 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3364 WINED3DSTENCILCAPS_INCRSAT |
3365 WINED3DSTENCILCAPS_INVERT |
3366 WINED3DSTENCILCAPS_KEEP |
3367 WINED3DSTENCILCAPS_REPLACE |
3368 WINED3DSTENCILCAPS_ZERO;
3369 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3370 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3371 WINED3DSTENCILCAPS_INCR;
3373 if ( This->dxVersion > 8 &&
3374 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
3375 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
3376 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3379 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3381 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3382 pCaps->MaxActiveLights = GL_LIMITS(lights);
3384 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3385 pCaps->MaxVertexBlendMatrixIndex = 0;
3387 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3388 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3391 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3392 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3393 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3394 WINED3DVTXPCAPS_LOCALVIEWER |
3395 WINED3DVTXPCAPS_VERTEXFOG |
3396 WINED3DVTXPCAPS_TEXGEN;
3398 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3400 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3401 pCaps->MaxVertexIndex = 0xFFFFF;
3402 pCaps->MaxStreams = MAX_STREAMS;
3403 pCaps->MaxStreamStride = 1024;
3405 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3406 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3407 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3408 pCaps->MaxNpatchTessellationLevel = 0;
3409 pCaps->MasterAdapterOrdinal = 0;
3410 pCaps->AdapterOrdinalInGroup = 0;
3411 pCaps->NumberOfAdaptersInGroup = 1;
3413 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3415 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3416 WINED3DPTFILTERCAPS_MAGFPOINT |
3417 WINED3DPTFILTERCAPS_MINFLINEAR |
3418 WINED3DPTFILTERCAPS_MAGFLINEAR;
3419 pCaps->VertexTextureFilterCaps = 0;
3421 memset(&shader_caps, 0, sizeof(shader_caps));
3422 shader_backend = select_shader_backend(Adapter, DeviceType);
3423 shader_backend->shader_get_caps(DeviceType, &GLINFO_LOCATION, &shader_caps);
3425 memset(&fragment_caps, 0, sizeof(fragment_caps));
3426 frag_pipeline = select_fragment_implementation(Adapter, DeviceType);
3427 frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &fragment_caps);
3429 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
3430 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
3432 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
3433 * Ignore shader model capabilities if disabled in config
3435 if(vs_selected_mode == SHADER_NONE) {
3436 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
3437 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
3438 pCaps->MaxVertexShaderConst = 0;
3440 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
3441 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
3444 if(ps_selected_mode == SHADER_NONE) {
3445 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
3446 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
3447 pCaps->PixelShader1xMaxValue = 0.0;
3449 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
3450 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
3453 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
3454 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
3455 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
3457 pCaps->VS20Caps = shader_caps.VS20Caps;
3458 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
3459 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
3460 pCaps->PS20Caps = shader_caps.PS20Caps;
3461 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
3462 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
3464 /* The following caps are shader specific, but they are things we cannot detect, or which
3465 * are the same among all shader models. So to avoid code duplication set the shader version
3466 * specific, but otherwise constant caps here
3468 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
3469 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3470 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
3471 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
3472 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3473 pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
3474 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
3476 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
3477 pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
3478 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
3479 pCaps->VS20Caps.Caps = 0;
3480 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
3481 pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
3482 pCaps->VS20Caps.StaticFlowControlDepth = 1;
3484 pCaps->MaxVShaderInstructionsExecuted = 65535;
3485 pCaps->MaxVertexShader30InstructionSlots = 0;
3486 } else { /* VS 1.x */
3487 pCaps->VS20Caps.Caps = 0;
3488 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
3489 pCaps->VS20Caps.NumTemps = 0;
3490 pCaps->VS20Caps.StaticFlowControlDepth = 0;
3492 pCaps->MaxVShaderInstructionsExecuted = 0;
3493 pCaps->MaxVertexShader30InstructionSlots = 0;
3496 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
3497 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3498 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
3500 /* 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 */
3501 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
3502 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
3503 WINED3DPS20CAPS_PREDICATION |
3504 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
3505 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
3506 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3507 pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
3508 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
3509 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
3511 pCaps->MaxPShaderInstructionsExecuted = 65535;
3512 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
3513 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
3514 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
3515 pCaps->PS20Caps.Caps = 0;
3516 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
3517 pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
3518 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
3519 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
3521 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
3522 pCaps->MaxPixelShader30InstructionSlots = 0;
3523 } else { /* PS 1.x */
3524 pCaps->PS20Caps.Caps = 0;
3525 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
3526 pCaps->PS20Caps.NumTemps = 0;
3527 pCaps->PS20Caps.StaticFlowControlDepth = 0;
3528 pCaps->PS20Caps.NumInstructionSlots = 0;
3530 pCaps->MaxPShaderInstructionsExecuted = 0;
3531 pCaps->MaxPixelShader30InstructionSlots = 0;
3534 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
3535 /* OpenGL supports all the formats below, perhaps not always
3536 * without conversion, but it supports them.
3537 * Further GLSL doesn't seem to have an official unsigned type so
3538 * don't advertise it yet as I'm not sure how we handle it.
3539 * We might need to add some clamping in the shader engine to
3541 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
3542 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
3543 WINED3DDTCAPS_UBYTE4N |
3544 WINED3DDTCAPS_SHORT2N |
3545 WINED3DDTCAPS_SHORT4N;
3546 if (GL_SUPPORT(NV_HALF_FLOAT)) {
3547 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
3548 WINED3DDTCAPS_FLOAT16_4;
3551 pCaps->DeclTypes = 0;
3553 /* Set DirectDraw helper Caps */
3554 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
3555 WINEDDCKEYCAPS_SRCBLT;
3556 fx_caps = WINEDDFXCAPS_BLTALPHA |
3557 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
3558 WINEDDFXCAPS_BLTMIRRORUPDOWN |
3559 WINEDDFXCAPS_BLTROTATION90 |
3560 WINEDDFXCAPS_BLTSHRINKX |
3561 WINEDDFXCAPS_BLTSHRINKXN |
3562 WINEDDFXCAPS_BLTSHRINKY |
3563 WINEDDFXCAPS_BLTSHRINKXN |
3564 WINEDDFXCAPS_BLTSTRETCHX |
3565 WINEDDFXCAPS_BLTSTRETCHXN |
3566 WINEDDFXCAPS_BLTSTRETCHY |
3567 WINEDDFXCAPS_BLTSTRETCHYN;
3568 blit_caps = WINEDDCAPS_BLT |
3569 WINEDDCAPS_BLTCOLORFILL |
3570 WINEDDCAPS_BLTDEPTHFILL |
3571 WINEDDCAPS_BLTSTRETCH |
3572 WINEDDCAPS_CANBLTSYSMEM |
3573 WINEDDCAPS_CANCLIP |
3574 WINEDDCAPS_CANCLIPSTRETCHED |
3575 WINEDDCAPS_COLORKEY |
3576 WINEDDCAPS_COLORKEYHWASSIST |
3577 WINEDDCAPS_ALIGNBOUNDARYSRC;
3579 /* Fill the ddraw caps structure */
3580 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
3581 WINEDDCAPS_PALETTE |
3583 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
3584 WINEDDCAPS2_NOPAGELOCKREQUIRED |
3585 WINEDDCAPS2_PRIMARYGAMMA |
3586 WINEDDCAPS2_WIDESURFACES |
3587 WINEDDCAPS2_CANRENDERWINDOWED;
3588 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
3589 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
3590 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
3591 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
3592 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
3593 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
3594 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
3595 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
3596 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
3598 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
3599 WINEDDSCAPS_BACKBUFFER |
3601 WINEDDSCAPS_FRONTBUFFER |
3602 WINEDDSCAPS_OFFSCREENPLAIN |
3603 WINEDDSCAPS_PALETTE |
3604 WINEDDSCAPS_PRIMARYSURFACE |
3605 WINEDDSCAPS_SYSTEMMEMORY |
3606 WINEDDSCAPS_VIDEOMEMORY |
3607 WINEDDSCAPS_VISIBLE;
3608 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
3610 /* Set D3D caps if OpenGL is available. */
3611 if(Adapters[Adapter].opengl) {
3612 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
3613 WINEDDSCAPS_MIPMAP |
3614 WINEDDSCAPS_TEXTURE |
3615 WINEDDSCAPS_ZBUFFER;
3616 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
3622 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
3623 and fields being inserted in the middle, a new structure is used in place */
3624 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
3625 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
3628 IWineD3DDeviceImpl *object = NULL;
3629 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3630 WINED3DDISPLAYMODE mode;
3631 const struct fragment_pipeline *frag_pipeline = NULL;
3633 struct fragment_caps ffp_caps;
3635 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
3636 * number and create a device without a 3D adapter for 2D only operation.
3638 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
3639 return WINED3DERR_INVALIDCALL;
3642 /* Create a WineD3DDevice object */
3643 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
3644 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
3645 TRACE("Created WineD3DDevice object @ %p\n", object);
3646 if (NULL == object) {
3647 return WINED3DERR_OUTOFVIDEOMEMORY;
3650 /* Set up initial COM information */
3651 object->lpVtbl = &IWineD3DDevice_Vtbl;
3653 object->wineD3D = iface;
3654 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
3655 IWineD3D_AddRef(object->wineD3D);
3656 object->parent = parent;
3657 list_init(&object->resources);
3658 list_init(&object->shaders);
3660 if(This->dxVersion == 7) {
3661 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
3663 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
3665 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
3667 /* Set the state up as invalid until the device is fully created */
3668 object->state = WINED3DERR_DRIVERINTERNALERROR;
3670 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
3671 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
3673 /* Save the creation parameters */
3674 object->createParms.AdapterOrdinal = Adapter;
3675 object->createParms.DeviceType = DeviceType;
3676 object->createParms.hFocusWindow = hFocusWindow;
3677 object->createParms.BehaviorFlags = BehaviourFlags;
3679 /* Initialize other useful values */
3680 object->adapterNo = Adapter;
3681 object->devType = DeviceType;
3683 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
3684 object->shader_backend = select_shader_backend(Adapter, DeviceType);
3686 memset(&ffp_caps, 0, sizeof(ffp_caps));
3687 frag_pipeline = select_fragment_implementation(Adapter, DeviceType);
3688 object->frag_pipe = frag_pipeline;
3689 frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &ffp_caps);
3690 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
3691 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
3692 compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
3693 ffp_vertexstate_template, frag_pipeline, misc_state_template);
3695 object->blitter = select_blit_implementation(Adapter, DeviceType);
3697 /* Prefer the vtable with functions optimized for single dirtifyable objects if the shader
3698 * model can deal with that. It is essentially the same, just with adjusted
3699 * Set*ShaderConstantF implementations
3701 if(object->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) object)) {
3702 object->lpVtbl = &IWineD3DDevice_DirtyConst_Vtbl;
3705 /* set the state of the device to valid */
3706 object->state = WINED3D_OK;
3708 /* Get the initial screen setup for ddraw */
3709 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
3711 object->ddraw_width = mode.Width;
3712 object->ddraw_height = mode.Height;
3713 object->ddraw_format = mode.Format;
3715 for(i = 0; i < PATCHMAP_SIZE; i++) {
3716 list_init(&object->patches[i]);
3720 #undef GLINFO_LOCATION
3722 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
3723 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3724 IUnknown_AddRef(This->parent);
3725 *pParent = This->parent;
3729 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
3730 IUnknown* surfaceParent;
3731 TRACE("(%p) call back\n", pSurface);
3733 /* Now, release the parent, which will take care of cleaning up the surface for us */
3734 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
3735 IUnknown_Release(surfaceParent);
3736 return IUnknown_Release(surfaceParent);
3739 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
3740 IUnknown* volumeParent;
3741 TRACE("(%p) call back\n", pVolume);
3743 /* Now, release the parent, which will take care of cleaning up the volume for us */
3744 IWineD3DVolume_GetParent(pVolume, &volumeParent);
3745 IUnknown_Release(volumeParent);
3746 return IUnknown_Release(volumeParent);
3749 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
3750 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
3751 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
3752 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
3754 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
3755 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
3756 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
3757 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
3758 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
3759 * the chance that other implementations support them is rather small since Win32 QuickTime uses
3760 * DirectDraw, not OpenGL.
3762 if(gl_info->supported[APPLE_FENCE] &&
3763 gl_info->supported[APPLE_CLIENT_STORAGE] &&
3764 gl_info->supported[APPLE_FLUSH_RENDER] &&
3765 gl_info->supported[APPLE_YCBCR_422]) {
3766 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
3767 TRACE_(d3d_caps)("Activating MacOS fixups\n");
3770 TRACE_(d3d_caps)("Apple extensions are not supported\n");
3771 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
3776 #define GLINFO_LOCATION (*gl_info)
3777 static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
3778 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
3779 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
3780 * all the texture. This function detects this bug by its symptom and disables PBOs
3781 * if the test fails.
3783 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
3784 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
3785 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
3786 * read back is compared to the original. If they are equal PBOs are assumed to work,
3787 * otherwise the PBO extension is disabled.
3789 GLuint texture, pbo;
3790 static const unsigned int pattern[] = {
3791 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
3792 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
3793 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
3794 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
3796 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
3798 if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
3799 /* No PBO -> No point in testing them */
3803 while(glGetError());
3804 glGenTextures(1, &texture);
3805 glBindTexture(GL_TEXTURE_2D, texture);
3806 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
3807 checkGLcall("Specifying the PBO test texture\n");
3809 GL_EXTCALL(glGenBuffersARB(1, &pbo));
3810 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
3811 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
3812 checkGLcall("Specifying the PBO test pbo\n");
3814 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3815 checkGLcall("Loading the PBO test texture\n");
3817 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
3818 glFinish(); /* just to be sure */
3820 memset(check, 0, sizeof(check));
3821 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
3822 checkGLcall("Reading back the PBO test texture\n");
3824 glDeleteTextures(1, &texture);
3825 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
3826 checkGLcall("PBO test cleanup\n");
3828 if(memcmp(check, pattern, sizeof(check)) != 0) {
3829 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
3830 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
3831 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
3833 TRACE_(d3d_caps)("PBO test successful\n");
3836 #undef GLINFO_LOCATION
3838 /* Certain applications(Steam) complain if we report an outdated driver version. In general,
3839 * reporting a driver version is moot because we are not the Windows driver, and we have different
3840 * bugs, features, etc.
3842 * If a card is not found in this table, the gl driver version is reported
3844 struct driver_version_information {
3845 WORD vendor; /* reported PCI card vendor ID */
3846 WORD card; /* reported PCI card device ID */
3847 WORD hipart_hi, hipart_lo; /* driver hiword to report */
3848 WORD lopart_hi, lopart_lo; /* driver loword to report */
3851 static const struct driver_version_information driver_version_table[] = {
3852 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (177.x)*/
3853 /* GeforceFX support is up to 173.x, Geforce2MX/3/4 up to 96.x, TNT/Geforce1/2 up to 71.x */
3854 /* Note that version numbers >100 lets say 123.45 use >= x.y.11.2345 and not x.y.10.12345 */
3855 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 11, 7341 },
3856 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 11, 7341 },
3857 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 11, 7341 },
3858 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 11, 7341 },
3859 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 11, 7341 },
3860 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 11, 7341 },
3861 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 11, 7341 },
3862 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 11, 7341 },
3863 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 11, 7341 },
3864 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 11, 7341 },
3865 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 11, 7341 },
3866 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 11, 7341 },
3867 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 11, 7341 },
3868 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 11, 7341 },
3869 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, 7, 15, 11, 7341 },
3870 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, 7, 15, 11, 7341 },
3871 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, 7, 15, 11, 7341 },
3873 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
3874 {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 },
3875 {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 },
3876 {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 },
3877 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 },
3878 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 },
3879 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 },
3881 /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */
3884 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
3886 BOOL apple = implementation_is_apple(gl_info);
3889 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
3890 * used it falls back to software. While the compiler can detect if the shader uses all declared
3891 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
3892 * using relative addressing falls back to software.
3894 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
3896 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
3897 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
3899 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
3900 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
3901 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
3904 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
3905 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
3906 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
3907 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
3908 * according to the spec.
3910 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
3911 * makes the shader slower and eats instruction slots which should be available to the d3d app.
3913 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
3914 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
3915 * this workaround is activated on cards that do not need it, it won't break things, just affect
3916 * performance negatively.
3918 if(gl_info->gl_vendor == VENDOR_INTEL ||
3919 (gl_info->gl_vendor == VENDOR_ATI && gl_info->gl_card != CARD_ATI_RADEON_X1600)) {
3920 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
3921 gl_info->set_texcoord_w = TRUE;
3925 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
3926 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
3927 * If real NP2 textures are used, the driver falls back to software. We could just remove the
3928 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
3929 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
3930 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
3931 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
3933 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
3934 * has this extension promoted to core. The extension loading code sets this extension supported
3935 * due to that, so this code works on fglrx as well.
3937 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
3938 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
3939 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
3940 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
3941 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
3942 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3943 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
3947 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
3948 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
3949 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
3950 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
3951 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
3952 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
3954 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
3955 * triggering the software fallback. There is not much we can do here apart from disabling the
3956 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
3957 * in IWineD3DImpl_FillGLCaps).
3958 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
3959 * post-processing effects in the game "Max Payne 2").
3960 * The behaviour can be verified through a simple test app attached in bugreport #14724.
3962 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_NVIDIA) {
3963 if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
3964 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
3965 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3966 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
3970 /* Find out if PBOs work as they are supposed to */
3971 test_pbo_functionality(gl_info);
3973 /* Fixup the driver version */
3974 for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
3975 if(gl_info->gl_vendor == driver_version_table[i].vendor &&
3976 gl_info->gl_card == driver_version_table[i].card) {
3977 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
3979 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
3980 driver_version_table[i].lopart_lo);
3981 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
3982 driver_version_table[i].hipart_lo);
3988 static void WINE_GLAPI invalid_func(void *data) {
3989 ERR("Invalid vertex attribute function called\n");
3993 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, void * data) {
3994 ERR("Invalid texcoord function called\n");
3998 #define GLINFO_LOCATION (Adapters[0].gl_info)
4000 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4001 * the extension detection and are used in drawStridedSlow
4003 static void WINE_GLAPI position_d3dcolor(void *data) {
4004 DWORD pos = *((DWORD *) data);
4006 FIXME("Add a test for fixed function position from d3dcolor type\n");
4007 glVertex4s(D3DCOLOR_B_R(pos),
4012 static void WINE_GLAPI position_float4(void *data) {
4013 GLfloat *pos = (float *) data;
4015 if (pos[3] < eps && pos[3] > -eps)
4018 float w = 1.0 / pos[3];
4020 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4024 static void WINE_GLAPI diffuse_d3dcolor(void *data) {
4025 DWORD diffuseColor = *((DWORD *) data);
4027 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4028 D3DCOLOR_B_G(diffuseColor),
4029 D3DCOLOR_B_B(diffuseColor),
4030 D3DCOLOR_B_A(diffuseColor));
4033 static void WINE_GLAPI specular_d3dcolor(void *data) {
4034 DWORD specularColor = *((DWORD *) data);
4036 GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
4037 D3DCOLOR_B_G(specularColor),
4038 D3DCOLOR_B_B(specularColor));
4040 static void WINE_GLAPI warn_no_specular_func(void *data) {
4041 WARN("GL_EXT_secondary_color not supported\n");
4044 void fillGLAttribFuncs(WineD3D_GL_Info *gl_info) {
4045 position_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4046 position_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4047 position_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glVertex3fv;
4048 position_funcs[WINED3DDECLTYPE_FLOAT4] = position_float4;
4049 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = position_d3dcolor;
4050 position_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4051 position_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4052 position_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glVertex2sv;
4053 position_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4054 position_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4055 position_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4056 position_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4057 position_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4058 position_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4059 position_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4060 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4061 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4063 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4064 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4065 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glColor3fv;
4066 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glColor4fv;
4067 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = diffuse_d3dcolor;
4068 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4069 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4070 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4071 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (glAttribFunc)glColor4ubv;
4072 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4073 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (glAttribFunc)glColor4sv;
4074 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4075 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (glAttribFunc)glColor4usv;
4076 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4077 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4078 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4079 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4081 /* No 4 component entry points here */
4082 specular_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4083 specular_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4084 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4085 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4087 specular_funcs[WINED3DDECLTYPE_FLOAT3] = warn_no_specular_func;
4089 specular_funcs[WINED3DDECLTYPE_FLOAT4] = invalid_func;
4090 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4091 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = specular_d3dcolor;
4093 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = warn_no_specular_func;
4095 specular_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4096 specular_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4097 specular_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4098 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4099 specular_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4100 specular_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4101 specular_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4102 specular_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4103 specular_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4104 specular_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4105 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4106 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4108 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4109 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4111 normal_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4112 normal_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4113 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glNormal3fv;
4114 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4115 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
4116 normal_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4117 normal_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4118 normal_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4119 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4120 normal_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4121 normal_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4122 normal_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4123 normal_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4124 normal_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4125 normal_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4126 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4127 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4129 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4130 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4131 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4132 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4133 multi_texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_texcoord_func;
4134 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_texcoord_func;
4135 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4136 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4137 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_texcoord_func;
4138 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_texcoord_func;
4139 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_texcoord_func;
4140 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_texcoord_func;
4141 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_texcoord_func;
4142 multi_texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_texcoord_func;
4143 multi_texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_texcoord_func;
4144 if (GL_SUPPORT(NV_HALF_FLOAT))
4146 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4147 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4149 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_texcoord_func;
4150 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_texcoord_func;
4153 texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glAttribFunc)glTexCoord1fv;
4154 texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glAttribFunc)glTexCoord2fv;
4155 texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glTexCoord3fv;
4156 texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glTexCoord4fv;
4157 texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
4158 texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4159 texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glAttribFunc)glTexCoord2sv;
4160 texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glTexCoord4sv;
4161 texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4162 texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4163 texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4164 texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4165 texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4166 texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4167 texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4168 if (GL_SUPPORT(NV_HALF_FLOAT))
4170 texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glAttribFunc)GL_EXTCALL(glTexCoord2hvNV);
4171 texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glAttribFunc)GL_EXTCALL(glTexCoord4hvNV);
4173 texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4174 texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4178 #define PUSH1(att) attribs[nAttribs++] = (att);
4179 BOOL InitAdapters(void) {
4180 static HMODULE mod_gl, mod_win32gl;
4182 int ps_selected_mode, vs_selected_mode;
4184 /* No need to hold any lock. The calling library makes sure only one thread calls
4185 * wined3d simultaneously
4187 if(numAdapters > 0) return Adapters[0].opengl;
4189 TRACE("Initializing adapters\n");
4192 #ifdef USE_WIN32_OPENGL
4193 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4194 mod_gl = LoadLibraryA("opengl32.dll");
4196 ERR("Can't load opengl32.dll!\n");
4199 mod_win32gl = mod_gl;
4201 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4202 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4203 mod_gl = GetModuleHandleA("gdi32.dll");
4204 mod_win32gl = LoadLibraryA("opengl32.dll");
4206 ERR("Can't load opengl32.dll!\n");
4212 /* Load WGL core functions from opengl32.dll */
4213 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4217 if(!pwglGetProcAddress) {
4218 ERR("Unable to load wglGetProcAddress!\n");
4222 /* Dynamically load all GL core functions */
4226 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4227 * otherwise because we have to use winex11.drv's override
4229 glFinish = (void*)GetProcAddress(mod_win32gl, "glFinish");
4230 glFlush = (void*)GetProcAddress(mod_win32gl, "glFlush");
4232 /* For now only one default adapter */
4240 WineD3D_PixelFormat *cfgs;
4242 DISPLAY_DEVICEW DisplayDevice;
4245 TRACE("Initializing default adapter\n");
4246 Adapters[0].num = 0;
4247 Adapters[0].monitorPoint.x = -1;
4248 Adapters[0].monitorPoint.y = -1;
4250 if (!WineD3D_CreateFakeGLContext()) {
4251 ERR("Failed to get a gl context for default adapter\n");
4252 WineD3D_ReleaseFakeGLContext();
4256 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
4258 ERR("Failed to initialize gl caps for default adapter\n");
4259 WineD3D_ReleaseFakeGLContext();
4262 ret = initPixelFormats(&Adapters[0].gl_info);
4264 ERR("Failed to init gl formats\n");
4265 WineD3D_ReleaseFakeGLContext();
4269 hdc = pwglGetCurrentDC();
4271 ERR("Failed to get gl HDC\n");
4272 WineD3D_ReleaseFakeGLContext();
4276 Adapters[0].driver = "Display";
4277 Adapters[0].description = "Direct3D HAL";
4279 /* Use the VideoRamSize registry setting when set */
4280 if(wined3d_settings.emulated_textureram)
4281 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4283 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
4284 Adapters[0].UsedTextureRam = 0;
4285 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
4287 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4288 DisplayDevice.cb = sizeof(DisplayDevice);
4289 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4290 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4291 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
4293 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4294 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
4296 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
4297 cfgs = Adapters[0].cfgs;
4298 PUSH1(WGL_RED_BITS_ARB)
4299 PUSH1(WGL_GREEN_BITS_ARB)
4300 PUSH1(WGL_BLUE_BITS_ARB)
4301 PUSH1(WGL_ALPHA_BITS_ARB)
4302 PUSH1(WGL_DEPTH_BITS_ARB)
4303 PUSH1(WGL_STENCIL_BITS_ARB)
4304 PUSH1(WGL_DRAW_TO_WINDOW_ARB)
4305 PUSH1(WGL_PIXEL_TYPE_ARB)
4306 PUSH1(WGL_DOUBLE_BUFFER_ARB)
4307 PUSH1(WGL_AUX_BUFFERS_ARB)
4309 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
4310 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4315 /* Cache the pixel format */
4316 cfgs->iPixelFormat = iPixelFormat;
4317 cfgs->redSize = values[0];
4318 cfgs->greenSize = values[1];
4319 cfgs->blueSize = values[2];
4320 cfgs->alphaSize = values[3];
4321 cfgs->depthSize = values[4];
4322 cfgs->stencilSize = values[5];
4323 cfgs->windowDrawable = values[6];
4324 cfgs->iPixelType = values[7];
4325 cfgs->doubleBuffer = values[8];
4326 cfgs->auxBuffers = values[9];
4328 cfgs->pbufferDrawable = FALSE;
4329 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4330 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4331 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4333 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4334 cfgs->pbufferDrawable = value;
4337 cfgs->numSamples = 0;
4338 /* Check multisample support */
4339 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4340 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4342 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4343 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4344 * value[1] = number of multi sample buffers*/
4346 cfgs->numSamples = value[1];
4350 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);
4354 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4355 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4356 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4357 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4358 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4359 * driver is allowed to consume more bits EXCEPT for stencil bits.
4361 * Mark an adapter with this broken stencil behavior.
4363 Adapters[0].brokenStencil = TRUE;
4364 for(i=0, cfgs=Adapters[0].cfgs; i<Adapters[0].nCfgs; i++) {
4365 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4366 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4367 Adapters[0].brokenStencil = FALSE;
4372 fixup_extensions(&Adapters[0].gl_info);
4374 WineD3D_ReleaseFakeGLContext();
4376 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4377 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
4378 fillGLAttribFuncs(&Adapters[0].gl_info);
4379 init_type_lookup(&Adapters[0].gl_info);
4380 Adapters[0].opengl = TRUE;
4383 TRACE("%d adapters successfully initialized\n", numAdapters);
4388 /* Initialize an adapter for ddraw-only memory counting */
4389 memset(Adapters, 0, sizeof(Adapters));
4390 Adapters[0].num = 0;
4391 Adapters[0].opengl = FALSE;
4392 Adapters[0].monitorPoint.x = -1;
4393 Adapters[0].monitorPoint.y = -1;
4395 Adapters[0].driver = "Display";
4396 Adapters[0].description = "WineD3D DirectDraw Emulation";
4397 if(wined3d_settings.emulated_textureram) {
4398 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4400 Adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4407 #undef GLINFO_LOCATION
4409 /**********************************************************
4410 * IWineD3D VTbl follows
4411 **********************************************************/
4413 const IWineD3DVtbl IWineD3D_Vtbl =
4416 IWineD3DImpl_QueryInterface,
4417 IWineD3DImpl_AddRef,
4418 IWineD3DImpl_Release,
4420 IWineD3DImpl_GetParent,
4421 IWineD3DImpl_GetAdapterCount,
4422 IWineD3DImpl_RegisterSoftwareDevice,
4423 IWineD3DImpl_GetAdapterMonitor,
4424 IWineD3DImpl_GetAdapterModeCount,
4425 IWineD3DImpl_EnumAdapterModes,
4426 IWineD3DImpl_GetAdapterDisplayMode,
4427 IWineD3DImpl_GetAdapterIdentifier,
4428 IWineD3DImpl_CheckDeviceMultiSampleType,
4429 IWineD3DImpl_CheckDepthStencilMatch,
4430 IWineD3DImpl_CheckDeviceType,
4431 IWineD3DImpl_CheckDeviceFormat,
4432 IWineD3DImpl_CheckDeviceFormatConversion,
4433 IWineD3DImpl_GetDeviceCaps,
4434 IWineD3DImpl_CreateDevice