2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 /* Compile time diagnostics: */
27 #ifndef DEBUG_SINGLE_MODE
28 /* Set to 1 to force only a single display mode to be exposed: */
29 #define DEBUG_SINGLE_MODE 0
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 #define GLINFO_LOCATION (*gl_info)
41 /* The d3d device ID */
42 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
44 /* Extension detection */
46 const char *extension_string;
47 GL_SupportedExt extension;
51 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
52 {"GL_APPLE_fence", APPLE_FENCE, 0 },
53 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
54 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
55 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
58 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
59 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
60 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
61 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
62 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
65 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
66 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
67 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
68 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
69 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
70 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
71 {"GL_ARB_imaging", ARB_IMAGING, 0 },
72 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
73 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
74 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
75 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
76 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
77 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
78 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
79 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
80 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
81 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
82 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
83 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
84 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
85 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
86 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
87 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
88 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
89 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
90 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
91 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
92 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
93 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
94 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
95 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
98 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
99 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
100 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
101 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
102 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
103 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
104 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
105 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
106 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
107 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
108 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
109 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
110 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
111 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
112 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
113 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
114 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
115 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
116 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
117 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
118 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
119 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
120 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
121 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
122 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
123 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
124 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
127 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
128 {"GL_NV_fence", NV_FENCE, 0 },
129 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
130 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
131 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
132 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
133 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
134 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
135 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
136 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
137 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
138 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
139 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
140 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
141 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
142 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
143 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
144 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
145 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
148 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
151 /**********************************************************
152 * Utility functions follow
153 **********************************************************/
155 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
156 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
157 WINED3DDEVTYPE DeviceType);
158 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
159 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
162 const int minLookup[MAX_LOOKUPS] =
164 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
167 const int maxLookup[MAX_LOOKUPS] =
169 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
172 DWORD *stateLookup[MAX_LOOKUPS];
174 struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
175 const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
177 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
178 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
179 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
180 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
183 GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
184 const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
186 GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
189 /* drawStridedSlow attributes */
190 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
191 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
192 glAttribFunc specular_func_3ubv;
193 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
194 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
195 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
198 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
199 * i.e., there is no GL Context - Get a default rendering context to enable the
200 * function query some info from GL.
203 static int wined3d_fake_gl_context_ref = 0;
204 static BOOL wined3d_fake_gl_context_foreign;
205 static BOOL wined3d_fake_gl_context_available = FALSE;
206 static HDC wined3d_fake_gl_context_hdc = NULL;
207 static HWND wined3d_fake_gl_context_hwnd = NULL;
209 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
210 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
212 0, 0, &wined3d_fake_gl_context_cs,
213 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
214 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
215 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
217 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
219 static void WineD3D_ReleaseFakeGLContext(void) {
222 EnterCriticalSection(&wined3d_fake_gl_context_cs);
224 if(!wined3d_fake_gl_context_available) {
225 TRACE_(d3d_caps)("context not available\n");
226 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
230 glCtx = pwglGetCurrentContext();
232 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
233 if (0 == (--wined3d_fake_gl_context_ref) ) {
234 if(!wined3d_fake_gl_context_foreign && glCtx) {
235 TRACE_(d3d_caps)("destroying fake GL context\n");
236 pwglMakeCurrent(NULL, NULL);
237 pwglDeleteContext(glCtx);
239 if(wined3d_fake_gl_context_hdc)
240 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
241 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
242 if(wined3d_fake_gl_context_hwnd)
243 DestroyWindow(wined3d_fake_gl_context_hwnd);
244 wined3d_fake_gl_context_hwnd = NULL;
245 wined3d_fake_gl_context_available = FALSE;
247 assert(wined3d_fake_gl_context_ref >= 0);
249 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
252 static BOOL WineD3D_CreateFakeGLContext(void) {
255 EnterCriticalSection(&wined3d_fake_gl_context_cs);
257 TRACE("getting context...\n");
258 if(wined3d_fake_gl_context_ref > 0) goto ret;
259 assert(0 == wined3d_fake_gl_context_ref);
261 wined3d_fake_gl_context_foreign = TRUE;
263 glCtx = pwglGetCurrentContext();
265 PIXELFORMATDESCRIPTOR pfd;
268 wined3d_fake_gl_context_foreign = FALSE;
270 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
271 wined3d_fake_gl_context_hwnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
272 if(!wined3d_fake_gl_context_hwnd) {
273 ERR("HWND creation failed!\n");
276 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
277 if(!wined3d_fake_gl_context_hdc) {
278 ERR("GetDC failed!\n");
282 /* PixelFormat selection */
283 ZeroMemory(&pfd, sizeof(pfd));
284 pfd.nSize = sizeof(pfd);
286 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
287 pfd.iPixelType = PFD_TYPE_RGBA;
289 pfd.iLayerType = PFD_MAIN_PLANE;
291 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
293 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
294 ERR("Can't find a suitable iPixelFormat\n");
297 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
298 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
300 /* Create a GL context */
301 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
303 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
307 /* Make it the current GL context */
308 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
309 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
315 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
316 wined3d_fake_gl_context_ref++;
317 wined3d_fake_gl_context_available = TRUE;
318 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
321 if(wined3d_fake_gl_context_hdc)
322 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
323 wined3d_fake_gl_context_hdc = NULL;
324 if(wined3d_fake_gl_context_hwnd)
325 DestroyWindow(wined3d_fake_gl_context_hwnd);
326 wined3d_fake_gl_context_hwnd = NULL;
327 if(glCtx) pwglDeleteContext(glCtx);
328 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
332 /* Adjust the amount of used texture memory */
333 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
334 struct WineD3DAdapter *adapter = D3DDevice->adapter;
336 adapter->UsedTextureRam += glram;
337 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
338 return adapter->UsedTextureRam;
341 /**********************************************************
342 * IUnknown parts follows
343 **********************************************************/
345 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
349 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
350 if (IsEqualGUID(riid, &IID_IUnknown)
351 || IsEqualGUID(riid, &IID_IWineD3DBase)
352 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
353 IUnknown_AddRef(iface);
358 return E_NOINTERFACE;
361 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
362 IWineD3DImpl *This = (IWineD3DImpl *)iface;
363 ULONG refCount = InterlockedIncrement(&This->ref);
365 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
369 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
370 IWineD3DImpl *This = (IWineD3DImpl *)iface;
372 TRACE("(%p) : Releasing from %d\n", This, This->ref);
373 ref = InterlockedDecrement(&This->ref);
377 for (i = 0; i < This->adapter_count; ++i)
379 HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
381 HeapFree(GetProcessHeap(), 0, This);
387 /* Set the shader type for this device, depending on the given capabilities,
388 * the device type, and the user preferences in wined3d_settings */
390 static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
392 if (wined3d_settings.vs_mode == VS_NONE) {
393 *vs_selected = SHADER_NONE;
394 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
395 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
396 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
397 * shaders only on this card. */
398 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
399 *vs_selected = SHADER_ARB;
401 *vs_selected = SHADER_GLSL;
402 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
403 *vs_selected = SHADER_ARB;
405 *vs_selected = SHADER_NONE;
408 if (wined3d_settings.ps_mode == PS_NONE) {
409 *ps_selected = SHADER_NONE;
410 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
411 *ps_selected = SHADER_GLSL;
412 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
413 *ps_selected = SHADER_ARB;
414 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
415 *ps_selected = SHADER_ATI;
417 *ps_selected = SHADER_NONE;
421 /** Select the number of report maximum shader constants based on the selected shader modes */
422 static void select_shader_max_constants(
423 int ps_selected_mode,
424 int vs_selected_mode,
425 WineD3D_GL_Info *gl_info) {
427 switch (vs_selected_mode) {
429 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
432 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
435 gl_info->max_vshader_constantsF = 0;
439 switch (ps_selected_mode) {
441 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
444 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
447 gl_info->max_pshader_constantsF = 0;
452 /**********************************************************
453 * IWineD3D parts follows
454 **********************************************************/
456 /* GL locking is done by the caller */
457 static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info)
461 const char *testcode =
463 "PARAM C[66] = { program.env[0..65] };\n"
465 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
466 "ARL A0.x, zero.x;\n"
467 "MOV result.position, C[A0.x + 65];\n"
471 GL_EXTCALL(glGenProgramsARB(1, &prog));
473 ERR("Failed to create an ARB offset limit test program\n");
475 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
476 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
477 strlen(testcode), testcode));
478 if(glGetError() != 0) {
479 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
480 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
482 } else TRACE("OpenGL implementation allows offsets > 63\n");
484 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
485 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
486 checkGLcall("ARB vp offset limit test cleanup\n");
491 static DWORD ver_for_ext(GL_SupportedExt ext)
494 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
495 if(EXTENSION_MAP[i].extension == ext) {
496 return EXTENSION_MAP[i].version;
502 static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
503 const char *GL_Extensions = NULL;
504 const char *WGL_Extensions = NULL;
505 const char *gl_string = NULL;
506 const char *gl_string_cursor = NULL;
508 GLfloat gl_floatv[2];
509 int major = 1, minor = 0;
510 BOOL return_value = TRUE;
513 unsigned int vidmem=0;
515 TRACE_(d3d_caps)("(%p)\n", gl_info);
519 gl_string = (const char *) glGetString(GL_RENDERER);
520 if (!gl_string) gl_string = "None";
521 strcpy(gl_info->gl_renderer, gl_string);
523 gl_string = (const char *) glGetString(GL_VENDOR);
524 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
525 if (gl_string != NULL) {
526 /* Fill in the GL vendor */
527 if (strstr(gl_string, "NVIDIA")) {
528 gl_info->gl_vendor = VENDOR_NVIDIA;
529 } else if (strstr(gl_string, "ATI")) {
530 gl_info->gl_vendor = VENDOR_ATI;
531 } else if (strstr(gl_string, "Intel(R)") ||
532 strstr(gl_info->gl_renderer, "Intel(R)") ||
533 strstr(gl_string, "Intel Inc.")) {
534 gl_info->gl_vendor = VENDOR_INTEL;
535 } else if (strstr(gl_string, "Mesa")) {
536 gl_info->gl_vendor = VENDOR_MESA;
538 gl_info->gl_vendor = VENDOR_WINE;
541 gl_info->gl_vendor = VENDOR_WINE;
545 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
547 /* Parse the GL_VERSION field into major and minor information */
548 gl_string = (const char *) glGetString(GL_VERSION);
549 if (gl_string != NULL) {
551 /* First, parse the generic opengl version. This is supposed not to be convoluted with
552 * driver specific information
554 gl_string_cursor = gl_string;
555 major = atoi(gl_string_cursor);
557 ERR("Invalid opengl major version: %d\n", major);
559 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
562 if (*gl_string_cursor++ != '.') {
563 ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
565 minor = atoi(gl_string_cursor);
566 TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
567 gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
569 /* Now parse the driver specific string which we'll report to the app */
570 switch (gl_info->gl_vendor) {
572 gl_string_cursor = strstr(gl_string, "NVIDIA");
573 if (!gl_string_cursor) {
574 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
578 gl_string_cursor = strstr(gl_string_cursor, " ");
579 if (!gl_string_cursor) {
580 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
584 while (*gl_string_cursor == ' ') {
588 if (!*gl_string_cursor) {
589 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
593 major = atoi(gl_string_cursor);
594 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
598 if (*gl_string_cursor++ != '.') {
599 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
603 minor = atoi(gl_string_cursor);
604 minor = major*100+minor;
611 gl_string_cursor = strchr(gl_string, '-');
612 if (gl_string_cursor) {
616 /* Check if version number is of the form x.y.z */
617 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
619 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
621 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
623 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
626 /* Mark version number as malformed */
628 gl_string_cursor = 0;
631 if (!gl_string_cursor)
632 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
634 major = *gl_string_cursor - '0';
635 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
640 /* Apple and Mesa version strings look differently, but both provide intel drivers */
641 if(strstr(gl_string, "APPLE")) {
642 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
643 * We only need the first part, and use the APPLE as identification
646 gl_string_cursor = gl_string;
647 major = atoi(gl_string_cursor);
648 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
652 if (*gl_string_cursor++ != '.') {
653 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
657 minor = atoi(gl_string_cursor);
662 gl_string_cursor = strstr(gl_string, "Mesa");
663 gl_string_cursor = strstr(gl_string_cursor, " ");
664 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
665 if (*gl_string_cursor) {
669 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
670 tmp[cursor++] = *gl_string_cursor;
676 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
680 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
681 tmp[cursor++] = *gl_string_cursor;
693 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
694 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
695 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
696 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
698 FIXME("OpenGL driver did not return version information\n");
699 gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
700 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
703 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
706 * Initialize openGL extension related variables
707 * with Default values
709 memset(gl_info->supported, 0, sizeof(gl_info->supported));
710 gl_info->max_buffers = 1;
711 gl_info->max_textures = 1;
712 gl_info->max_texture_stages = 1;
713 gl_info->max_fragment_samplers = 1;
714 gl_info->max_vertex_samplers = 0;
715 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
716 gl_info->max_sampler_stages = 1;
717 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
718 gl_info->ps_arb_max_temps = 0;
719 gl_info->ps_arb_max_instructions = 0;
720 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
721 gl_info->vs_arb_max_temps = 0;
722 gl_info->vs_arb_max_instructions = 0;
723 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
724 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
725 gl_info->vs_glsl_constantsF = 0;
726 gl_info->ps_glsl_constantsF = 0;
727 gl_info->vs_arb_constantsF = 0;
728 gl_info->ps_arb_constantsF = 0;
730 /* Retrieve opengl defaults */
731 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
732 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
733 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
735 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
736 gl_info->max_lights = gl_max;
737 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
739 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
740 gl_info->max_texture_size = gl_max;
741 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
743 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
744 gl_info->max_pointsizemin = gl_floatv[0];
745 gl_info->max_pointsize = gl_floatv[1];
746 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
748 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
749 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
750 TRACE_(d3d_caps)("GL_Extensions reported:\n");
752 if (NULL == GL_Extensions) {
753 ERR(" GL_Extensions returns NULL\n");
755 while (*GL_Extensions != 0x00) {
760 while (isspace(*GL_Extensions)) GL_Extensions++;
761 Start = GL_Extensions;
762 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
766 len = GL_Extensions - Start;
767 if (len == 0 || len >= sizeof(ThisExtn))
770 memcpy(ThisExtn, Start, len);
771 ThisExtn[len] = '\0';
772 TRACE_(d3d_caps)("- %s\n", ThisExtn);
774 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
775 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
776 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
777 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
785 /* Now work out what GL support this card really has */
786 #define USE_GL_FUNC(type, pfn, ext, replace) { \
787 DWORD ver = ver_for_ext(ext); \
788 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
789 else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
790 else gl_info->pfn = NULL; \
795 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
800 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
801 * loading the functions, otherwise the code above will load the extension entry points instead of the
802 * core functions, which may not work
804 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
805 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
806 EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
807 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
808 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
812 if (gl_info->supported[APPLE_FENCE]) {
813 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
814 * The apple extension interacts with some other apple exts. Disable the NV
815 * extension if the apple one is support to prevent confusion in other parts
818 gl_info->supported[NV_FENCE] = FALSE;
820 if (gl_info->supported[APPLE_FLOAT_PIXELS]) {
821 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
823 * The enums are the same:
824 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
825 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
826 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
827 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
828 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
830 if(!gl_info->supported[ARB_TEXTURE_FLOAT]) {
831 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n");
832 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
834 if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) {
835 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n");
836 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
839 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
840 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
841 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
843 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
844 if(gl_info->supported[NV_REGISTER_COMBINERS]) {
845 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
846 * are supported. The nv extensions provide the same functionality as the
847 * ATI one, and a bit more(signed pixelformats)
849 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
852 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
853 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
854 gl_info->max_buffers = gl_max;
855 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
857 if (gl_info->supported[ARB_MULTITEXTURE]) {
858 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
859 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
860 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
862 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
864 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
865 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
867 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
869 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
871 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
873 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
874 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
876 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
878 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
880 if (gl_info->supported[ARB_VERTEX_SHADER]) {
882 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
883 gl_info->max_vertex_samplers = tmp;
884 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
885 gl_info->max_combined_samplers = tmp;
887 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
888 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
889 * an issue because then the sampler setup only depends on the two shaders. If a pixel
890 * shader is used with fixed function vertex processing we're fine too because fixed function
891 * vertex processing doesn't use any samplers. If fixed function fragment processing is
892 * used we have to make sure that all vertex sampler setups are valid together with all
893 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
894 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
895 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
896 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
897 * a fixed function pipeline anymore.
899 * So this is just a check to check that our assumption holds true. If not, write a warning
900 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
902 if(gl_info->max_vertex_samplers &&
903 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
904 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
905 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
906 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
907 if( gl_info->max_combined_samplers > MAX_TEXTURES )
908 gl_info->max_vertex_samplers =
909 gl_info->max_combined_samplers - MAX_TEXTURES;
911 gl_info->max_vertex_samplers = 0;
914 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
916 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
917 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
919 if (gl_info->supported[ARB_VERTEX_BLEND]) {
920 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
921 gl_info->max_blends = gl_max;
922 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
924 if (gl_info->supported[EXT_TEXTURE3D]) {
925 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
926 gl_info->max_texture3d_size = gl_max;
927 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
929 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
930 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
931 gl_info->max_anisotropy = gl_max;
932 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
934 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
935 gl_info->ps_arb_version = PS_VERSION_11;
936 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
937 gl_info->ps_arb_constantsF = gl_max;
938 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
939 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
940 gl_info->ps_arb_max_temps = gl_max;
941 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
942 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
943 gl_info->ps_arb_max_instructions = gl_max;
944 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
946 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
947 gl_info->vs_arb_version = VS_VERSION_11;
948 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
949 gl_info->vs_arb_constantsF = gl_max;
950 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
951 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
952 gl_info->vs_arb_max_temps = gl_max;
953 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
954 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
955 gl_info->vs_arb_max_instructions = gl_max;
956 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
958 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
960 if (gl_info->supported[ARB_VERTEX_SHADER]) {
961 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
962 gl_info->vs_glsl_constantsF = gl_max / 4;
963 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
965 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
966 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
967 gl_info->ps_glsl_constantsF = gl_max / 4;
968 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
969 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
970 gl_info->max_glsl_varyings = gl_max;
971 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
973 if (gl_info->supported[EXT_VERTEX_SHADER]) {
974 gl_info->vs_ati_version = VS_VERSION_11;
976 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
977 gl_info->vs_nv_version = VS_VERSION_30;
978 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
979 gl_info->vs_nv_version = VS_VERSION_20;
980 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
981 gl_info->vs_nv_version = VS_VERSION_11;
982 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
983 gl_info->vs_nv_version = VS_VERSION_10;
985 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
986 gl_info->ps_nv_version = PS_VERSION_30;
987 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
988 gl_info->ps_nv_version = PS_VERSION_20;
990 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) {
991 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
993 gl_info->max_shininess = 128.0;
995 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
996 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
997 * This saves a few redundant glDisable calls
999 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1001 if(gl_info->supported[ATI_FRAGMENT_SHADER]) {
1002 /* Disable NV_register_combiners and fragment shader if this is supported.
1003 * generally the NV extensions are preferred over the ATI ones, and this
1004 * extension is disabled if register_combiners and texture_shader2 are both
1005 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1006 * fragment processing support
1008 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1009 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1010 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1011 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1012 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1014 if(gl_info->supported[NV_HALF_FLOAT]) {
1015 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float */
1016 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
1018 if(gl_info->supported[ARB_POINT_SPRITE]) {
1019 gl_info->max_point_sprite_units = gl_info->max_textures;
1021 gl_info->max_point_sprite_units = 0;
1024 checkGLcall("extension detection\n");
1026 /* In some cases the number of texture stages can be larger than the number
1027 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1028 * shaders), but 8 texture stages (register combiners). */
1029 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1031 /* We can only use ORM_FBO when the hardware supports it. */
1032 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1033 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
1034 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
1037 /* MRTs are currently only supported when FBOs are used. */
1038 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1039 gl_info->max_buffers = 1;
1042 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
1043 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
1044 * in case of the latest videocards in the number of pixel/vertex pipelines.
1046 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
1047 * rendering. Various games use this information to get a rough estimation of the features of the card
1048 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
1049 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
1050 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
1053 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
1054 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
1055 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
1056 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
1057 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1058 * is used for rendering which is not always the case). This would work but it is not very portable. Second
1059 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1062 * As said most games only use the PCI id to get an indication of the capabilities of the card.
1063 * It doesn't really matter if the given id is the correct one if we return the id of a card with
1064 * similar 3d features.
1066 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
1067 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1068 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1069 * won't pass we return a default card. This way is better than maintaining a full card database as even
1070 * without a full database we can return a card with similar features. Second the size of the database
1071 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
1072 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
1073 * to distinguishes between different models from that family.
1075 * The code also selects a default amount of video memory which we will use for an estimation of the amount
1076 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
1077 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
1078 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
1079 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
1080 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1081 * memory behind our backs if really needed.
1082 * Note that the amount of video memory can be overruled using a registry setting.
1084 switch (gl_info->gl_vendor) {
1086 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1087 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1089 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1090 /* Geforce 200 - highend */
1091 if(strstr(gl_info->gl_renderer, "GTX 280") ||
1092 strstr(gl_info->gl_renderer, "GTX 285") ||
1093 strstr(gl_info->gl_renderer, "GTX 295"))
1095 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1098 /* Geforce 200 - midend high */
1099 if(strstr(gl_info->gl_renderer, "GTX 275")) {
1100 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX275;
1103 /* Geforce 200 - midend */
1104 if(strstr(gl_info->gl_renderer, "GTX 260")) {
1105 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX260;
1108 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1109 else if(strstr(gl_info->gl_renderer, "9800") ||
1110 strstr(gl_info->gl_renderer, "GTS 150") ||
1111 strstr(gl_info->gl_renderer, "GTS 250"))
1113 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1116 /* Geforce9 - midend */
1117 else if(strstr(gl_info->gl_renderer, "9600")) {
1118 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1119 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1121 /* Geforce9 - midend low / Geforce 200 - low*/
1122 else if(strstr(gl_info->gl_renderer, "9500") ||
1123 strstr(gl_info->gl_renderer, "GT 120") ||
1124 strstr(gl_info->gl_renderer, "GT 130"))
1126 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9500GT;
1127 vidmem = 256; /* The 9500GT has 256-1024MB */
1129 /* Geforce9 - lowend */
1130 else if(strstr(gl_info->gl_renderer, "9400")) {
1131 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9400GT;
1132 vidmem = 256; /* The 9400GT has 256-1024MB */
1134 /* Geforce9 - lowend low */
1135 else if(strstr(gl_info->gl_renderer, "9100") ||
1136 strstr(gl_info->gl_renderer, "9200") ||
1137 strstr(gl_info->gl_renderer, "9300") ||
1138 strstr(gl_info->gl_renderer, "G 100"))
1140 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9200;
1141 vidmem = 256; /* The 9100-9300 cards have 256MB */
1143 /* Geforce8 - highend */
1144 else if (strstr(gl_info->gl_renderer, "8800")) {
1145 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1146 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1148 /* Geforce8 - midend mobile */
1149 else if(strstr(gl_info->gl_renderer, "8600 M")) {
1150 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1153 /* Geforce8 - midend */
1154 else if(strstr(gl_info->gl_renderer, "8600") ||
1155 strstr(gl_info->gl_renderer, "8700"))
1157 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1160 /* Geforce8 - lowend */
1161 else if(strstr(gl_info->gl_renderer, "8300") ||
1162 strstr(gl_info->gl_renderer, "8400") ||
1163 strstr(gl_info->gl_renderer, "8500"))
1165 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1166 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1168 /* Geforce7 - highend */
1169 else if(strstr(gl_info->gl_renderer, "7800") ||
1170 strstr(gl_info->gl_renderer, "7900") ||
1171 strstr(gl_info->gl_renderer, "7950") ||
1172 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1173 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1175 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1176 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1178 /* Geforce7 midend */
1179 else if(strstr(gl_info->gl_renderer, "7600") ||
1180 strstr(gl_info->gl_renderer, "7700")) {
1181 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1182 vidmem = 256; /* The 7600 uses 256-512MB */
1183 /* Geforce7 lower medium */
1184 } else if(strstr(gl_info->gl_renderer, "7400")) {
1185 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1186 vidmem = 256; /* The 7400 uses 256-512MB */
1188 /* Geforce7 lowend */
1189 else if(strstr(gl_info->gl_renderer, "7300")) {
1190 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1191 vidmem = 256; /* Mac Pros with this card have 256 MB */
1193 /* Geforce6 highend */
1194 else if(strstr(gl_info->gl_renderer, "6800"))
1196 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1197 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1199 /* Geforce6 - midend */
1200 else if(strstr(gl_info->gl_renderer, "6600") ||
1201 strstr(gl_info->gl_renderer, "6610") ||
1202 strstr(gl_info->gl_renderer, "6700"))
1204 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1205 vidmem = 128; /* A 6600GT has 128-256MB */
1207 /* Geforce6/7 lowend */
1209 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1212 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1213 /* GeforceFX - highend */
1214 if (strstr(gl_info->gl_renderer, "5800") ||
1215 strstr(gl_info->gl_renderer, "5900") ||
1216 strstr(gl_info->gl_renderer, "5950") ||
1217 strstr(gl_info->gl_renderer, "Quadro FX"))
1219 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1220 vidmem = 256; /* 5800-5900 cards use 256MB */
1222 /* GeforceFX - midend */
1223 else if(strstr(gl_info->gl_renderer, "5600") ||
1224 strstr(gl_info->gl_renderer, "5650") ||
1225 strstr(gl_info->gl_renderer, "5700") ||
1226 strstr(gl_info->gl_renderer, "5750"))
1228 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1229 vidmem = 128; /* A 5600 uses 128-256MB */
1231 /* GeforceFX - lowend */
1233 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1234 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1236 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1237 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1238 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1239 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1242 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1243 vidmem = 64; /* Geforce3 cards have 64-128MB */
1245 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1246 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1247 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1248 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1250 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1251 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1252 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1254 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1255 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1256 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1259 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1260 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1263 if (strstr(gl_info->gl_renderer, "TNT2")) {
1264 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1265 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1268 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1269 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1274 if(WINE_D3D9_CAPABLE(gl_info)) {
1275 /* Radeon R7xx HD4800 - highend */
1276 if (strstr(gl_info->gl_renderer, "HD 4800") ||
1277 strstr(gl_info->gl_renderer, "HD 4830") ||
1278 strstr(gl_info->gl_renderer, "HD 4850") ||
1279 strstr(gl_info->gl_renderer, "HD 4870") ||
1280 strstr(gl_info->gl_renderer, "HD 4890"))
1282 gl_info->gl_card = CARD_ATI_RADEON_HD4800;
1283 vidmem = 512; /* HD4800 cards use 512-1024MB, up to 2048MB for X2 version */
1285 /* Radeon R6xx HD2900/HD3800 - highend */
1286 else if (strstr(gl_info->gl_renderer, "HD 2900") ||
1287 strstr(gl_info->gl_renderer, "HD 3870") ||
1288 strstr(gl_info->gl_renderer, "HD 3850"))
1290 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1291 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1293 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1294 else if (strstr(gl_info->gl_renderer, "HD 2600") ||
1295 strstr(gl_info->gl_renderer, "HD 3830") ||
1296 strstr(gl_info->gl_renderer, "HD 3690") ||
1297 strstr(gl_info->gl_renderer, "HD 3650"))
1299 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1300 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1302 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1303 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1304 strstr(gl_info->gl_renderer, "HD 2400") ||
1305 strstr(gl_info->gl_renderer, "HD 3470") ||
1306 strstr(gl_info->gl_renderer, "HD 3450") ||
1307 strstr(gl_info->gl_renderer, "HD 3430"))
1309 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1310 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1312 /* Radeon R6xx/R7xx integrated */
1313 else if (strstr(gl_info->gl_renderer, "HD 3100") ||
1314 strstr(gl_info->gl_renderer, "HD 3200") ||
1315 strstr(gl_info->gl_renderer, "HD 3300"))
1317 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1318 vidmem = 128; /* 128MB */
1321 else if (strstr(gl_info->gl_renderer, "X1600") ||
1322 strstr(gl_info->gl_renderer, "X1650") ||
1323 strstr(gl_info->gl_renderer, "X1800") ||
1324 strstr(gl_info->gl_renderer, "X1900") ||
1325 strstr(gl_info->gl_renderer, "X1950"))
1327 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1328 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1330 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1331 else if(strstr(gl_info->gl_renderer, "X700") ||
1332 strstr(gl_info->gl_renderer, "X800") ||
1333 strstr(gl_info->gl_renderer, "X850") ||
1334 strstr(gl_info->gl_renderer, "X1300") ||
1335 strstr(gl_info->gl_renderer, "X1400") ||
1336 strstr(gl_info->gl_renderer, "X1450") ||
1337 strstr(gl_info->gl_renderer, "X1550"))
1339 gl_info->gl_card = CARD_ATI_RADEON_X700;
1340 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1342 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1343 else if(strstr(gl_info->gl_renderer, "Radeon Xpress"))
1345 gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M;
1346 vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1350 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1351 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1353 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1354 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1355 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1356 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1357 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1358 vidmem = 32; /* There are models with up to 64MB */
1360 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1361 vidmem = 16; /* There are 16-32MB models */
1365 if (strstr(gl_info->gl_renderer, "GMA 950") ||
1366 strstr(gl_info->gl_renderer, "945GM")) {
1367 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1368 gl_info->gl_card = CARD_INTEL_I945GM;
1370 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1371 gl_info->gl_card = CARD_INTEL_I915GM;
1372 } else if (strstr(gl_info->gl_renderer, "915G")) {
1373 gl_info->gl_card = CARD_INTEL_I915G;
1374 } else if (strstr(gl_info->gl_renderer, "865G")) {
1375 gl_info->gl_card = CARD_INTEL_I865G;
1376 } else if (strstr(gl_info->gl_renderer, "855G")) {
1377 gl_info->gl_card = CARD_INTEL_I855G;
1378 } else if (strstr(gl_info->gl_renderer, "830G")) {
1379 gl_info->gl_card = CARD_INTEL_I830G;
1381 gl_info->gl_card = CARD_INTEL_I915G;
1387 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1388 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1389 * them a good generic choice.
1391 gl_info->gl_vendor = VENDOR_NVIDIA;
1392 if(WINE_D3D9_CAPABLE(gl_info))
1393 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1394 else if(WINE_D3D8_CAPABLE(gl_info))
1395 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1396 else if(WINE_D3D7_CAPABLE(gl_info))
1397 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1398 else if(WINE_D3D6_CAPABLE(gl_info))
1399 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1401 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1403 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1405 /* If we have an estimate use it, else default to 64MB; */
1407 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1409 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1411 /* Load all the lookup tables */
1412 for (i = 0; i < MAX_LOOKUPS; i++) {
1413 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1416 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1417 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1418 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1419 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1420 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1421 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1422 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1423 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1424 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1425 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1427 magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
1428 magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
1429 magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
1430 magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1431 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1434 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1435 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
1436 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
1437 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
1438 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1439 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1440 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1441 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1442 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1443 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
1444 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1445 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
1446 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1447 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
1448 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1450 /* TODO: config lookups */
1452 /* Make sure there's an active HDC else the WGL extensions will fail */
1453 hdc = pwglGetCurrentDC();
1455 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
1456 if(GL_EXTCALL(wglGetExtensionsStringARB))
1457 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1459 if (NULL == WGL_Extensions) {
1460 ERR(" WGL_Extensions returns NULL\n");
1462 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1463 while (*WGL_Extensions != 0x00) {
1468 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1469 Start = WGL_Extensions;
1470 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1474 len = WGL_Extensions - Start;
1475 if (len == 0 || len >= sizeof(ThisExtn))
1478 memcpy(ThisExtn, Start, len);
1479 ThisExtn[len] = '\0';
1480 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1482 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1483 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1484 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1486 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
1487 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
1488 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
1490 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1491 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1492 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1499 return return_value;
1502 /**********************************************************
1503 * IWineD3D implementation follows
1504 **********************************************************/
1506 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1507 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1509 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
1511 return This->adapter_count;
1514 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1515 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1516 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1520 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1521 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1523 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1525 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1529 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1532 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1533 of the same bpp but different resolutions */
1535 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1536 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1537 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1538 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1540 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1544 /* TODO: Store modes per adapter and read it from the adapter structure */
1545 if (Adapter == 0) { /* Display */
1549 if (!DEBUG_SINGLE_MODE) {
1552 ZeroMemory(&DevModeW, sizeof(DevModeW));
1553 DevModeW.dmSize = sizeof(DevModeW);
1554 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1558 case WINED3DFMT_UNKNOWN:
1559 /* This is for D3D8, do not enumerate P8 here */
1560 if (DevModeW.dmBitsPerPel == 32 ||
1561 DevModeW.dmBitsPerPel == 16) i++;
1563 case WINED3DFMT_X8R8G8B8:
1564 if (DevModeW.dmBitsPerPel == 32) i++;
1566 case WINED3DFMT_R5G6B5:
1567 if (DevModeW.dmBitsPerPel == 16) i++;
1570 if (DevModeW.dmBitsPerPel == 8) i++;
1573 /* Skip other modes as they do not match the requested format */
1582 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1585 FIXME_(d3d_caps)("Adapter not primary display\n");
1590 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1591 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1592 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1593 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1595 /* Validate the parameters as much as possible */
1596 if (NULL == pMode ||
1597 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1598 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1599 return WINED3DERR_INVALIDCALL;
1602 /* TODO: Store modes per adapter and read it from the adapter structure */
1603 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1609 ZeroMemory(&DevModeW, sizeof(DevModeW));
1610 DevModeW.dmSize = sizeof(DevModeW);
1612 /* If we are filtering to a specific format (D3D9), then need to skip
1613 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1614 just count through the ones with valid bit depths */
1615 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1618 case WINED3DFMT_UNKNOWN:
1619 /* This is D3D8. Do not enumerate P8 here */
1620 if (DevModeW.dmBitsPerPel == 32 ||
1621 DevModeW.dmBitsPerPel == 16) i++;
1623 case WINED3DFMT_X8R8G8B8:
1624 if (DevModeW.dmBitsPerPel == 32) i++;
1626 case WINED3DFMT_R5G6B5:
1627 if (DevModeW.dmBitsPerPel == 16) i++;
1630 if (DevModeW.dmBitsPerPel == 8) i++;
1633 /* Modes that don't match what we support can get an early-out */
1634 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1635 return WINED3DERR_INVALIDCALL;
1640 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1641 return WINED3DERR_INVALIDCALL;
1645 /* Now get the display mode via the calculated index */
1646 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1647 pMode->Width = DevModeW.dmPelsWidth;
1648 pMode->Height = DevModeW.dmPelsHeight;
1649 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1650 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1651 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1653 if (Format == WINED3DFMT_UNKNOWN) {
1654 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1656 pMode->Format = Format;
1659 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1660 return WINED3DERR_INVALIDCALL;
1663 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1664 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1665 DevModeW.dmBitsPerPel);
1667 } else if (DEBUG_SINGLE_MODE) {
1668 /* Return one setting of the format requested */
1669 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1671 pMode->Height = 600;
1672 pMode->RefreshRate = 60;
1673 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1675 FIXME_(d3d_caps)("Adapter not primary display\n");
1681 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1682 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1683 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1685 if (NULL == pMode ||
1686 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1687 return WINED3DERR_INVALIDCALL;
1690 if (Adapter == 0) { /* Display */
1694 ZeroMemory(&DevModeW, sizeof(DevModeW));
1695 DevModeW.dmSize = sizeof(DevModeW);
1697 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1698 pMode->Width = DevModeW.dmPelsWidth;
1699 pMode->Height = DevModeW.dmPelsHeight;
1700 bpp = DevModeW.dmBitsPerPel;
1701 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1702 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1704 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1707 pMode->Format = pixelformat_for_depth(bpp);
1709 FIXME_(d3d_caps)("Adapter not primary display\n");
1712 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1713 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1717 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1718 and fields being inserted in the middle, a new structure is used in place */
1719 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1720 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1721 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1723 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1725 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1726 return WINED3DERR_INVALIDCALL;
1729 /* Return the information requested */
1730 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1731 strcpy(pIdentifier->Driver, This->adapters[Adapter].driver);
1732 if(This->adapters[Adapter].gl_info.driver_description)
1733 strcpy(pIdentifier->Description, This->adapters[Adapter].gl_info.driver_description);
1734 else /* Copy default description "Direct3D HAL" */
1735 strcpy(pIdentifier->Description, This->adapters[Adapter].description);
1737 /* Note dx8 doesn't supply a DeviceName */
1738 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1739 pIdentifier->DriverVersion->u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
1740 pIdentifier->DriverVersion->u.LowPart = This->adapters[Adapter].gl_info.driver_version;
1741 *(pIdentifier->VendorId) = This->adapters[Adapter].gl_info.gl_vendor;
1742 *(pIdentifier->DeviceId) = This->adapters[Adapter].gl_info.gl_card;
1743 *(pIdentifier->SubSysId) = 0;
1744 *(pIdentifier->Revision) = 0;
1745 *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID;
1747 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1749 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
1750 *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id;
1753 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1755 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
1756 *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id;
1759 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1760 *(pIdentifier->WHQLLevel) = 0;
1762 *(pIdentifier->WHQLLevel) = 1;
1768 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_GL_Info *gl_info,
1769 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
1771 short redSize, greenSize, blueSize, alphaSize, colorBits;
1776 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
1777 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
1779 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
1783 if(cfg->redSize < redSize)
1786 if(cfg->greenSize < greenSize)
1789 if(cfg->blueSize < blueSize)
1792 if(cfg->alphaSize < alphaSize)
1796 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
1797 if (format_desc->format == WINED3DFMT_R16_FLOAT)
1798 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1799 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
1800 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1801 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
1802 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
1803 if (format_desc->format == WINED3DFMT_R32_FLOAT)
1804 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1805 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
1806 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1807 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
1808 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
1810 /* Probably a color index mode */
1817 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_GL_Info *gl_info,
1818 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
1820 short depthSize, stencilSize;
1821 BOOL lockable = FALSE;
1826 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
1828 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
1832 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32F_LOCKABLE))
1835 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
1836 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
1837 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
1838 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
1841 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
1842 * allow more stencil bits than requested. */
1843 if(cfg->stencilSize < stencilSize)
1849 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1850 WINED3DFORMAT AdapterFormat,
1851 WINED3DFORMAT RenderTargetFormat,
1852 WINED3DFORMAT DepthStencilFormat) {
1853 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1855 const WineD3D_PixelFormat *cfgs;
1856 const struct WineD3DAdapter *adapter;
1857 const struct GlPixelFormatDesc *rt_format_desc;
1858 const struct GlPixelFormatDesc *ds_format_desc;
1861 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1863 DeviceType, debug_d3ddevicetype(DeviceType),
1864 AdapterFormat, debug_d3dformat(AdapterFormat),
1865 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1866 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1868 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1869 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1870 return WINED3DERR_INVALIDCALL;
1873 adapter = &This->adapters[Adapter];
1874 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
1875 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
1876 cfgs = adapter->cfgs;
1877 nCfgs = adapter->nCfgs;
1878 for (it = 0; it < nCfgs; ++it) {
1879 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
1881 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
1883 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1888 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1890 return WINED3DERR_NOTAVAILABLE;
1893 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1894 WINED3DFORMAT SurfaceFormat,
1895 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1897 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1898 const struct GlPixelFormatDesc *glDesc;
1899 const struct WineD3DAdapter *adapter;
1901 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1904 DeviceType, debug_d3ddevicetype(DeviceType),
1905 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1910 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1911 return WINED3DERR_INVALIDCALL;
1914 /* TODO: handle Windowed, add more quality levels */
1916 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1918 /* By default multisampling is disabled right now as it causes issues
1919 * on some Nvidia driver versions and it doesn't work well in combination
1921 if(!wined3d_settings.allow_multisampling)
1922 return WINED3DERR_NOTAVAILABLE;
1924 adapter = &This->adapters[Adapter];
1925 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
1926 if (!glDesc) return WINED3DERR_INVALIDCALL;
1928 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
1930 const WineD3D_PixelFormat *cfgs;
1932 cfgs = adapter->cfgs;
1933 nCfgs = adapter->nCfgs;
1934 for(i=0; i<nCfgs; i++) {
1935 if(cfgs[i].numSamples != MultiSampleType)
1938 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
1941 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1944 *pQualityLevels = 1; /* Guess at a value! */
1948 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
1949 short redSize, greenSize, blueSize, alphaSize, colorBits;
1951 const WineD3D_PixelFormat *cfgs;
1953 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
1955 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
1956 return WINED3DERR_NOTAVAILABLE;
1959 cfgs = adapter->cfgs;
1960 nCfgs = adapter->nCfgs;
1961 for(i=0; i<nCfgs; i++) {
1962 if(cfgs[i].numSamples != MultiSampleType)
1964 if(cfgs[i].redSize != redSize)
1966 if(cfgs[i].greenSize != greenSize)
1968 if(cfgs[i].blueSize != blueSize)
1970 if(cfgs[i].alphaSize != alphaSize)
1973 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1976 *pQualityLevels = 1; /* Guess at a value! */
1980 return WINED3DERR_NOTAVAILABLE;
1983 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1984 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1986 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1987 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1990 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1993 DeviceType, debug_d3ddevicetype(DeviceType),
1994 DisplayFormat, debug_d3dformat(DisplayFormat),
1995 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1998 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1999 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2000 return WINED3DERR_INVALIDCALL;
2003 /* The task of this function is to check whether a certain display / backbuffer format
2004 * combination is available on the given adapter. In fullscreen mode microsoft specified
2005 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2006 * and display format should match exactly.
2007 * In windowed mode format conversion can occur and this depends on the driver. When format
2008 * conversion is done, this function should nevertheless fail and applications need to use
2009 * CheckDeviceFormatConversion.
2010 * At the moment we assume that fullscreen and windowed have the same capabilities */
2012 /* There are only 4 display formats */
2013 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
2014 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
2015 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
2016 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
2018 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2019 return WINED3DERR_NOTAVAILABLE;
2022 /* If the requested DisplayFormat is not available, don't continue */
2023 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2025 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2026 return WINED3DERR_NOTAVAILABLE;
2029 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2030 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2031 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2032 return WINED3DERR_NOTAVAILABLE;
2035 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2036 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
2037 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2038 return WINED3DERR_NOTAVAILABLE;
2041 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2042 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
2043 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2044 return WINED3DERR_NOTAVAILABLE;
2047 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2048 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
2049 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2050 return WINED3DERR_NOTAVAILABLE;
2053 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2054 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
2055 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2056 return WINED3DERR_NOTAVAILABLE;
2059 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2060 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2062 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2068 /* Check if we support bumpmapping for a format */
2069 static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
2070 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2072 const struct fragment_pipeline *fp;
2074 switch(format_desc->format)
2076 case WINED3DFMT_R8G8_SNORM:
2077 case WINED3DFMT_R16G16_SNORM:
2078 case WINED3DFMT_L6V5U5:
2079 case WINED3DFMT_X8L8V8U8:
2080 case WINED3DFMT_R8G8B8A8_SNORM:
2081 /* Ask the fixed function pipeline implementation if it can deal
2082 * with the conversion. If we've got a GL extension giving native
2083 * support this will be an identity conversion. */
2084 fp = select_fragment_implementation(adapter, DeviceType);
2085 if (fp->color_fixup_supported(format_desc->color_fixup))
2087 TRACE_(d3d_caps)("[OK]\n");
2090 TRACE_(d3d_caps)("[FAILED]\n");
2094 TRACE_(d3d_caps)("[FAILED]\n");
2099 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2100 static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
2101 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2105 /* Only allow depth/stencil formats */
2106 if (!(ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) return FALSE;
2108 /* Walk through all WGL pixel formats to find a match */
2109 for (it = 0; it < adapter->nCfgs; ++it)
2111 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2112 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2114 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2124 static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2126 /* The flags entry of a format contains the filtering capability */
2127 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2132 /* Check the render target capabilities of a format */
2133 static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
2134 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2136 /* Filter out non-RT formats */
2137 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2139 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2140 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2142 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2143 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2145 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2146 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2148 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2149 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2150 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2151 TRACE_(d3d_caps)("[FAILED]\n");
2155 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2156 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2157 for (it = 0; it < adapter->nCfgs; ++it)
2159 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2160 &cfgs[it], check_format_desc))
2162 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2163 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2167 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2168 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2169 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2172 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2173 for (it = 0; it < adapter->nCfgs; ++it)
2175 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2176 &cfgs[it], check_format_desc))
2178 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2179 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2183 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2184 /* For now return TRUE for FBOs until we have some proper checks.
2185 * Note that this function will only be called when the format is around for texturing. */
2191 static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2193 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2195 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2196 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2197 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2201 switch (format_desc->format)
2203 case WINED3DFMT_A8R8G8B8:
2204 case WINED3DFMT_X8R8G8B8:
2205 case WINED3DFMT_A4R4G4B4:
2207 case WINED3DFMT_A8L8:
2208 case WINED3DFMT_DXT1:
2209 case WINED3DFMT_DXT2:
2210 case WINED3DFMT_DXT3:
2211 case WINED3DFMT_DXT4:
2212 case WINED3DFMT_DXT5:
2213 TRACE_(d3d_caps)("[OK]\n");
2217 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2223 static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
2224 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2226 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2227 * doing the color fixup in shaders.
2228 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2229 if ((format_desc->format == WINED3DFMT_X8R8G8B8) || (format_desc->format == WINED3DFMT_A8R8G8B8))
2231 int vs_selected_mode;
2232 int ps_selected_mode;
2233 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2235 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2236 TRACE_(d3d_caps)("[OK]\n");
2241 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2245 /* Check if a format support blending in combination with pixel shaders */
2246 static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter,
2247 const struct GlPixelFormatDesc *format_desc)
2249 /* The flags entry of a format contains the post pixel shader blending capability */
2250 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2255 static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2257 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2258 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2259 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2260 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2261 * capability anyway.
2263 * For now lets report this on all formats, but in the future we may want to
2264 * restrict it to some should games need that
2269 /* Check if a texture format is supported on the given adapter */
2270 static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
2271 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2273 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2274 const shader_backend_t *shader_backend;
2275 const struct fragment_pipeline *fp;
2277 switch (format_desc->format)
2280 * supported: RGB(A) formats
2282 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2283 case WINED3DFMT_A8R8G8B8:
2284 case WINED3DFMT_X8R8G8B8:
2285 case WINED3DFMT_R5G6B5:
2286 case WINED3DFMT_X1R5G5B5:
2287 case WINED3DFMT_A1R5G5B5:
2288 case WINED3DFMT_A4R4G4B4:
2289 case WINED3DFMT_A8_UNORM:
2290 case WINED3DFMT_X4R4G4B4:
2291 case WINED3DFMT_R8G8B8A8_UNORM:
2292 case WINED3DFMT_X8B8G8R8:
2293 case WINED3DFMT_A2R10G10B10:
2294 case WINED3DFMT_R10G10B10A2_UNORM:
2295 case WINED3DFMT_R16G16_UNORM:
2296 TRACE_(d3d_caps)("[OK]\n");
2299 case WINED3DFMT_R3G3B2:
2300 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2304 * supported: Palettized
2307 TRACE_(d3d_caps)("[OK]\n");
2309 /* No Windows driver offers A8P8, so don't offer it either */
2310 case WINED3DFMT_A8P8:
2314 * Supported: (Alpha)-Luminance
2317 case WINED3DFMT_A8L8:
2318 case WINED3DFMT_L16:
2319 TRACE_(d3d_caps)("[OK]\n");
2322 /* Not supported on Windows, thus disabled */
2323 case WINED3DFMT_A4L4:
2324 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2328 * Supported: Depth/Stencil formats
2330 case WINED3DFMT_D16_LOCKABLE:
2331 case WINED3DFMT_D16_UNORM:
2332 case WINED3DFMT_D15S1:
2333 case WINED3DFMT_D24X8:
2334 case WINED3DFMT_D24X4S4:
2335 case WINED3DFMT_D24S8:
2336 case WINED3DFMT_D24FS8:
2337 case WINED3DFMT_D32:
2338 case WINED3DFMT_D32F_LOCKABLE:
2342 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2343 * GL_NV_texture_shader). Emulated by shaders
2345 case WINED3DFMT_R8G8_SNORM:
2346 case WINED3DFMT_X8L8V8U8:
2347 case WINED3DFMT_L6V5U5:
2348 case WINED3DFMT_R8G8B8A8_SNORM:
2349 case WINED3DFMT_R16G16_SNORM:
2350 /* Ask the shader backend if it can deal with the conversion. If
2351 * we've got a GL extension giving native support this will be an
2352 * identity conversion. */
2353 shader_backend = select_shader_backend(adapter, DeviceType);
2354 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
2356 TRACE_(d3d_caps)("[OK]\n");
2359 TRACE_(d3d_caps)("[FAILED]\n");
2362 case WINED3DFMT_DXT1:
2363 case WINED3DFMT_DXT2:
2364 case WINED3DFMT_DXT3:
2365 case WINED3DFMT_DXT4:
2366 case WINED3DFMT_DXT5:
2367 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2368 TRACE_(d3d_caps)("[OK]\n");
2371 TRACE_(d3d_caps)("[FAILED]\n");
2376 * Odd formats - not supported
2378 case WINED3DFMT_VERTEXDATA:
2379 case WINED3DFMT_R16_UINT:
2380 case WINED3DFMT_R32_UINT:
2381 case WINED3DFMT_R16G16B16A16_SNORM:
2382 case WINED3DFMT_A2W10V10U10:
2383 case WINED3DFMT_W11V11U10:
2384 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2388 * WINED3DFMT_CxV8U8: Not supported right now
2390 case WINED3DFMT_CxV8U8:
2391 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2395 case WINED3DFMT_UYVY:
2396 case WINED3DFMT_YUY2:
2397 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2398 TRACE_(d3d_caps)("[OK]\n");
2401 TRACE_(d3d_caps)("[FAILED]\n");
2403 case WINED3DFMT_YV12:
2404 TRACE_(d3d_caps)("[FAILED]\n");
2408 case WINED3DFMT_R16G16B16A16_UNORM:
2409 case WINED3DFMT_A8R3G3B2:
2410 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2413 /* Floating point formats */
2414 case WINED3DFMT_R16_FLOAT:
2415 case WINED3DFMT_R16G16_FLOAT:
2416 case WINED3DFMT_R16G16B16A16_FLOAT:
2417 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2418 TRACE_(d3d_caps)("[OK]\n");
2421 TRACE_(d3d_caps)("[FAILED]\n");
2424 case WINED3DFMT_R32_FLOAT:
2425 case WINED3DFMT_R32G32_FLOAT:
2426 case WINED3DFMT_R32G32B32A32_FLOAT:
2427 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2428 TRACE_(d3d_caps)("[OK]\n");
2431 TRACE_(d3d_caps)("[FAILED]\n");
2434 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2435 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2436 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2437 * We can do instancing with all shader versions, but we need vertex shaders.
2439 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2440 * to enable instancing. WineD3D doesn't need that and just ignores it.
2442 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2444 case WINEMAKEFOURCC('I','N','S','T'):
2445 TRACE("ATI Instancing check hack\n");
2446 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2447 TRACE_(d3d_caps)("[OK]\n");
2450 TRACE_(d3d_caps)("[FAILED]\n");
2453 /* Some weird FOURCC formats */
2454 case WINED3DFMT_R8G8_B8G8:
2455 case WINED3DFMT_G8R8_G8B8:
2456 case WINED3DFMT_MULTI2_ARGB8:
2457 TRACE_(d3d_caps)("[FAILED]\n");
2460 /* Vendor specific formats */
2461 case WINED3DFMT_ATI2N:
2462 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2463 shader_backend = select_shader_backend(adapter, DeviceType);
2464 fp = select_fragment_implementation(adapter, DeviceType);
2465 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
2466 && fp->color_fixup_supported(format_desc->color_fixup))
2468 TRACE_(d3d_caps)("[OK]\n");
2472 TRACE_(d3d_caps)("[OK]\n");
2475 TRACE_(d3d_caps)("[FAILED]\n");
2478 case WINED3DFMT_NVHU:
2479 case WINED3DFMT_NVHS:
2480 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2481 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2482 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2483 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2484 * Applications have to deal with not having NVHS and NVHU.
2486 TRACE_(d3d_caps)("[FAILED]\n");
2489 case WINED3DFMT_UNKNOWN:
2493 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
2499 static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
2500 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
2502 const struct blit_shader *blitter;
2504 if(SurfaceType == SURFACE_GDI) {
2505 switch(check_format_desc->format)
2507 case WINED3DFMT_R8G8B8:
2508 case WINED3DFMT_A8R8G8B8:
2509 case WINED3DFMT_X8R8G8B8:
2510 case WINED3DFMT_R5G6B5:
2511 case WINED3DFMT_X1R5G5B5:
2512 case WINED3DFMT_A1R5G5B5:
2513 case WINED3DFMT_A4R4G4B4:
2514 case WINED3DFMT_R3G3B2:
2515 case WINED3DFMT_A8_UNORM:
2516 case WINED3DFMT_A8R3G3B2:
2517 case WINED3DFMT_X4R4G4B4:
2518 case WINED3DFMT_R10G10B10A2_UNORM:
2519 case WINED3DFMT_R8G8B8A8_UNORM:
2520 case WINED3DFMT_X8B8G8R8:
2521 case WINED3DFMT_R16G16_UNORM:
2522 case WINED3DFMT_A2R10G10B10:
2523 case WINED3DFMT_R16G16B16A16_UNORM:
2525 TRACE_(d3d_caps)("[OK]\n");
2528 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
2533 /* All format that are supported for textures are supported for surfaces as well */
2534 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
2535 /* All depth stencil formats are supported on surfaces */
2536 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
2538 /* If opengl can't process the format natively, the blitter may be able to convert it */
2539 blitter = select_blit_implementation(adapter, DeviceType);
2540 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
2542 TRACE_(d3d_caps)("[OK]\n");
2546 /* Reject other formats */
2547 TRACE_(d3d_caps)("[FAILED]\n");
2551 static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2553 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2555 if (!GL_LIMITS(vertex_samplers)) {
2556 TRACE_(d3d_caps)("[FAILED]\n");
2560 switch (format_desc->format)
2562 case WINED3DFMT_R32G32B32A32_FLOAT:
2563 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2564 TRACE_(d3d_caps)("[FAILED]\n");
2567 TRACE_(d3d_caps)("[OK]\n");
2571 TRACE_(d3d_caps)("[FAILED]\n");
2577 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2578 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
2579 WINED3DSURFTYPE SurfaceType) {
2580 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2581 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
2582 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2583 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
2584 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
2585 DWORD UsageCaps = 0;
2587 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
2590 DeviceType, debug_d3ddevicetype(DeviceType),
2591 AdapterFormat, debug_d3dformat(AdapterFormat),
2592 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
2593 RType, debug_d3dresourcetype(RType),
2594 CheckFormat, debug_d3dformat(CheckFormat));
2596 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2597 return WINED3DERR_INVALIDCALL;
2600 if(RType == WINED3DRTYPE_CUBETEXTURE) {
2602 if(SurfaceType != SURFACE_OPENGL) {
2603 TRACE("[FAILED]\n");
2604 return WINED3DERR_NOTAVAILABLE;
2607 /* Cubetexture allows:
2608 * - D3DUSAGE_AUTOGENMIPMAP
2609 * - D3DUSAGE_DEPTHSTENCIL
2610 * - D3DUSAGE_DYNAMIC
2611 * - D3DUSAGE_NONSECURE (d3d9ex)
2612 * - D3DUSAGE_RENDERTARGET
2613 * - D3DUSAGE_SOFTWAREPROCESSING
2614 * - D3DUSAGE_QUERY_WRAPANDMIP
2616 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2617 /* Check if the texture format is around */
2618 if (CheckTextureCapability(adapter, DeviceType, format_desc))
2620 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2621 /* Check for automatic mipmap generation support */
2622 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2623 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2625 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2626 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2630 /* Always report dynamic locking */
2631 if(Usage & WINED3DUSAGE_DYNAMIC)
2632 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2634 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2635 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
2637 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2639 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2640 return WINED3DERR_NOTAVAILABLE;
2644 /* Always report software processing */
2645 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2646 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2648 /* Check QUERY_FILTER support */
2649 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2650 if (CheckFilterCapability(adapter, format_desc))
2652 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2654 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2655 return WINED3DERR_NOTAVAILABLE;
2659 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2660 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2661 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
2663 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2665 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2666 return WINED3DERR_NOTAVAILABLE;
2670 /* Check QUERY_SRGBREAD support */
2671 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2672 if (CheckSrgbReadCapability(adapter, format_desc))
2674 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2676 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2677 return WINED3DERR_NOTAVAILABLE;
2681 /* Check QUERY_SRGBWRITE support */
2682 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2683 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
2685 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2687 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2688 return WINED3DERR_NOTAVAILABLE;
2692 /* Check QUERY_VERTEXTEXTURE support */
2693 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2694 if (CheckVertexTextureCapability(adapter, format_desc))
2696 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2698 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2699 return WINED3DERR_NOTAVAILABLE;
2703 /* Check QUERY_WRAPANDMIP support */
2704 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2705 if (CheckWrapAndMipCapability(adapter, format_desc))
2707 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2709 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2710 return WINED3DERR_NOTAVAILABLE;
2714 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
2715 return WINED3DERR_NOTAVAILABLE;
2718 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
2719 return WINED3DERR_NOTAVAILABLE;
2721 } else if(RType == WINED3DRTYPE_SURFACE) {
2723 * - D3DUSAGE_DEPTHSTENCIL
2724 * - D3DUSAGE_NONSECURE (d3d9ex)
2725 * - D3DUSAGE_RENDERTARGET
2728 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
2730 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2731 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
2733 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2735 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
2736 return WINED3DERR_NOTAVAILABLE;
2740 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2741 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
2743 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2745 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2746 return WINED3DERR_NOTAVAILABLE;
2750 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2751 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2752 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
2754 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2756 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2757 return WINED3DERR_NOTAVAILABLE;
2761 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
2762 return WINED3DERR_NOTAVAILABLE;
2765 } else if(RType == WINED3DRTYPE_TEXTURE) {
2767 * - D3DUSAGE_AUTOGENMIPMAP
2768 * - D3DUSAGE_DEPTHSTENCIL
2770 * - D3DUSAGE_DYNAMIC
2771 * - D3DUSAGE_NONSECURE (d3d9ex)
2772 * - D3DUSAGE_RENDERTARGET
2773 * - D3DUSAGE_SOFTWAREPROCESSING
2774 * - D3DUSAGE_TEXTAPI (d3d9ex)
2775 * - D3DUSAGE_QUERY_WRAPANDMIP
2778 if(SurfaceType != SURFACE_OPENGL) {
2779 TRACE("[FAILED]\n");
2780 return WINED3DERR_NOTAVAILABLE;
2783 /* Check if the texture format is around */
2784 if (CheckTextureCapability(adapter, DeviceType, format_desc))
2786 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2787 /* Check for automatic mipmap generation support */
2788 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2789 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2791 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2792 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2796 /* Always report dynamic locking */
2797 if(Usage & WINED3DUSAGE_DYNAMIC)
2798 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2800 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2801 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
2803 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2805 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2806 return WINED3DERR_NOTAVAILABLE;
2810 /* Always report software processing */
2811 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2812 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2814 /* Check QUERY_FILTER support */
2815 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2816 if (CheckFilterCapability(adapter, format_desc))
2818 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2820 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2821 return WINED3DERR_NOTAVAILABLE;
2825 /* Check QUERY_LEGACYBUMPMAP support */
2826 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
2827 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
2829 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
2831 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
2832 return WINED3DERR_NOTAVAILABLE;
2836 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2837 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2838 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
2840 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2842 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2843 return WINED3DERR_NOTAVAILABLE;
2847 /* Check QUERY_SRGBREAD support */
2848 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2849 if (CheckSrgbReadCapability(adapter, format_desc))
2851 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2853 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2854 return WINED3DERR_NOTAVAILABLE;
2858 /* Check QUERY_SRGBWRITE support */
2859 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2860 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
2862 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2864 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2865 return WINED3DERR_NOTAVAILABLE;
2869 /* Check QUERY_VERTEXTEXTURE support */
2870 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2871 if (CheckVertexTextureCapability(adapter, format_desc))
2873 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2875 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2876 return WINED3DERR_NOTAVAILABLE;
2880 /* Check QUERY_WRAPANDMIP support */
2881 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2882 if (CheckWrapAndMipCapability(adapter, format_desc))
2884 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2886 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2887 return WINED3DERR_NOTAVAILABLE;
2891 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2892 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
2894 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2896 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
2897 return WINED3DERR_NOTAVAILABLE;
2901 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
2902 return WINED3DERR_NOTAVAILABLE;
2904 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
2905 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
2906 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
2908 * Volumetexture allows:
2909 * - D3DUSAGE_DYNAMIC
2910 * - D3DUSAGE_NONSECURE (d3d9ex)
2911 * - D3DUSAGE_SOFTWAREPROCESSING
2912 * - D3DUSAGE_QUERY_WRAPANDMIP
2915 if(SurfaceType != SURFACE_OPENGL) {
2916 TRACE("[FAILED]\n");
2917 return WINED3DERR_NOTAVAILABLE;
2920 /* Check volume texture and volume usage caps */
2921 if(GL_SUPPORT(EXT_TEXTURE3D)) {
2922 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
2924 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
2925 return WINED3DERR_NOTAVAILABLE;
2928 /* Always report dynamic locking */
2929 if(Usage & WINED3DUSAGE_DYNAMIC)
2930 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2932 /* Always report software processing */
2933 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2934 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2936 /* Check QUERY_FILTER support */
2937 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2938 if (CheckFilterCapability(adapter, format_desc))
2940 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2942 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2943 return WINED3DERR_NOTAVAILABLE;
2947 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2948 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2949 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
2951 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2953 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2954 return WINED3DERR_NOTAVAILABLE;
2958 /* Check QUERY_SRGBREAD support */
2959 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2960 if (CheckSrgbReadCapability(adapter, format_desc))
2962 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2964 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2965 return WINED3DERR_NOTAVAILABLE;
2969 /* Check QUERY_SRGBWRITE support */
2970 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2971 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
2973 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2975 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2976 return WINED3DERR_NOTAVAILABLE;
2980 /* Check QUERY_VERTEXTEXTURE support */
2981 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2982 if (CheckVertexTextureCapability(adapter, format_desc))
2984 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2986 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2987 return WINED3DERR_NOTAVAILABLE;
2991 /* Check QUERY_WRAPANDMIP support */
2992 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2993 if (CheckWrapAndMipCapability(adapter, format_desc))
2995 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2997 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2998 return WINED3DERR_NOTAVAILABLE;
3002 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3003 return WINED3DERR_NOTAVAILABLE;
3006 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3007 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3008 * app needing one of those formats, don't advertize them to avoid leading apps into
3009 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3012 switch(CheckFormat) {
3014 case WINED3DFMT_A4L4:
3015 case WINED3DFMT_R32_FLOAT:
3016 case WINED3DFMT_R16_FLOAT:
3017 case WINED3DFMT_X8L8V8U8:
3018 case WINED3DFMT_L6V5U5:
3019 case WINED3DFMT_R16G16_UNORM:
3020 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3021 return WINED3DERR_NOTAVAILABLE;
3023 case WINED3DFMT_R8G8B8A8_SNORM:
3024 case WINED3DFMT_R16G16_SNORM:
3025 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3026 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3027 return WINED3DERR_NOTAVAILABLE;
3031 case WINED3DFMT_R8G8_SNORM:
3032 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3033 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3034 return WINED3DERR_NOTAVAILABLE;
3038 case WINED3DFMT_DXT1:
3039 case WINED3DFMT_DXT2:
3040 case WINED3DFMT_DXT3:
3041 case WINED3DFMT_DXT4:
3042 case WINED3DFMT_DXT5:
3043 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3044 * compressed texture results in an error. While the D3D refrast does
3045 * support s3tc volumes, at least the nvidia windows driver does not, so
3046 * we're free not to support this format.
3048 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3049 return WINED3DERR_NOTAVAILABLE;
3052 /* Do nothing, continue with checking the format below */
3055 } else if(RType == WINED3DRTYPE_BUFFER){
3056 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3057 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3058 return WINED3DERR_NOTAVAILABLE;
3061 /* This format is nothing special and it is supported perfectly.
3062 * However, ati and nvidia driver on windows do not mark this format as
3063 * supported (tested with the dxCapsViewer) and pretending to
3064 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
3065 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
3066 * Enable it on dx7. It will need additional checking on dx10 when we support it.
3068 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
3069 TRACE_(d3d_caps)("[FAILED]\n");
3070 return WINED3DERR_NOTAVAILABLE;
3073 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3074 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3075 * usage flags match. */
3076 if(UsageCaps == Usage) {
3078 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3079 return WINED3DOK_NOAUTOGEN;
3081 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);
3082 return WINED3DERR_NOTAVAILABLE;
3086 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3087 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3088 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3090 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3093 DeviceType, debug_d3ddevicetype(DeviceType),
3094 SourceFormat, debug_d3dformat(SourceFormat),
3095 TargetFormat, debug_d3dformat(TargetFormat));
3099 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3101 const shader_backend_t *ret;
3102 int vs_selected_mode;
3103 int ps_selected_mode;
3105 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3106 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3107 ret = &glsl_shader_backend;
3108 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3109 ret = &arb_program_shader_backend;
3111 ret = &none_shader_backend;
3116 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
3117 WINED3DDEVTYPE DeviceType)
3119 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3120 int vs_selected_mode;
3121 int ps_selected_mode;
3123 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3124 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3125 return &arbfp_fragment_pipeline;
3126 } else if(ps_selected_mode == SHADER_ATI) {
3127 return &atifs_fragment_pipeline;
3128 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3129 return &nvts_fragment_pipeline;
3130 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3131 return &nvrc_fragment_pipeline;
3133 return &ffp_fragment_pipeline;
3137 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3139 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3140 int vs_selected_mode;
3141 int ps_selected_mode;
3143 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3144 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3151 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3152 subset of a D3DCAPS9 structure. However, it has to come via a void *
3153 as the d3d8 interface cannot import the d3d9 header */
3154 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3156 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3157 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3158 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3159 int vs_selected_mode;
3160 int ps_selected_mode;
3161 struct shader_caps shader_caps;
3162 struct fragment_caps fragment_caps;
3163 const shader_backend_t *shader_backend;
3164 const struct fragment_pipeline *frag_pipeline = NULL;
3165 DWORD ckey_caps, blit_caps, fx_caps;
3167 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3169 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3170 return WINED3DERR_INVALIDCALL;
3173 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3175 /* This function should *not* be modifying GL caps
3176 * TODO: move the functionality where it belongs */
3177 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
3179 /* ------------------------------------------------
3180 The following fields apply to both d3d8 and d3d9
3181 ------------------------------------------------ */
3182 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3183 pCaps->AdapterOrdinal = Adapter;
3186 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3187 WINED3DCAPS2_FULLSCREENGAMMA |
3188 WINED3DCAPS2_DYNAMICTEXTURES;
3189 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3190 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3193 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3194 WINED3DCAPS3_COPY_TO_VIDMEM |
3195 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3197 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3198 WINED3DPRESENT_INTERVAL_ONE;
3200 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3201 WINED3DCURSORCAPS_LOWRES;
3203 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3204 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3205 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3206 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3207 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3208 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3209 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3210 WINED3DDEVCAPS_PUREDEVICE |
3211 WINED3DDEVCAPS_HWRASTERIZATION |
3212 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3213 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3214 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3215 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3216 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3217 WINED3DDEVCAPS_RTPATCHES;
3219 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3220 WINED3DPMISCCAPS_CULLCCW |
3221 WINED3DPMISCCAPS_CULLCW |
3222 WINED3DPMISCCAPS_COLORWRITEENABLE |
3223 WINED3DPMISCCAPS_CLIPTLVERTS |
3224 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3225 WINED3DPMISCCAPS_MASKZ |
3226 WINED3DPMISCCAPS_BLENDOP |
3227 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3229 WINED3DPMISCCAPS_NULLREFERENCE
3230 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3231 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3232 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3233 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3235 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3236 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3238 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3239 WINED3DPRASTERCAPS_PAT |
3240 WINED3DPRASTERCAPS_WFOG |
3241 WINED3DPRASTERCAPS_ZFOG |
3242 WINED3DPRASTERCAPS_FOGVERTEX |
3243 WINED3DPRASTERCAPS_FOGTABLE |
3244 WINED3DPRASTERCAPS_STIPPLE |
3245 WINED3DPRASTERCAPS_SUBPIXEL |
3246 WINED3DPRASTERCAPS_ZTEST |
3247 WINED3DPRASTERCAPS_SCISSORTEST |
3248 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3249 WINED3DPRASTERCAPS_DEPTHBIAS;
3251 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3252 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3253 WINED3DPRASTERCAPS_ZBIAS |
3254 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3256 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3257 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3260 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3261 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3262 WINED3DPRASTERCAPS_ANTIALIASEDGES
3263 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3264 WINED3DPRASTERCAPS_WBUFFER */
3266 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3267 WINED3DPCMPCAPS_EQUAL |
3268 WINED3DPCMPCAPS_GREATER |
3269 WINED3DPCMPCAPS_GREATEREQUAL |
3270 WINED3DPCMPCAPS_LESS |
3271 WINED3DPCMPCAPS_LESSEQUAL |
3272 WINED3DPCMPCAPS_NEVER |
3273 WINED3DPCMPCAPS_NOTEQUAL;
3275 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3276 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3277 WINED3DPBLENDCAPS_DESTALPHA |
3278 WINED3DPBLENDCAPS_DESTCOLOR |
3279 WINED3DPBLENDCAPS_INVDESTALPHA |
3280 WINED3DPBLENDCAPS_INVDESTCOLOR |
3281 WINED3DPBLENDCAPS_INVSRCALPHA |
3282 WINED3DPBLENDCAPS_INVSRCCOLOR |
3283 WINED3DPBLENDCAPS_ONE |
3284 WINED3DPBLENDCAPS_SRCALPHA |
3285 WINED3DPBLENDCAPS_SRCALPHASAT |
3286 WINED3DPBLENDCAPS_SRCCOLOR |
3287 WINED3DPBLENDCAPS_ZERO;
3289 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3290 WINED3DPBLENDCAPS_DESTCOLOR |
3291 WINED3DPBLENDCAPS_INVDESTALPHA |
3292 WINED3DPBLENDCAPS_INVDESTCOLOR |
3293 WINED3DPBLENDCAPS_INVSRCALPHA |
3294 WINED3DPBLENDCAPS_INVSRCCOLOR |
3295 WINED3DPBLENDCAPS_ONE |
3296 WINED3DPBLENDCAPS_SRCALPHA |
3297 WINED3DPBLENDCAPS_SRCCOLOR |
3298 WINED3DPBLENDCAPS_ZERO;
3299 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3300 * according to the glBlendFunc manpage
3302 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3303 * legacy settings for srcblend only
3306 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3307 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3308 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3312 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3313 WINED3DPCMPCAPS_EQUAL |
3314 WINED3DPCMPCAPS_GREATER |
3315 WINED3DPCMPCAPS_GREATEREQUAL |
3316 WINED3DPCMPCAPS_LESS |
3317 WINED3DPCMPCAPS_LESSEQUAL |
3318 WINED3DPCMPCAPS_NEVER |
3319 WINED3DPCMPCAPS_NOTEQUAL;
3321 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3322 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3323 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3324 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3325 WINED3DPSHADECAPS_COLORFLATRGB |
3326 WINED3DPSHADECAPS_FOGFLAT |
3327 WINED3DPSHADECAPS_FOGGOURAUD |
3328 WINED3DPSHADECAPS_SPECULARFLATRGB;
3330 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3331 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3332 WINED3DPTEXTURECAPS_TRANSPARENCY |
3333 WINED3DPTEXTURECAPS_BORDER |
3334 WINED3DPTEXTURECAPS_MIPMAP |
3335 WINED3DPTEXTURECAPS_PROJECTED |
3336 WINED3DPTEXTURECAPS_PERSPECTIVE;
3338 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3339 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3340 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3343 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3344 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3345 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3346 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3349 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3350 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3351 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3352 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3356 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3357 WINED3DPTFILTERCAPS_MAGFPOINT |
3358 WINED3DPTFILTERCAPS_MINFLINEAR |
3359 WINED3DPTFILTERCAPS_MINFPOINT |
3360 WINED3DPTFILTERCAPS_MIPFLINEAR |
3361 WINED3DPTFILTERCAPS_MIPFPOINT |
3362 WINED3DPTFILTERCAPS_LINEAR |
3363 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3364 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3365 WINED3DPTFILTERCAPS_MIPLINEAR |
3366 WINED3DPTFILTERCAPS_MIPNEAREST |
3367 WINED3DPTFILTERCAPS_NEAREST;
3369 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3370 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3371 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3374 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3375 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3376 WINED3DPTFILTERCAPS_MAGFPOINT |
3377 WINED3DPTFILTERCAPS_MINFLINEAR |
3378 WINED3DPTFILTERCAPS_MINFPOINT |
3379 WINED3DPTFILTERCAPS_MIPFLINEAR |
3380 WINED3DPTFILTERCAPS_MIPFPOINT |
3381 WINED3DPTFILTERCAPS_LINEAR |
3382 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3383 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3384 WINED3DPTFILTERCAPS_MIPLINEAR |
3385 WINED3DPTFILTERCAPS_MIPNEAREST |
3386 WINED3DPTFILTERCAPS_NEAREST;
3388 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3389 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3390 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3393 pCaps->CubeTextureFilterCaps = 0;
3395 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3396 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3397 WINED3DPTFILTERCAPS_MAGFPOINT |
3398 WINED3DPTFILTERCAPS_MINFLINEAR |
3399 WINED3DPTFILTERCAPS_MINFPOINT |
3400 WINED3DPTFILTERCAPS_MIPFLINEAR |
3401 WINED3DPTFILTERCAPS_MIPFPOINT |
3402 WINED3DPTFILTERCAPS_LINEAR |
3403 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3404 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3405 WINED3DPTFILTERCAPS_MIPLINEAR |
3406 WINED3DPTFILTERCAPS_MIPNEAREST |
3407 WINED3DPTFILTERCAPS_NEAREST;
3409 pCaps->VolumeTextureFilterCaps = 0;
3411 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3412 WINED3DPTADDRESSCAPS_CLAMP |
3413 WINED3DPTADDRESSCAPS_WRAP;
3415 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3416 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3418 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3419 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3421 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3422 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3425 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3426 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3427 WINED3DPTADDRESSCAPS_CLAMP |
3428 WINED3DPTADDRESSCAPS_WRAP;
3429 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3430 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3432 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3433 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3435 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3436 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3439 pCaps->VolumeTextureAddressCaps = 0;
3441 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3442 WINED3DLINECAPS_ZTEST |
3443 WINED3DLINECAPS_BLEND |
3444 WINED3DLINECAPS_ALPHACMP |
3445 WINED3DLINECAPS_FOG;
3446 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3447 * idea how generating the smoothing alpha values works; the result is different
3450 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3451 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3453 if(GL_SUPPORT(EXT_TEXTURE3D))
3454 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3456 pCaps->MaxVolumeExtent = 0;
3458 pCaps->MaxTextureRepeat = 32768;
3459 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3460 pCaps->MaxVertexW = 1.0;
3462 pCaps->GuardBandLeft = 0;
3463 pCaps->GuardBandTop = 0;
3464 pCaps->GuardBandRight = 0;
3465 pCaps->GuardBandBottom = 0;
3467 pCaps->ExtentsAdjust = 0;
3469 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3470 WINED3DSTENCILCAPS_INCRSAT |
3471 WINED3DSTENCILCAPS_INVERT |
3472 WINED3DSTENCILCAPS_KEEP |
3473 WINED3DSTENCILCAPS_REPLACE |
3474 WINED3DSTENCILCAPS_ZERO;
3475 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3476 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3477 WINED3DSTENCILCAPS_INCR;
3479 if ( This->dxVersion > 8 &&
3480 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
3481 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
3482 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3485 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3487 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3488 pCaps->MaxActiveLights = GL_LIMITS(lights);
3490 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3491 pCaps->MaxVertexBlendMatrixIndex = 0;
3493 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3494 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3497 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3498 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3499 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3500 WINED3DVTXPCAPS_LOCALVIEWER |
3501 WINED3DVTXPCAPS_VERTEXFOG |
3502 WINED3DVTXPCAPS_TEXGEN;
3504 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3506 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3507 pCaps->MaxVertexIndex = 0xFFFFF;
3508 pCaps->MaxStreams = MAX_STREAMS;
3509 pCaps->MaxStreamStride = 1024;
3511 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3512 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3513 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3514 pCaps->MaxNpatchTessellationLevel = 0;
3515 pCaps->MasterAdapterOrdinal = 0;
3516 pCaps->AdapterOrdinalInGroup = 0;
3517 pCaps->NumberOfAdaptersInGroup = 1;
3519 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3521 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3522 WINED3DPTFILTERCAPS_MAGFPOINT |
3523 WINED3DPTFILTERCAPS_MINFLINEAR |
3524 WINED3DPTFILTERCAPS_MAGFLINEAR;
3525 pCaps->VertexTextureFilterCaps = 0;
3527 memset(&shader_caps, 0, sizeof(shader_caps));
3528 shader_backend = select_shader_backend(adapter, DeviceType);
3529 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
3531 memset(&fragment_caps, 0, sizeof(fragment_caps));
3532 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
3533 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
3535 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
3536 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
3538 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
3539 * Ignore shader model capabilities if disabled in config
3541 if(vs_selected_mode == SHADER_NONE) {
3542 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
3543 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
3544 pCaps->MaxVertexShaderConst = 0;
3546 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
3547 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
3550 if(ps_selected_mode == SHADER_NONE) {
3551 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
3552 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
3553 pCaps->PixelShader1xMaxValue = 0.0;
3555 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
3556 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
3559 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
3560 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
3561 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
3563 pCaps->VS20Caps = shader_caps.VS20Caps;
3564 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
3565 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
3566 pCaps->PS20Caps = shader_caps.PS20Caps;
3567 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
3568 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
3570 /* The following caps are shader specific, but they are things we cannot detect, or which
3571 * are the same among all shader models. So to avoid code duplication set the shader version
3572 * specific, but otherwise constant caps here
3574 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
3575 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3576 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
3577 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
3578 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3579 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.vs_arb_max_temps);
3580 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
3582 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
3583 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
3584 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
3585 pCaps->VS20Caps.Caps = 0;
3586 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
3587 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.vs_arb_max_temps);
3588 pCaps->VS20Caps.StaticFlowControlDepth = 1;
3590 pCaps->MaxVShaderInstructionsExecuted = 65535;
3591 pCaps->MaxVertexShader30InstructionSlots = 0;
3592 } else { /* VS 1.x */
3593 pCaps->VS20Caps.Caps = 0;
3594 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
3595 pCaps->VS20Caps.NumTemps = 0;
3596 pCaps->VS20Caps.StaticFlowControlDepth = 0;
3598 pCaps->MaxVShaderInstructionsExecuted = 0;
3599 pCaps->MaxVertexShader30InstructionSlots = 0;
3602 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
3603 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3604 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
3606 /* 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 */
3607 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
3608 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
3609 WINED3DPS20CAPS_PREDICATION |
3610 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
3611 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
3612 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3613 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.ps_arb_max_temps);
3614 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
3615 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
3617 pCaps->MaxPShaderInstructionsExecuted = 65535;
3618 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
3619 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
3620 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
3621 pCaps->PS20Caps.Caps = 0;
3622 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
3623 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.ps_arb_max_temps);
3624 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
3625 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
3627 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
3628 pCaps->MaxPixelShader30InstructionSlots = 0;
3629 } else { /* PS 1.x */
3630 pCaps->PS20Caps.Caps = 0;
3631 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
3632 pCaps->PS20Caps.NumTemps = 0;
3633 pCaps->PS20Caps.StaticFlowControlDepth = 0;
3634 pCaps->PS20Caps.NumInstructionSlots = 0;
3636 pCaps->MaxPShaderInstructionsExecuted = 0;
3637 pCaps->MaxPixelShader30InstructionSlots = 0;
3640 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
3641 /* OpenGL supports all the formats below, perhaps not always
3642 * without conversion, but it supports them.
3643 * Further GLSL doesn't seem to have an official unsigned type so
3644 * don't advertise it yet as I'm not sure how we handle it.
3645 * We might need to add some clamping in the shader engine to
3647 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
3648 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
3649 WINED3DDTCAPS_UBYTE4N |
3650 WINED3DDTCAPS_SHORT2N |
3651 WINED3DDTCAPS_SHORT4N;
3652 if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
3653 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
3654 WINED3DDTCAPS_FLOAT16_4;
3657 pCaps->DeclTypes = 0;
3659 /* Set DirectDraw helper Caps */
3660 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
3661 WINEDDCKEYCAPS_SRCBLT;
3662 fx_caps = WINEDDFXCAPS_BLTALPHA |
3663 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
3664 WINEDDFXCAPS_BLTMIRRORUPDOWN |
3665 WINEDDFXCAPS_BLTROTATION90 |
3666 WINEDDFXCAPS_BLTSHRINKX |
3667 WINEDDFXCAPS_BLTSHRINKXN |
3668 WINEDDFXCAPS_BLTSHRINKY |
3669 WINEDDFXCAPS_BLTSHRINKXN |
3670 WINEDDFXCAPS_BLTSTRETCHX |
3671 WINEDDFXCAPS_BLTSTRETCHXN |
3672 WINEDDFXCAPS_BLTSTRETCHY |
3673 WINEDDFXCAPS_BLTSTRETCHYN;
3674 blit_caps = WINEDDCAPS_BLT |
3675 WINEDDCAPS_BLTCOLORFILL |
3676 WINEDDCAPS_BLTDEPTHFILL |
3677 WINEDDCAPS_BLTSTRETCH |
3678 WINEDDCAPS_CANBLTSYSMEM |
3679 WINEDDCAPS_CANCLIP |
3680 WINEDDCAPS_CANCLIPSTRETCHED |
3681 WINEDDCAPS_COLORKEY |
3682 WINEDDCAPS_COLORKEYHWASSIST |
3683 WINEDDCAPS_ALIGNBOUNDARYSRC;
3685 /* Fill the ddraw caps structure */
3686 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
3687 WINEDDCAPS_PALETTE |
3689 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
3690 WINEDDCAPS2_NOPAGELOCKREQUIRED |
3691 WINEDDCAPS2_PRIMARYGAMMA |
3692 WINEDDCAPS2_WIDESURFACES |
3693 WINEDDCAPS2_CANRENDERWINDOWED;
3694 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
3695 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
3696 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
3697 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
3698 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
3699 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
3700 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
3701 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
3702 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
3704 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
3705 WINEDDSCAPS_BACKBUFFER |
3707 WINEDDSCAPS_FRONTBUFFER |
3708 WINEDDSCAPS_OFFSCREENPLAIN |
3709 WINEDDSCAPS_PALETTE |
3710 WINEDDSCAPS_PRIMARYSURFACE |
3711 WINEDDSCAPS_SYSTEMMEMORY |
3712 WINEDDSCAPS_VIDEOMEMORY |
3713 WINEDDSCAPS_VISIBLE;
3714 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
3716 /* Set D3D caps if OpenGL is available. */
3717 if (adapter->opengl)
3719 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
3720 WINEDDSCAPS_MIPMAP |
3721 WINEDDSCAPS_TEXTURE |
3722 WINEDDSCAPS_ZBUFFER;
3723 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
3729 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
3730 and fields being inserted in the middle, a new structure is used in place */
3731 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
3732 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
3733 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
3735 IWineD3DDeviceImpl *object = NULL;
3736 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3737 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3738 WINED3DDISPLAYMODE mode;
3739 const struct fragment_pipeline *frag_pipeline = NULL;
3741 struct fragment_caps ffp_caps;
3742 struct shader_caps shader_caps;
3745 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
3746 * number and create a device without a 3D adapter for 2D only operation.
3748 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
3749 return WINED3DERR_INVALIDCALL;
3752 /* Create a WineD3DDevice object */
3753 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
3754 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
3755 TRACE("Created WineD3DDevice object @ %p\n", object);
3756 if (NULL == object) {
3757 return WINED3DERR_OUTOFVIDEOMEMORY;
3760 /* Set up initial COM information */
3761 object->lpVtbl = &IWineD3DDevice_Vtbl;
3763 object->wineD3D = iface;
3764 object->adapter = This->adapter_count ? adapter : NULL;
3765 IWineD3D_AddRef(object->wineD3D);
3766 object->parent = parent;
3767 object->device_parent = device_parent;
3768 list_init(&object->resources);
3769 list_init(&object->shaders);
3771 if(This->dxVersion == 7) {
3772 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
3774 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
3776 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
3778 /* Set the state up as invalid until the device is fully created */
3779 object->state = WINED3DERR_DRIVERINTERNALERROR;
3781 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
3782 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
3784 /* Save the creation parameters */
3785 object->createParms.AdapterOrdinal = Adapter;
3786 object->createParms.DeviceType = DeviceType;
3787 object->createParms.hFocusWindow = hFocusWindow;
3788 object->createParms.BehaviorFlags = BehaviourFlags;
3790 /* Initialize other useful values */
3791 object->adapterNo = Adapter;
3792 object->devType = DeviceType;
3794 select_shader_mode(&adapter->gl_info, DeviceType,
3795 &object->ps_selected_mode, &object->vs_selected_mode);
3796 object->shader_backend = select_shader_backend(adapter, DeviceType);
3798 memset(&shader_caps, 0, sizeof(shader_caps));
3799 object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
3800 object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
3801 object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
3803 memset(&ffp_caps, 0, sizeof(ffp_caps));
3804 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
3805 object->frag_pipe = frag_pipeline;
3806 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
3807 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
3808 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
3809 hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
3810 ffp_vertexstate_template, frag_pipeline, misc_state_template);
3813 IWineD3D_Release(object->wineD3D);
3814 HeapFree(GetProcessHeap(), 0, object);
3819 object->blitter = select_blit_implementation(adapter, DeviceType);
3821 /* set the state of the device to valid */
3822 object->state = WINED3D_OK;
3824 /* Get the initial screen setup for ddraw */
3825 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
3827 object->ddraw_width = mode.Width;
3828 object->ddraw_height = mode.Height;
3829 object->ddraw_format = mode.Format;
3831 for(i = 0; i < PATCHMAP_SIZE; i++) {
3832 list_init(&object->patches[i]);
3835 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
3840 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
3841 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3842 IUnknown_AddRef(This->parent);
3843 *pParent = This->parent;
3847 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
3848 IUnknown* surfaceParent;
3849 TRACE("(%p) call back\n", pSurface);
3851 /* Now, release the parent, which will take care of cleaning up the surface for us */
3852 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
3853 IUnknown_Release(surfaceParent);
3854 return IUnknown_Release(surfaceParent);
3857 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
3858 IUnknown* volumeParent;
3859 TRACE("(%p) call back\n", pVolume);
3861 /* Now, release the parent, which will take care of cleaning up the volume for us */
3862 IWineD3DVolume_GetParent(pVolume, &volumeParent);
3863 IUnknown_Release(volumeParent);
3864 return IUnknown_Release(volumeParent);
3867 static BOOL match_apple(const WineD3D_GL_Info *gl_info)
3869 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
3870 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
3871 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
3873 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
3874 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
3875 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
3876 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
3877 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
3878 * the chance that other implementations support them is rather small since Win32 QuickTime uses
3879 * DirectDraw, not OpenGL.
3881 if(gl_info->supported[APPLE_FENCE] &&
3882 gl_info->supported[APPLE_CLIENT_STORAGE] &&
3883 gl_info->supported[APPLE_FLUSH_RENDER] &&
3884 gl_info->supported[APPLE_YCBCR_422]) {
3885 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
3886 TRACE_(d3d_caps)("Activating MacOS fixups\n");
3889 TRACE_(d3d_caps)("Apple extensions are not supported\n");
3890 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
3895 static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
3896 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
3897 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
3898 * all the texture. This function detects this bug by its symptom and disables PBOs
3899 * if the test fails.
3901 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
3902 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
3903 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
3904 * read back is compared to the original. If they are equal PBOs are assumed to work,
3905 * otherwise the PBO extension is disabled.
3907 GLuint texture, pbo;
3908 static const unsigned int pattern[] = {
3909 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
3910 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
3911 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
3912 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
3914 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
3916 if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
3917 /* No PBO -> No point in testing them */
3923 while(glGetError());
3924 glGenTextures(1, &texture);
3925 glBindTexture(GL_TEXTURE_2D, texture);
3927 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3928 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
3929 checkGLcall("Specifying the PBO test texture\n");
3931 GL_EXTCALL(glGenBuffersARB(1, &pbo));
3932 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
3933 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
3934 checkGLcall("Specifying the PBO test pbo\n");
3936 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3937 checkGLcall("Loading the PBO test texture\n");
3939 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
3940 glFinish(); /* just to be sure */
3942 memset(check, 0, sizeof(check));
3943 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
3944 checkGLcall("Reading back the PBO test texture\n");
3946 glDeleteTextures(1, &texture);
3947 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
3948 checkGLcall("PBO test cleanup\n");
3952 if(memcmp(check, pattern, sizeof(check)) != 0) {
3953 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
3954 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
3955 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
3957 TRACE_(d3d_caps)("PBO test successful\n");
3961 /* Certain applications(Steam) complain if we report an outdated driver version. In general,
3962 * reporting a driver version is moot because we are not the Windows driver, and we have different
3963 * bugs, features, etc.
3965 * If a card is not found in this table, the gl driver version is reported
3967 struct driver_version_information {
3968 WORD vendor; /* reported PCI card vendor ID */
3969 WORD card; /* reported PCI card device ID */
3970 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
3971 WORD hipart_hi, hipart_lo; /* driver hiword to report */
3972 WORD lopart_hi, lopart_lo; /* driver loword to report */
3975 static const struct driver_version_information driver_version_table[] = {
3976 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
3977 * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown
3978 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
3979 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
3981 * All version numbers used below are from the Linux nvidia drivers.
3983 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 },
3984 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 },
3985 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 },
3986 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 },
3987 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 },
3988 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 4, 3 },
3989 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 4, 3 },
3990 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 4, 3 },
3991 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7341 },
3992 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7341 },
3993 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7341 },
3994 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8044 },
3995 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8044 },
3996 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8044 },
3997 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8044 },
3998 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8044 },
3999 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8044 },
4000 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8044 },
4001 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8044 },
4002 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8044 },
4003 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8044 },
4004 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8044 },
4005 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8044 },
4006 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8044 },
4007 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8044 },
4008 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8044 },
4009 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8044 },
4010 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8044 },
4011 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8044 },
4012 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8044 },
4014 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
4015 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 },
4016 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 },
4017 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 },
4018 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 },
4019 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 },
4020 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 },
4021 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 },
4023 /* TODO: Add information about legacy ATI hardware, Intel and other cards */
4026 static BOOL match_ati_r300_to_500(const WineD3D_GL_Info *gl_info) {
4027 if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
4028 if(gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
4029 if(gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
4030 if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
4034 static BOOL match_geforce5(const WineD3D_GL_Info *gl_info) {
4035 if(gl_info->gl_vendor == VENDOR_NVIDIA) {
4036 if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
4043 static BOOL match_apple_intel(const WineD3D_GL_Info *gl_info) {
4044 return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info);
4047 static BOOL match_apple_nonr500ati(const WineD3D_GL_Info *gl_info) {
4048 if(!match_apple(gl_info)) return FALSE;
4049 if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
4050 if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
4054 static BOOL match_fglrx(const WineD3D_GL_Info *gl_info) {
4055 if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
4056 if(match_apple(gl_info)) return FALSE;
4057 if(strstr(gl_info->gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers */
4061 static void quirk_arb_constants(WineD3D_GL_Info *gl_info) {
4062 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL\n", gl_info->vs_arb_constantsF);
4063 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
4064 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL\n", gl_info->ps_arb_constantsF);
4065 gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
4068 static void quirk_apple_glsl_constants(WineD3D_GL_Info *gl_info) {
4069 quirk_arb_constants(gl_info);
4070 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
4071 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
4072 * allow 48 different offsets or other helper immediate values
4074 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use\n");
4075 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
4078 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
4079 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
4080 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
4081 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
4082 * most games, but avoids the crash
4084 * A more sophisticated way would be to find all units that need texture coordinates and enable
4085 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
4086 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
4088 * Note that disabling the extension entirely does not gain predictability because there is no point
4089 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension.
4091 static void quirk_one_point_sprite(WineD3D_GL_Info *gl_info) {
4092 if(gl_info->supported[ARB_POINT_SPRITE]) {
4093 TRACE("Limiting point sprites to one texture unit\n");
4094 gl_info->max_point_sprite_units = 1;
4098 static void quirk_ati_dx9(WineD3D_GL_Info *gl_info) {
4099 quirk_arb_constants(gl_info);
4101 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
4102 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
4103 * If real NP2 textures are used, the driver falls back to software. We could just remove the
4104 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
4105 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
4106 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
4107 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
4109 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
4110 * has this extension promoted to core. The extension loading code sets this extension supported
4111 * due to that, so this code works on fglrx as well.
4113 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
4114 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
4115 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
4117 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
4118 * it is generally more efficient. Reserve just 8 constants
4120 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use\n");
4121 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
4124 static void quirk_no_np2(WineD3D_GL_Info *gl_info) {
4125 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
4126 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
4127 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
4128 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
4129 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
4130 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
4132 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
4133 * triggering the software fallback. There is not much we can do here apart from disabling the
4134 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
4135 * in IWineD3DImpl_FillGLCaps).
4136 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
4137 * post-processing effects in the game "Max Payne 2").
4138 * The behaviour can be verified through a simple test app attached in bugreport #14724.
4140 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
4141 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
4142 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
4145 static void quirk_texcoord_w(WineD3D_GL_Info *gl_info) {
4146 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
4147 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
4148 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
4149 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
4150 * according to the spec.
4152 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
4153 * makes the shader slower and eats instruction slots which should be available to the d3d app.
4155 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
4156 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
4157 * this workaround is activated on cards that do not need it, it won't break things, just affect
4158 * performance negatively.
4160 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
4161 gl_info->set_texcoord_w = TRUE;
4164 struct driver_quirk quirk_table[] = {
4166 match_ati_r300_to_500,
4168 "ATI GLSL constant and normalized texrect quirk"
4170 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
4171 * used it falls back to software. While the compiler can detect if the shader uses all declared
4172 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
4173 * using relative addressing falls back to software.
4175 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
4179 quirk_apple_glsl_constants,
4180 "Apple GLSL uniform override"
4185 "Geforce 5 NP2 disable"
4190 "Init texcoord .w for Apple Intel GPU driver"
4193 match_apple_nonr500ati,
4195 "Init texcoord .w for Apple ATI >= r600 GPU driver"
4199 quirk_one_point_sprite,
4200 "Fglrx point sprite crash workaround"
4204 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
4207 for(i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); i++) {
4208 if(!quirk_table[i].match(gl_info)) continue;
4209 TRACE_(d3d_caps)("Applying driver quirk \"%s\"\n", quirk_table[i].description);
4210 quirk_table[i].apply(gl_info);
4213 /* Find out if PBOs work as they are supposed to */
4214 test_pbo_functionality(gl_info);
4216 /* Fixup the driver version */
4217 for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
4218 if(gl_info->gl_vendor == driver_version_table[i].vendor &&
4219 gl_info->gl_card == driver_version_table[i].card) {
4220 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
4222 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
4223 driver_version_table[i].lopart_lo);
4224 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
4225 driver_version_table[i].hipart_lo);
4226 strcpy(gl_info->driver_description, driver_version_table[i].description);
4232 static void WINE_GLAPI invalid_func(const void *data)
4234 ERR("Invalid vertex attribute function called\n");
4238 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4240 ERR("Invalid texcoord function called\n");
4244 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4245 * the extension detection and are used in drawStridedSlow
4247 static void WINE_GLAPI position_d3dcolor(const void *data)
4249 DWORD pos = *((const DWORD *)data);
4251 FIXME("Add a test for fixed function position from d3dcolor type\n");
4252 glVertex4s(D3DCOLOR_B_R(pos),
4258 static void WINE_GLAPI position_float4(const void *data)
4260 const GLfloat *pos = data;
4262 if (pos[3] < eps && pos[3] > -eps)
4265 float w = 1.0 / pos[3];
4267 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4271 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4273 DWORD diffuseColor = *((const DWORD *)data);
4275 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4276 D3DCOLOR_B_G(diffuseColor),
4277 D3DCOLOR_B_B(diffuseColor),
4278 D3DCOLOR_B_A(diffuseColor));
4281 static void WINE_GLAPI specular_d3dcolor(const void *data)
4283 DWORD specularColor = *((const DWORD *)data);
4284 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4285 D3DCOLOR_B_G(specularColor),
4286 D3DCOLOR_B_B(specularColor)};
4288 specular_func_3ubv(d);
4291 static void WINE_GLAPI warn_no_specular_func(const void *data)
4293 WARN("GL_EXT_secondary_color not supported\n");
4296 static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
4298 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4299 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4300 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4301 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4302 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4303 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4304 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4305 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4306 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4307 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4308 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4309 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4310 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4311 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4312 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4313 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4314 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4316 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4317 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4318 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4319 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4320 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4321 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4322 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4323 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4324 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4325 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4326 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4327 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4328 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4329 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4330 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4331 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4332 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4334 /* No 4 component entry points here */
4335 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4336 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4337 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4338 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4340 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4342 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4343 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4344 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4345 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4347 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4349 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4350 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4351 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4352 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4353 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4354 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4355 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4356 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4357 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4358 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4359 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4360 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4362 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4363 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4365 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4366 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4367 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4368 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4369 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4370 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4371 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4372 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4373 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4374 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4375 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4376 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4377 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4378 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4379 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4380 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4381 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4383 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4384 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4385 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4386 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4387 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4388 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4389 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4390 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4391 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4392 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4393 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4394 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4395 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4396 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4397 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4398 if (GL_SUPPORT(NV_HALF_FLOAT))
4400 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4401 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4402 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4404 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4405 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4409 BOOL InitAdapters(IWineD3DImpl *This)
4411 static HMODULE mod_gl;
4413 int ps_selected_mode, vs_selected_mode;
4415 /* No need to hold any lock. The calling library makes sure only one thread calls
4416 * wined3d simultaneously
4419 TRACE("Initializing adapters\n");
4422 #ifdef USE_WIN32_OPENGL
4423 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4424 mod_gl = LoadLibraryA("opengl32.dll");
4426 ERR("Can't load opengl32.dll!\n");
4430 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4431 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4432 mod_gl = GetModuleHandleA("gdi32.dll");
4436 /* Load WGL core functions from opengl32.dll */
4437 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4441 if(!pwglGetProcAddress) {
4442 ERR("Unable to load wglGetProcAddress!\n");
4446 /* Dynamically load all GL core functions */
4450 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4451 * otherwise because we have to use winex11.drv's override
4453 #ifdef USE_WIN32_OPENGL
4454 glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4455 glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4457 glFinish = (void*)pwglGetProcAddress("wglFinish");
4458 glFlush = (void*)pwglGetProcAddress("wglFlush");
4461 glEnableWINE = glEnable;
4462 glDisableWINE = glDisable;
4464 /* For now only one default adapter */
4466 struct WineD3DAdapter *adapter = &This->adapters[0];
4467 const WineD3D_GL_Info *gl_info = &adapter->gl_info;
4471 WineD3D_PixelFormat *cfgs;
4472 DISPLAY_DEVICEW DisplayDevice;
4475 TRACE("Initializing default adapter\n");
4477 adapter->monitorPoint.x = -1;
4478 adapter->monitorPoint.y = -1;
4480 if (!WineD3D_CreateFakeGLContext()) {
4481 ERR("Failed to get a gl context for default adapter\n");
4482 WineD3D_ReleaseFakeGLContext();
4486 ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
4488 ERR("Failed to initialize gl caps for default adapter\n");
4489 WineD3D_ReleaseFakeGLContext();
4492 ret = initPixelFormats(&adapter->gl_info);
4494 ERR("Failed to init gl formats\n");
4495 WineD3D_ReleaseFakeGLContext();
4499 hdc = pwglGetCurrentDC();
4501 ERR("Failed to get gl HDC\n");
4502 WineD3D_ReleaseFakeGLContext();
4506 adapter->driver = "Display";
4507 adapter->description = "Direct3D HAL";
4509 /* Use the VideoRamSize registry setting when set */
4510 if(wined3d_settings.emulated_textureram)
4511 adapter->TextureRam = wined3d_settings.emulated_textureram;
4513 adapter->TextureRam = adapter->gl_info.vidmem;
4514 adapter->UsedTextureRam = 0;
4515 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4517 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4518 DisplayDevice.cb = sizeof(DisplayDevice);
4519 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4520 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4521 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4523 if(GL_SUPPORT(WGL_ARB_PIXEL_FORMAT))
4530 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4531 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4533 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4534 cfgs = adapter->cfgs;
4535 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4536 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4537 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4538 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4539 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4540 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4541 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4542 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4543 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4544 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4546 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4548 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4553 /* Cache the pixel format */
4554 cfgs->iPixelFormat = iPixelFormat;
4555 cfgs->redSize = values[0];
4556 cfgs->greenSize = values[1];
4557 cfgs->blueSize = values[2];
4558 cfgs->alphaSize = values[3];
4559 cfgs->depthSize = values[4];
4560 cfgs->stencilSize = values[5];
4561 cfgs->windowDrawable = values[6];
4562 cfgs->iPixelType = values[7];
4563 cfgs->doubleBuffer = values[8];
4564 cfgs->auxBuffers = values[9];
4566 cfgs->pbufferDrawable = FALSE;
4567 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4568 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4569 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4571 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4572 cfgs->pbufferDrawable = value;
4575 cfgs->numSamples = 0;
4576 /* Check multisample support */
4577 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4578 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4580 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4581 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4582 * value[1] = number of multi sample buffers*/
4584 cfgs->numSamples = value[1];
4588 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);
4594 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4595 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4596 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4598 cfgs = adapter->cfgs;
4599 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4601 PIXELFORMATDESCRIPTOR ppfd;
4603 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4607 /* We only want HW acceleration using an OpenGL ICD driver.
4608 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4609 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4611 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4613 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4617 cfgs->iPixelFormat = iPixelFormat;
4618 cfgs->redSize = ppfd.cRedBits;
4619 cfgs->greenSize = ppfd.cGreenBits;
4620 cfgs->blueSize = ppfd.cBlueBits;
4621 cfgs->alphaSize = ppfd.cAlphaBits;
4622 cfgs->depthSize = ppfd.cDepthBits;
4623 cfgs->stencilSize = ppfd.cStencilBits;
4624 cfgs->pbufferDrawable = 0;
4625 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4626 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4627 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4628 cfgs->auxBuffers = ppfd.cAuxBuffers;
4629 cfgs->numSamples = 0;
4631 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);
4636 /* Yikes we haven't found any suitable formats. This should only happen in case of GDI software rendering which we can't use anyway as its 3D functionality is very, very limited */
4639 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4641 WineD3D_ReleaseFakeGLContext();
4642 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4647 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4648 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4649 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4650 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4651 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4652 * driver is allowed to consume more bits EXCEPT for stencil bits.
4654 * Mark an adapter with this broken stencil behavior.
4656 adapter->brokenStencil = TRUE;
4657 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4659 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4660 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4661 adapter->brokenStencil = FALSE;
4666 fixup_extensions(&adapter->gl_info);
4667 add_gl_compat_wrappers(&adapter->gl_info);
4669 WineD3D_ReleaseFakeGLContext();
4671 select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4672 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
4673 fillGLAttribFuncs(&adapter->gl_info);
4674 adapter->opengl = TRUE;
4676 This->adapter_count = 1;
4677 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4682 /* Initialize an adapter for ddraw-only memory counting */
4683 memset(This->adapters, 0, sizeof(This->adapters));
4684 This->adapters[0].num = 0;
4685 This->adapters[0].opengl = FALSE;
4686 This->adapters[0].monitorPoint.x = -1;
4687 This->adapters[0].monitorPoint.y = -1;
4689 This->adapters[0].driver = "Display";
4690 This->adapters[0].description = "WineD3D DirectDraw Emulation";
4691 if(wined3d_settings.emulated_textureram) {
4692 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4694 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4697 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4699 This->adapter_count = 1;
4703 /**********************************************************
4704 * IWineD3D VTbl follows
4705 **********************************************************/
4707 const IWineD3DVtbl IWineD3D_Vtbl =
4710 IWineD3DImpl_QueryInterface,
4711 IWineD3DImpl_AddRef,
4712 IWineD3DImpl_Release,
4714 IWineD3DImpl_GetParent,
4715 IWineD3DImpl_GetAdapterCount,
4716 IWineD3DImpl_RegisterSoftwareDevice,
4717 IWineD3DImpl_GetAdapterMonitor,
4718 IWineD3DImpl_GetAdapterModeCount,
4719 IWineD3DImpl_EnumAdapterModes,
4720 IWineD3DImpl_GetAdapterDisplayMode,
4721 IWineD3DImpl_GetAdapterIdentifier,
4722 IWineD3DImpl_CheckDeviceMultiSampleType,
4723 IWineD3DImpl_CheckDepthStencilMatch,
4724 IWineD3DImpl_CheckDeviceType,
4725 IWineD3DImpl_CheckDeviceFormat,
4726 IWineD3DImpl_CheckDeviceFormatConversion,
4727 IWineD3DImpl_GetDeviceCaps,
4728 IWineD3DImpl_CreateDevice