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
9 * Copyright 2009 Henri Verbeet for CodeWeavers
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
33 #define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024)
35 /* The d3d device ID */
36 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
38 /* Extension detection */
40 const char *extension_string;
41 GL_SupportedExt extension;
45 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
46 {"GL_APPLE_fence", APPLE_FENCE, 0 },
47 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
48 {"GL_APPLE_flush_buffer_range", APPLE_FLUSH_BUFFER_RANGE, 0 },
49 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
50 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
53 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
54 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
55 {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP, 0 },
56 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
57 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
58 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
59 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
60 {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT, 0 },
61 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
62 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
63 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
64 {"GL_ARB_imaging", ARB_IMAGING, 0 },
65 {"GL_ARB_map_buffer_range", ARB_MAP_BUFFER_RANGE, 0 },
66 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
67 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
68 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
69 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
70 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
71 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
72 {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX, 0 },
73 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
74 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
75 {"GL_ARB_shading_language_100", ARB_SHADING_LANGUAGE_100, 0 },
76 {"GL_ARB_shadow", ARB_SHADOW, 0 },
77 {"GL_ARB_sync", ARB_SYNC, 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_array_bgra", ARB_VERTEX_ARRAY_BGRA, 0 },
90 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
91 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
92 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
93 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
96 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
97 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
98 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
99 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
100 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
103 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
104 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
105 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
106 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
107 {"GL_EXT_draw_buffers2", EXT_DRAW_BUFFERS2, 0 },
108 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
109 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
110 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
111 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
112 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
113 {"GL_EXT_gpu_shader4", EXT_GPU_SHADER4, 0 },
114 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
115 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
116 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
117 {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 },
118 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
119 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
120 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
121 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
122 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
123 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
124 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
125 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
126 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
127 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
128 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
129 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
130 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
133 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
134 {"GL_NV_fence", NV_FENCE, 0 },
135 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
136 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
137 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
138 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
139 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
140 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
141 {"GL_NV_point_sprite", NV_POINT_SPRITE, 0 },
142 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
143 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
144 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
145 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
146 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
147 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
148 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
149 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
150 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
151 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
152 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
155 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
158 /**********************************************************
159 * Utility functions follow
160 **********************************************************/
162 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
164 const struct min_lookup minMipLookup[] =
166 /* NONE POINT LINEAR */
167 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
168 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
169 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
172 const struct min_lookup minMipLookup_noFilter[] =
174 /* NONE POINT LINEAR */
175 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
176 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
177 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
180 const struct min_lookup minMipLookup_noMip[] =
182 /* NONE POINT LINEAR */
183 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
184 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
185 {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */
188 const GLenum magLookup[] =
190 /* NONE POINT LINEAR */
191 GL_NEAREST, GL_NEAREST, GL_LINEAR,
194 const GLenum magLookup_noFilter[] =
196 /* NONE POINT LINEAR */
197 GL_NEAREST, GL_NEAREST, GL_NEAREST,
200 /* drawStridedSlow attributes */
201 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
202 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
203 glAttribFunc specular_func_3ubv;
204 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
205 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
206 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
209 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
210 * i.e., there is no GL Context - Get a default rendering context to enable the
211 * function query some info from GL.
214 struct wined3d_fake_gl_ctx
220 HGLRC restore_gl_ctx;
223 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
225 TRACE_(d3d_caps)("Destroying fake GL context.\n");
227 if (!pwglMakeCurrent(NULL, NULL))
229 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
232 if (!pwglDeleteContext(ctx->gl_ctx))
234 DWORD err = GetLastError();
235 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
238 ReleaseDC(ctx->wnd, ctx->dc);
239 DestroyWindow(ctx->wnd);
241 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
243 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
247 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
249 PIXELFORMATDESCRIPTOR pfd;
252 TRACE("getting context...\n");
254 ctx->restore_dc = pwglGetCurrentDC();
255 ctx->restore_gl_ctx = pwglGetCurrentContext();
257 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
258 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
259 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
262 ERR_(d3d_caps)("Failed to create a window.\n");
266 ctx->dc = GetDC(ctx->wnd);
269 ERR_(d3d_caps)("Failed to get a DC.\n");
273 /* PixelFormat selection */
274 ZeroMemory(&pfd, sizeof(pfd));
275 pfd.nSize = sizeof(pfd);
277 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
278 pfd.iPixelType = PFD_TYPE_RGBA;
280 pfd.iLayerType = PFD_MAIN_PLANE;
282 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
285 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
286 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
289 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
290 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
292 /* Create a GL context. */
293 ctx->gl_ctx = pwglCreateContext(ctx->dc);
296 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
300 /* Make it the current GL context. */
301 if (!context_set_current(NULL))
303 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
306 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
308 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
315 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
317 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
319 if (ctx->wnd) DestroyWindow(ctx->wnd);
321 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
323 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
329 /* Adjust the amount of used texture memory */
330 unsigned int WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *device, unsigned int glram)
332 struct wined3d_adapter *adapter = device->adapter;
334 adapter->UsedTextureRam += glram;
335 TRACE("Adjusted gl ram by %d to %d\n", glram, adapter->UsedTextureRam);
336 return adapter->UsedTextureRam;
339 static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
341 HeapFree(GetProcessHeap(), 0, adapter->gl_info.gl_formats);
342 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
345 /**********************************************************
346 * IUnknown parts follows
347 **********************************************************/
349 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
353 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
354 if (IsEqualGUID(riid, &IID_IUnknown)
355 || IsEqualGUID(riid, &IID_IWineD3DBase)
356 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
357 IUnknown_AddRef(iface);
362 return E_NOINTERFACE;
365 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
366 IWineD3DImpl *This = (IWineD3DImpl *)iface;
367 ULONG refCount = InterlockedIncrement(&This->ref);
369 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
373 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
374 IWineD3DImpl *This = (IWineD3DImpl *)iface;
376 TRACE("(%p) : Releasing from %d\n", This, This->ref);
377 ref = InterlockedDecrement(&This->ref);
381 for (i = 0; i < This->adapter_count; ++i)
383 wined3d_adapter_cleanup(&This->adapters[i]);
385 HeapFree(GetProcessHeap(), 0, This);
391 /**********************************************************
392 * IWineD3D parts follows
393 **********************************************************/
395 /* GL locking is done by the caller */
396 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
400 const char *testcode =
402 "PARAM C[66] = { program.env[0..65] };\n"
404 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
405 "ARL A0.x, zero.x;\n"
406 "MOV result.position, C[A0.x + 65];\n"
410 GL_EXTCALL(glGenProgramsARB(1, &prog));
412 ERR("Failed to create an ARB offset limit test program\n");
414 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
415 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
416 strlen(testcode), testcode));
417 if(glGetError() != 0) {
418 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
419 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
421 } else TRACE("OpenGL implementation allows offsets > 63\n");
423 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
424 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
425 checkGLcall("ARB vp offset limit test cleanup");
430 static DWORD ver_for_ext(GL_SupportedExt ext)
433 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
434 if(EXTENSION_MAP[i].extension == ext) {
435 return EXTENSION_MAP[i].version;
441 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
442 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
444 if (card_vendor != HW_VENDOR_ATI) return FALSE;
445 if (device == CARD_ATI_RADEON_9500) return TRUE;
446 if (device == CARD_ATI_RADEON_X700) return TRUE;
447 if (device == CARD_ATI_RADEON_X1600) return TRUE;
451 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
452 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
454 if (card_vendor == HW_VENDOR_NVIDIA)
456 if (device == CARD_NVIDIA_GEFORCEFX_5200 ||
457 device == CARD_NVIDIA_GEFORCEFX_5600 ||
458 device == CARD_NVIDIA_GEFORCEFX_5800)
466 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
467 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
469 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
470 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
471 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
473 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
474 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
475 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
476 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
477 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
478 * the chance that other implementations support them is rather small since Win32 QuickTime uses
479 * DirectDraw, not OpenGL.
481 * This test has been moved into wined3d_guess_gl_vendor()
483 if (gl_vendor == GL_VENDOR_APPLE)
490 /* Context activation is done by the caller. */
491 static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
493 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
494 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
495 * all the texture. This function detects this bug by its symptom and disables PBOs
498 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
499 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
500 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
501 * read back is compared to the original. If they are equal PBOs are assumed to work,
502 * otherwise the PBO extension is disabled. */
504 static const unsigned int pattern[] =
506 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
507 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
508 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
509 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
511 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
513 /* No PBO -> No point in testing them. */
514 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
518 while (glGetError());
519 glGenTextures(1, &texture);
520 glBindTexture(GL_TEXTURE_2D, texture);
522 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
523 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
524 checkGLcall("Specifying the PBO test texture");
526 GL_EXTCALL(glGenBuffersARB(1, &pbo));
527 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
528 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
529 checkGLcall("Specifying the PBO test pbo");
531 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
532 checkGLcall("Loading the PBO test texture");
534 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
537 wglFinish(); /* just to be sure */
539 memset(check, 0, sizeof(check));
541 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
542 checkGLcall("Reading back the PBO test texture");
544 glDeleteTextures(1, &texture);
545 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
546 checkGLcall("PBO test cleanup");
550 if (memcmp(check, pattern, sizeof(check)))
552 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
553 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
554 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
558 TRACE_(d3d_caps)("PBO test successful.\n");
562 static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
563 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
565 return (card_vendor == HW_VENDOR_INTEL) && (gl_vendor == GL_VENDOR_APPLE);
568 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
569 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
571 if (gl_vendor != GL_VENDOR_APPLE) return FALSE;
572 if (card_vendor != HW_VENDOR_ATI) return FALSE;
573 if (device == CARD_ATI_RADEON_X1600) return FALSE;
577 static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
578 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
580 return gl_vendor == GL_VENDOR_FGLRX;
584 static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
585 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
587 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
588 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
589 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
590 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
593 * dx10 cards usually have 64 varyings */
594 return gl_info->limits.glsl_varyings > 44;
597 /* A GL context is provided by the caller */
598 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
599 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
604 if (!gl_info->supported[EXT_SECONDARY_COLOR]) return FALSE;
608 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
609 error = glGetError();
612 if(error == GL_NO_ERROR)
614 TRACE("GL Implementation accepts 4 component specular color pointers\n");
619 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
620 debug_glerror(error));
625 static BOOL match_apple_nvts(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
626 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
628 if (!match_apple(gl_info, gl_renderer, gl_vendor, card_vendor, device)) return FALSE;
629 return gl_info->supported[NV_TEXTURE_SHADER];
632 /* A GL context is provided by the caller */
633 static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
634 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
639 const char *testcode =
641 "OPTION NV_vertex_program2;\n"
642 "MOV result.clip[0], 0.0;\n"
643 "MOV result.position, 0.0;\n"
646 if (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]) return FALSE;
651 GL_EXTCALL(glGenProgramsARB(1, &prog));
654 ERR("Failed to create the NVvp clip test program\n");
658 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
659 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
660 strlen(testcode), testcode));
661 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
664 WARN("GL_NV_vertex_program2_option result.clip[] test failed\n");
665 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
669 else TRACE("GL_NV_vertex_program2_option result.clip[] test passed\n");
671 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
672 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
673 checkGLcall("GL_NV_vertex_program2_option result.clip[] test cleanup");
679 /* Context activation is done by the caller. */
680 static BOOL match_fbo_tex_update(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
681 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
683 char data[4 * 4 * 4];
687 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return FALSE;
689 memset(data, 0xcc, sizeof(data));
693 glGenTextures(1, &tex);
694 glBindTexture(GL_TEXTURE_2D, tex);
695 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
696 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
697 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
698 checkGLcall("glTexImage2D");
700 gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
701 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
702 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
703 checkGLcall("glFramebufferTexture2D");
705 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
706 if (status != GL_FRAMEBUFFER_COMPLETE) ERR("FBO status %#x\n", status);
707 checkGLcall("glCheckFramebufferStatus");
709 memset(data, 0x11, sizeof(data));
710 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
711 checkGLcall("glTexSubImage2D");
713 glClearColor(0.996, 0.729, 0.745, 0.792);
714 glClear(GL_COLOR_BUFFER_BIT);
715 checkGLcall("glClear");
717 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
718 checkGLcall("glGetTexImage");
720 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
721 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
722 glBindTexture(GL_TEXTURE_2D, 0);
723 checkGLcall("glBindTexture");
725 gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
726 glDeleteTextures(1, &tex);
727 checkGLcall("glDeleteTextures");
731 return *(DWORD *)data == 0x11111111;
734 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
736 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->limits.arb_vs_native_constants);
737 gl_info->limits.glsl_vs_float_constants = gl_info->limits.arb_vs_native_constants;
738 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->limits.arb_ps_native_constants);
739 gl_info->limits.glsl_ps_float_constants = gl_info->limits.arb_ps_native_constants;
742 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
744 quirk_arb_constants(gl_info);
745 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
746 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
747 * allow 48 different offsets or other helper immediate values. */
748 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
749 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
752 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
753 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
754 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
755 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
756 * most games, but avoids the crash
758 * A more sophisticated way would be to find all units that need texture coordinates and enable
759 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
760 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
762 * Note that disabling the extension entirely does not gain predictability because there is no point
763 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
764 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
766 if (gl_info->supported[ARB_POINT_SPRITE])
768 TRACE("Limiting point sprites to one texture unit.\n");
769 gl_info->limits.point_sprite_units = 1;
773 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
775 quirk_arb_constants(gl_info);
777 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
778 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
779 * If real NP2 textures are used, the driver falls back to software. We could just remove the
780 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
781 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
782 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
783 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
785 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
786 * has this extension promoted to core. The extension loading code sets this extension supported
787 * due to that, so this code works on fglrx as well. */
788 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
790 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
791 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
792 gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT] = TRUE;
795 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
796 * it is generally more efficient. Reserve just 8 constants. */
797 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
798 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
801 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
803 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
804 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
805 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
806 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
807 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
808 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
810 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
811 * triggering the software fallback. There is not much we can do here apart from disabling the
812 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
813 * in IWineD3DImpl_FillGLCaps).
814 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
815 * post-processing effects in the game "Max Payne 2").
816 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
817 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
818 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
819 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
822 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
824 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
825 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
826 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
827 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
828 * according to the spec.
830 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
831 * makes the shader slower and eats instruction slots which should be available to the d3d app.
833 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
834 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
835 * this workaround is activated on cards that do not need it, it won't break things, just affect
836 * performance negatively. */
837 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
838 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
841 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
843 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
846 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
848 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
851 static void quirk_apple_nvts(struct wined3d_gl_info *gl_info)
853 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
854 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
857 static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info)
859 gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN;
862 static void quirk_fbo_tex_update(struct wined3d_gl_info *gl_info)
864 gl_info->quirks |= WINED3D_QUIRK_FBO_TEX_UPDATE;
869 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
870 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device);
871 void (*apply)(struct wined3d_gl_info *gl_info);
872 const char *description;
875 static const struct driver_quirk quirk_table[] =
878 match_ati_r300_to_500,
880 "ATI GLSL constant and normalized texrect quirk"
882 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
883 * used it falls back to software. While the compiler can detect if the shader uses all declared
884 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
885 * using relative addressing falls back to software.
887 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
890 quirk_apple_glsl_constants,
891 "Apple GLSL uniform override"
896 "Geforce 5 NP2 disable"
901 "Init texcoord .w for Apple Intel GPU driver"
904 match_apple_nonr500ati,
906 "Init texcoord .w for Apple ATI >= r600 GPU driver"
910 quirk_one_point_sprite,
911 "Fglrx point sprite crash workaround"
916 "Reserved varying for gl_ClipPos"
919 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
920 * GL implementations accept it. The Mac GL is the only implementation known to
923 * If we can pass 4 component specular colors, do it, because (a) we don't have
924 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
925 * passes specular alpha to the pixel shader if any is used. Otherwise the
926 * specular alpha is used to pass the fog coordinate, which we pass to opengl
927 * via GL_EXT_fog_coord.
929 match_allows_spec_alpha,
930 quirk_allows_specular_alpha,
931 "Allow specular alpha quirk"
934 /* The pixel formats provided by GL_NV_texture_shader are broken on OSX
939 "Apple NV_texture_shader disable"
942 match_broken_nv_clip,
943 quirk_disable_nvvp_clip,
944 "Apple NV_vertex_program clip bug quirk"
947 match_fbo_tex_update,
948 quirk_fbo_tex_update,
949 "FBO rebind for attachment updates"
953 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
954 * reporting a driver version is moot because we are not the Windows driver, and we have different
955 * bugs, features, etc.
957 * The driver version has the form "x.y.z.w".
959 * "x" is the Windows version the driver is meant for:
966 * "y" is the Direct3D level the driver supports:
973 * "z" is unknown, possibly vendor specific.
975 * "w" is the vendor specific driver version.
977 struct driver_version_information
979 WORD vendor; /* reported PCI card vendor ID */
980 WORD card; /* reported PCI card device ID */
981 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
982 WORD d3d_level; /* driver hiword to report */
983 WORD lopart_hi, lopart_lo; /* driver loword to report */
986 static const struct driver_version_information driver_version_table[] =
988 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
989 * 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
990 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
991 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
993 * All version numbers used below are from the Linux nvidia drivers. */
994 {HW_VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 1, 8, 6 },
995 {HW_VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 1, 8, 6 },
996 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 1, 8, 6 },
997 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 6, 4, 3 },
998 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 1, 8, 6 },
999 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 6, 10, 9371 },
1000 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 6, 10, 9371 },
1001 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 6, 10, 9371 },
1002 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 15, 11, 7516 },
1003 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 15, 11, 7516 },
1004 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 15, 11, 7516 },
1005 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 15, 11, 9745 },
1006 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 15, 11, 9745 },
1007 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 15, 11, 9745 },
1008 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 15, 11, 9745 },
1009 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 15, 11, 9745 },
1010 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 15, 11, 9745 },
1011 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 15, 11, 9745 },
1012 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 15, 11, 9745 },
1013 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8400GS, "NVIDIA GeForce 8400 GS", 15, 11, 9745 },
1014 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 15, 11, 9745 },
1015 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 15, 11, 9745 },
1016 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 15, 11, 9745 },
1017 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 15, 11, 9745 },
1018 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 15, 11, 9745 },
1019 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 15, 11, 9745 },
1020 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 15, 11, 9745 },
1021 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 15, 11, 9745 },
1022 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_210, "NVIDIA GeForce 210", 15, 11, 9745 },
1023 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GT220, "NVIDIA GeForce GT 220", 15, 11, 9745 },
1024 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GT240, "NVIDIA GeForce GT 240", 15, 11, 9745 },
1025 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 15, 11, 9745 },
1026 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 15, 11, 9745 },
1027 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 15, 11, 9745 },
1028 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GT325M, "NVIDIA GeForce GT 325M", 15, 11, 9745 },
1029 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTS350M, "NVIDIA GeForce GTS 350M", 15, 11, 9745 },
1030 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX470, "NVIDIA GeForce GTX 470", 15, 11, 9775 },
1031 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX480, "NVIDIA GeForce GTX 480", 15, 11, 9775 },
1032 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
1033 {HW_VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 14, 10, 6764 },
1034 {HW_VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 14, 10, 6764 },
1035 {HW_VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 14, 10, 6764 },
1036 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2350, "ATI Mobility Radeon HD 2350", 14, 10, 6764 },
1037 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 14, 10, 6764 },
1038 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 14, 10, 6764 },
1039 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 14, 10, 6764 },
1040 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 14, 10, 6764 },
1041 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 14, 10, 6764 },
1042 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 14, 10, 6764 },
1043 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD5700, "ATI Radeon HD 5700 Series", 14, 10, 8681 },
1044 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD5800, "ATI Radeon HD 5800 Series", 14, 10, 8681 },
1046 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
1049 static void init_driver_info(struct wined3d_driver_info *driver_info,
1050 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
1052 OSVERSIONINFOW os_version;
1053 WORD driver_os_version;
1056 if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1058 TRACE_(d3d_caps)("Overriding PCI vendor ID with: %04x\n", wined3d_settings.pci_vendor_id);
1059 vendor = wined3d_settings.pci_vendor_id;
1061 driver_info->vendor = vendor;
1063 if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1065 TRACE_(d3d_caps)("Overriding PCI device ID with: %04x\n", wined3d_settings.pci_device_id);
1066 device = wined3d_settings.pci_device_id;
1068 driver_info->device = device;
1073 driver_info->name = "ati2dvag.dll";
1076 case HW_VENDOR_NVIDIA:
1077 driver_info->name = "nv4_disp.dll";
1080 case HW_VENDOR_INTEL:
1082 FIXME_(d3d_caps)("Unhandled vendor %04x.\n", vendor);
1083 driver_info->name = "Display";
1087 memset(&os_version, 0, sizeof(os_version));
1088 os_version.dwOSVersionInfoSize = sizeof(os_version);
1089 if (!GetVersionExW(&os_version))
1091 ERR("Failed to get OS version, reporting 2000/XP.\n");
1092 driver_os_version = 6;
1096 TRACE("OS version %u.%u.\n", os_version.dwMajorVersion, os_version.dwMinorVersion);
1097 switch (os_version.dwMajorVersion)
1100 driver_os_version = 4;
1104 driver_os_version = 6;
1108 if (os_version.dwMinorVersion == 0)
1110 driver_os_version = 7;
1114 if (os_version.dwMinorVersion > 1)
1116 FIXME("Unhandled OS version %u.%u, reporting Win 7.\n",
1117 os_version.dwMajorVersion, os_version.dwMinorVersion);
1119 driver_os_version = 8;
1124 FIXME("Unhandled OS version %u.%u, reporting 2000/XP.\n",
1125 os_version.dwMajorVersion, os_version.dwMinorVersion);
1126 driver_os_version = 6;
1131 driver_info->description = "Direct3D HAL";
1132 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
1133 driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
1135 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
1137 if (vendor == driver_version_table[i].vendor && device == driver_version_table[i].card)
1139 TRACE_(d3d_caps)("Found card %04x:%04x in driver DB.\n", vendor, device);
1141 driver_info->description = driver_version_table[i].description;
1142 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, driver_version_table[i].d3d_level);
1143 driver_info->version_low = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
1144 driver_version_table[i].lopart_lo);
1149 TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08x-0x%08x.\n",
1150 driver_info->version_high, driver_info->version_low);
1153 /* Context activation is done by the caller. */
1154 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer,
1155 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
1159 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
1161 if (!quirk_table[i].match(gl_info, gl_renderer, gl_vendor, card_vendor, device)) continue;
1162 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
1163 quirk_table[i].apply(gl_info);
1166 /* Find out if PBOs work as they are supposed to. */
1167 test_pbo_functionality(gl_info);
1170 static DWORD wined3d_parse_gl_version(const char *gl_version)
1172 const char *ptr = gl_version;
1176 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
1178 while (isdigit(*ptr)) ++ptr;
1179 if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version));
1183 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
1185 return MAKEDWORD_VERSION(major, minor);
1188 static enum wined3d_gl_vendor wined3d_guess_gl_vendor(struct wined3d_gl_info *gl_info, const char *gl_vendor_string, const char *gl_renderer)
1191 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
1192 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
1193 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
1195 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
1196 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
1197 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
1198 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
1199 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
1200 * the chance that other implementations support them is rather small since Win32 QuickTime uses
1201 * DirectDraw, not OpenGL. */
1202 if (gl_info->supported[APPLE_FENCE]
1203 && gl_info->supported[APPLE_CLIENT_STORAGE]
1204 && gl_info->supported[APPLE_FLUSH_RENDER]
1205 && gl_info->supported[APPLE_YCBCR_422])
1206 return GL_VENDOR_APPLE;
1208 if (strstr(gl_vendor_string, "NVIDIA"))
1209 return GL_VENDOR_NVIDIA;
1211 if (strstr(gl_vendor_string, "ATI"))
1212 return GL_VENDOR_FGLRX;
1214 if (strstr(gl_vendor_string, "Intel(R)")
1215 /* Intel switched from Intel(R) to Intel® recently, so just match Intel. */
1216 || strstr(gl_renderer, "Intel")
1217 || strstr(gl_vendor_string, "Intel Inc."))
1218 return GL_VENDOR_INTEL;
1220 if (strstr(gl_vendor_string, "Mesa")
1221 || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
1222 || strstr(gl_vendor_string, "DRI R300 Project")
1223 || strstr(gl_vendor_string, "X.Org R300 Project")
1224 || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
1225 || strstr(gl_vendor_string, "VMware, Inc.")
1226 || strstr(gl_renderer, "Mesa")
1227 || strstr(gl_renderer, "Gallium"))
1228 return GL_VENDOR_MESA;
1230 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning GL_VENDOR_UNKNOWN.\n",
1231 debugstr_a(gl_vendor_string));
1233 return GL_VENDOR_UNKNOWN;
1236 static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_string, const char *gl_renderer)
1238 if (strstr(gl_vendor_string, "NVIDIA"))
1239 return HW_VENDOR_NVIDIA;
1241 if (strstr(gl_vendor_string, "ATI")
1242 || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
1243 || strstr(gl_vendor_string, "X.Org R300 Project")
1244 || strstr(gl_vendor_string, "DRI R300 Project"))
1245 return HW_VENDOR_ATI;
1247 if (strstr(gl_vendor_string, "Intel(R)")
1248 /* Intel switched from Intel(R) to Intel® recently, so just match Intel. */
1249 || strstr(gl_renderer, "Intel")
1250 || strstr(gl_vendor_string, "Intel Inc."))
1251 return HW_VENDOR_INTEL;
1253 if (strstr(gl_vendor_string, "Mesa")
1254 || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
1255 || strstr(gl_vendor_string, "VMware, Inc."))
1256 return HW_VENDOR_SOFTWARE;
1258 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning HW_VENDOR_NVIDIA.\n", debugstr_a(gl_vendor_string));
1260 return HW_VENDOR_NVIDIA;
1265 static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info,
1266 const char *gl_renderer, unsigned int *vidmem)
1268 if (WINE_D3D10_CAPABLE(gl_info))
1270 /* Geforce 400 - highend */
1271 if (strstr(gl_renderer, "GTX 480"))
1274 return CARD_NVIDIA_GEFORCE_GTX480;
1277 /* Geforce 400 - midend high */
1278 if (strstr(gl_renderer, "GTX 470"))
1281 return CARD_NVIDIA_GEFORCE_GTX470;
1284 /* Geforce 300 highend mobile */
1285 if (strstr(gl_renderer, "GTS 350M")
1286 || strstr(gl_renderer, "GTS 360M"))
1289 return CARD_NVIDIA_GEFORCE_GTS350M;
1292 /* Geforce 300 midend mobile (Geforce GT 325M/330M use the same core) */
1293 if (strstr(gl_renderer, "GT 325M")
1294 || strstr(gl_renderer, "GT 330M"))
1297 return CARD_NVIDIA_GEFORCE_GT325M;
1300 /* Geforce 200 - highend */
1301 if (strstr(gl_renderer, "GTX 280")
1302 || strstr(gl_renderer, "GTX 285")
1303 || strstr(gl_renderer, "GTX 295"))
1306 return CARD_NVIDIA_GEFORCE_GTX280;
1309 /* Geforce 200 - midend high */
1310 if (strstr(gl_renderer, "GTX 275"))
1313 return CARD_NVIDIA_GEFORCE_GTX275;
1316 /* Geforce 200 - midend */
1317 if (strstr(gl_renderer, "GTX 260"))
1320 return CARD_NVIDIA_GEFORCE_GTX260;
1322 /* Geforce 200 - midend */
1323 if (strstr(gl_renderer, "GT 240"))
1326 return CARD_NVIDIA_GEFORCE_GT240;
1329 /* Geforce 200 lowend */
1330 if (strstr(gl_renderer, "GT 220"))
1332 *vidmem = 512; /* The GT 220 has 512-1024MB */
1333 return CARD_NVIDIA_GEFORCE_GT220;
1335 /* Geforce 200 lowend (Geforce 305/310 use the same core) */
1336 if (strstr(gl_renderer, "Geforce 210")
1337 || strstr(gl_renderer, "G 210")
1338 || strstr(gl_renderer, "Geforce 305")
1339 || strstr(gl_renderer, "Geforce 310"))
1342 return CARD_NVIDIA_GEFORCE_210;
1345 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1346 if (strstr(gl_renderer, "9800")
1347 || strstr(gl_renderer, "GTS 150")
1348 || strstr(gl_renderer, "GTS 250"))
1351 return CARD_NVIDIA_GEFORCE_9800GT;
1354 /* Geforce9 - midend (GT 140 uses the same core as the 9600GT) */
1355 if (strstr(gl_renderer, "9600")
1356 || strstr(gl_renderer, "GT 140"))
1358 *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1359 return CARD_NVIDIA_GEFORCE_9600GT;
1362 /* Geforce9 - midend low / Geforce 200 - low */
1363 if (strstr(gl_renderer, "9500")
1364 || strstr(gl_renderer, "GT 120")
1365 || strstr(gl_renderer, "GT 130"))
1367 *vidmem = 256; /* The 9500GT has 256-1024MB */
1368 return CARD_NVIDIA_GEFORCE_9500GT;
1371 /* Geforce9 - lowend */
1372 if (strstr(gl_renderer, "9400"))
1374 *vidmem = 256; /* The 9400GT has 256-1024MB */
1375 return CARD_NVIDIA_GEFORCE_9400GT;
1378 /* Geforce9 - lowend low */
1379 if (strstr(gl_renderer, "9100")
1380 || strstr(gl_renderer, "9200")
1381 || strstr(gl_renderer, "9300")
1382 || strstr(gl_renderer, "G 100"))
1384 *vidmem = 256; /* The 9100-9300 cards have 256MB */
1385 return CARD_NVIDIA_GEFORCE_9200;
1388 /* Geforce8 - highend */
1389 if (strstr(gl_renderer, "8800"))
1391 *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1392 return CARD_NVIDIA_GEFORCE_8800GTS;
1395 /* Geforce8 - midend mobile */
1396 if (strstr(gl_renderer, "8600 M"))
1399 return CARD_NVIDIA_GEFORCE_8600MGT;
1402 /* Geforce8 - midend */
1403 if (strstr(gl_renderer, "8600")
1404 || strstr(gl_renderer, "8700"))
1407 return CARD_NVIDIA_GEFORCE_8600GT;
1410 /* Geforce8 - mid-lowend */
1411 if (strstr(gl_renderer, "8400")
1412 || strstr(gl_renderer, "8500"))
1414 *vidmem = 128; /* 128-256MB for a 8400, 256-512MB for a 8500 */
1415 return CARD_NVIDIA_GEFORCE_8400GS;
1418 /* Geforce8 - lowend */
1419 if (strstr(gl_renderer, "8100")
1420 || strstr(gl_renderer, "8200")
1421 || strstr(gl_renderer, "8300"))
1423 *vidmem = 128; /* 128-256MB for a 8300 */
1424 return CARD_NVIDIA_GEFORCE_8300GS;
1427 /* Geforce8-compatible fall back if the GPU is not in the list yet */
1429 return CARD_NVIDIA_GEFORCE_8300GS;
1432 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1433 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1435 if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3])
1437 /* Geforce7 - highend */
1438 if (strstr(gl_renderer, "7800")
1439 || strstr(gl_renderer, "7900")
1440 || strstr(gl_renderer, "7950")
1441 || strstr(gl_renderer, "Quadro FX 4")
1442 || strstr(gl_renderer, "Quadro FX 5"))
1444 *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1445 return CARD_NVIDIA_GEFORCE_7800GT;
1448 /* Geforce7 midend */
1449 if (strstr(gl_renderer, "7600")
1450 || strstr(gl_renderer, "7700"))
1452 *vidmem = 256; /* The 7600 uses 256-512MB */
1453 return CARD_NVIDIA_GEFORCE_7600;
1456 /* Geforce7 lower medium */
1457 if (strstr(gl_renderer, "7400"))
1459 *vidmem = 256; /* The 7400 uses 256-512MB */
1460 return CARD_NVIDIA_GEFORCE_7400;
1463 /* Geforce7 lowend */
1464 if (strstr(gl_renderer, "7300"))
1466 *vidmem = 256; /* Mac Pros with this card have 256 MB */
1467 return CARD_NVIDIA_GEFORCE_7300;
1470 /* Geforce6 highend */
1471 if (strstr(gl_renderer, "6800"))
1473 *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1474 return CARD_NVIDIA_GEFORCE_6800;
1477 /* Geforce6 - midend */
1478 if (strstr(gl_renderer, "6600")
1479 || strstr(gl_renderer, "6610")
1480 || strstr(gl_renderer, "6700"))
1482 *vidmem = 128; /* A 6600GT has 128-256MB */
1483 return CARD_NVIDIA_GEFORCE_6600GT;
1486 /* Geforce6/7 lowend */
1488 return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1491 if (WINE_D3D9_CAPABLE(gl_info))
1493 /* GeforceFX - highend */
1494 if (strstr(gl_renderer, "5800")
1495 || strstr(gl_renderer, "5900")
1496 || strstr(gl_renderer, "5950")
1497 || strstr(gl_renderer, "Quadro FX"))
1499 *vidmem = 256; /* 5800-5900 cards use 256MB */
1500 return CARD_NVIDIA_GEFORCEFX_5800;
1503 /* GeforceFX - midend */
1504 if (strstr(gl_renderer, "5600")
1505 || strstr(gl_renderer, "5650")
1506 || strstr(gl_renderer, "5700")
1507 || strstr(gl_renderer, "5750"))
1509 *vidmem = 128; /* A 5600 uses 128-256MB */
1510 return CARD_NVIDIA_GEFORCEFX_5600;
1513 /* GeforceFX - lowend */
1514 *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1515 return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1518 if (WINE_D3D8_CAPABLE(gl_info))
1520 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1522 *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1523 return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1526 *vidmem = 64; /* Geforce3 cards have 64-128MB */
1527 return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1530 if (WINE_D3D7_CAPABLE(gl_info))
1532 if (strstr(gl_renderer, "GeForce4 MX"))
1534 /* Most Geforce4MX GPUs have at least 64MB of memory, some
1535 * early models had 32MB but most have 64MB or even 128MB. */
1537 return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1540 if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1542 *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1543 return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1546 if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1548 *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1549 return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1552 /* Most Geforce1 cards have 32MB, there are also some rare 16
1553 * and 64MB (Dell) models. */
1555 return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1558 if (strstr(gl_renderer, "TNT2"))
1560 *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1561 return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1564 *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1565 return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1569 static enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_info,
1570 const char *gl_renderer, unsigned int *vidmem)
1572 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1574 * Beware: renderer string do not match exact card model,
1575 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1576 if (WINE_D3D10_CAPABLE(gl_info))
1578 /* Radeon EG CYPRESS XT / PRO HD5800 - highend */
1579 if (strstr(gl_renderer, "HD 5800") /* Radeon EG CYPRESS HD58xx generic renderer string */
1580 || strstr(gl_renderer, "HD 5850") /* Radeon EG CYPRESS XT */
1581 || strstr(gl_renderer, "HD 5870")) /* Radeon EG CYPRESS PRO */
1583 *vidmem = 1024; /* note: HD58xx cards use 1024MB */
1584 return CARD_ATI_RADEON_HD5800;
1587 /* Radeon EG JUNIPER XT / LE HD5700 - midend */
1588 if (strstr(gl_renderer, "HD 5700") /* Radeon EG JUNIPER HD57xx generic renderer string */
1589 || strstr(gl_renderer, "HD 5750") /* Radeon EG JUNIPER LE */
1590 || strstr(gl_renderer, "HD 5770")) /* Radeon EG JUNIPER XT */
1592 *vidmem = 512; /* note: HD5770 cards use 1024MB and HD5750 cards use 512MB or 1024MB */
1593 return CARD_ATI_RADEON_HD5700;
1596 /* Radeon R7xx HD4800 - highend */
1597 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1598 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1599 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1600 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1601 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1603 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1604 return CARD_ATI_RADEON_HD4800;
1607 /* Radeon R740 HD4700 - midend */
1608 if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1609 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1612 return CARD_ATI_RADEON_HD4700;
1615 /* Radeon R730 HD4600 - midend */
1616 if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1617 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1618 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1621 return CARD_ATI_RADEON_HD4600;
1624 /* Radeon R710 HD4500/HD4350 - lowend */
1625 if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1626 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1629 return CARD_ATI_RADEON_HD4350;
1632 /* Radeon R6xx HD2900/HD3800 - highend */
1633 if (strstr(gl_renderer, "HD 2900")
1634 || strstr(gl_renderer, "HD 3870")
1635 || strstr(gl_renderer, "HD 3850"))
1637 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1638 return CARD_ATI_RADEON_HD2900;
1641 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1642 if (strstr(gl_renderer, "HD 2600")
1643 || strstr(gl_renderer, "HD 3830")
1644 || strstr(gl_renderer, "HD 3690")
1645 || strstr(gl_renderer, "HD 3650"))
1647 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1648 return CARD_ATI_RADEON_HD2600;
1651 /* Radeon R6xx HD2350/HD2400/HD3400 - lowend
1652 * Note HD2300=DX9, HD2350=DX10 */
1653 if (strstr(gl_renderer, "HD 2350")
1654 || strstr(gl_renderer, "HD 2400")
1655 || strstr(gl_renderer, "HD 3470")
1656 || strstr(gl_renderer, "HD 3450")
1657 || strstr(gl_renderer, "HD 3430")
1658 || strstr(gl_renderer, "HD 3400"))
1660 *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */
1661 return CARD_ATI_RADEON_HD2350;
1664 /* Radeon R6xx/R7xx integrated */
1665 if (strstr(gl_renderer, "HD 3100")
1666 || strstr(gl_renderer, "HD 3200")
1667 || strstr(gl_renderer, "HD 3300"))
1669 *vidmem = 128; /* 128MB */
1670 return CARD_ATI_RADEON_HD3200;
1673 /* Default for when no GPU has been found */
1674 *vidmem = 128; /* 128MB */
1675 return CARD_ATI_RADEON_HD3200;
1678 if (WINE_D3D8_CAPABLE(gl_info))
1681 if (strstr(gl_renderer, "X1600")
1682 || strstr(gl_renderer, "X1650")
1683 || strstr(gl_renderer, "X1800")
1684 || strstr(gl_renderer, "X1900")
1685 || strstr(gl_renderer, "X1950"))
1687 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1688 return CARD_ATI_RADEON_X1600;
1691 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx)
1692 * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */
1693 if (strstr(gl_renderer, "X700")
1694 || strstr(gl_renderer, "X800")
1695 || strstr(gl_renderer, "X850")
1696 || strstr(gl_renderer, "X1300")
1697 || strstr(gl_renderer, "X1400")
1698 || strstr(gl_renderer, "X1450")
1699 || strstr(gl_renderer, "X1550")
1700 || strstr(gl_renderer, "X2300")
1701 || strstr(gl_renderer, "X2500")
1702 || strstr(gl_renderer, "HD 2300")
1705 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1706 return CARD_ATI_RADEON_X700;
1709 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1710 if (strstr(gl_renderer, "Radeon Xpress"))
1712 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1713 return CARD_ATI_RADEON_XPRESS_200M;
1717 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1718 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1721 if (WINE_D3D8_CAPABLE(gl_info))
1723 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1724 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1727 if (WINE_D3D7_CAPABLE(gl_info))
1729 *vidmem = 32; /* There are models with up to 64MB */
1730 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1733 *vidmem = 16; /* There are 16-32MB models */
1734 return CARD_ATI_RAGE_128PRO;
1738 static enum wined3d_pci_device select_card_intel_binary(const struct wined3d_gl_info *gl_info,
1739 const char *gl_renderer, unsigned int *vidmem)
1741 if (strstr(gl_renderer, "X3100"))
1743 /* MacOS calls the card GMA X3100, otherwise known as GM965/GL960 */
1745 return CARD_INTEL_X3100;
1748 if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1750 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1752 return CARD_INTEL_I945GM;
1755 if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM;
1756 if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G;
1757 if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G;
1758 if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G;
1759 if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G;
1760 return CARD_INTEL_I915G;
1764 static enum wined3d_pci_device select_card_ati_mesa(const struct wined3d_gl_info *gl_info,
1765 const char *gl_renderer, unsigned int *vidmem)
1767 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1769 * Beware: renderer string do not match exact card model,
1770 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1771 if (strstr(gl_renderer, "Gallium"))
1773 /* Radeon R7xx HD4800 - highend */
1774 if (strstr(gl_renderer, "R700") /* Radeon R7xx HD48xx generic renderer string */
1775 || strstr(gl_renderer, "RV770") /* Radeon RV770 */
1776 || strstr(gl_renderer, "RV790")) /* Radeon RV790 */
1778 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1779 return CARD_ATI_RADEON_HD4800;
1782 /* Radeon R740 HD4700 - midend */
1783 if (strstr(gl_renderer, "RV740")) /* Radeon RV740 */
1786 return CARD_ATI_RADEON_HD4700;
1789 /* Radeon R730 HD4600 - midend */
1790 if (strstr(gl_renderer, "RV730")) /* Radeon RV730 */
1793 return CARD_ATI_RADEON_HD4600;
1796 /* Radeon R710 HD4500/HD4350 - lowend */
1797 if (strstr(gl_renderer, "RV710")) /* Radeon RV710 */
1800 return CARD_ATI_RADEON_HD4350;
1803 /* Radeon R6xx HD2900/HD3800 - highend */
1804 if (strstr(gl_renderer, "R600")
1805 || strstr(gl_renderer, "RV670")
1806 || strstr(gl_renderer, "R680"))
1808 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1809 return CARD_ATI_RADEON_HD2900;
1812 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1813 if (strstr(gl_renderer, "RV630")
1814 || strstr(gl_renderer, "RV635"))
1816 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1817 return CARD_ATI_RADEON_HD2600;
1820 /* Radeon R6xx HD2350/HD2400/HD3400 - lowend */
1821 if (strstr(gl_renderer, "RV610")
1822 || strstr(gl_renderer, "RV620"))
1824 *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */
1825 return CARD_ATI_RADEON_HD2350;
1828 /* Radeon R6xx/R7xx integrated */
1829 if (strstr(gl_renderer, "RS780")
1830 || strstr(gl_renderer, "RS880"))
1832 *vidmem = 128; /* 128MB */
1833 return CARD_ATI_RADEON_HD3200;
1837 if (strstr(gl_renderer, "RV530")
1838 || strstr(gl_renderer, "RV535")
1839 || strstr(gl_renderer, "RV560")
1840 || strstr(gl_renderer, "R520")
1841 || strstr(gl_renderer, "RV570")
1842 || strstr(gl_renderer, "R580"))
1844 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1845 return CARD_ATI_RADEON_X1600;
1848 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1849 if (strstr(gl_renderer, "R410")
1850 || strstr(gl_renderer, "R420")
1851 || strstr(gl_renderer, "R423")
1852 || strstr(gl_renderer, "R430")
1853 || strstr(gl_renderer, "R480")
1854 || strstr(gl_renderer, "R481")
1855 || strstr(gl_renderer, "RV410")
1856 || strstr(gl_renderer, "RV515")
1857 || strstr(gl_renderer, "RV516"))
1859 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1860 return CARD_ATI_RADEON_X700;
1863 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1864 if (strstr(gl_renderer, "RS400")
1865 || strstr(gl_renderer, "RS480")
1866 || strstr(gl_renderer, "RS482")
1867 || strstr(gl_renderer, "RS485")
1868 || strstr(gl_renderer, "RS600")
1869 || strstr(gl_renderer, "RS690")
1870 || strstr(gl_renderer, "RS740"))
1872 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1873 return CARD_ATI_RADEON_XPRESS_200M;
1877 if (strstr(gl_renderer, "R300")
1878 || strstr(gl_renderer, "RV350")
1879 || strstr(gl_renderer, "RV351")
1880 || strstr(gl_renderer, "RV360")
1881 || strstr(gl_renderer, "RV370")
1882 || strstr(gl_renderer, "R350")
1883 || strstr(gl_renderer, "R360"))
1885 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1886 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1890 if (WINE_D3D9_CAPABLE(gl_info))
1892 /* Radeon R7xx HD4800 - highend */
1893 if (strstr(gl_renderer, "(R700") /* Radeon R7xx HD48xx generic renderer string */
1894 || strstr(gl_renderer, "(RV770") /* Radeon RV770 */
1895 || strstr(gl_renderer, "(RV790")) /* Radeon RV790 */
1897 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1898 return CARD_ATI_RADEON_HD4800;
1901 /* Radeon R740 HD4700 - midend */
1902 if (strstr(gl_renderer, "(RV740")) /* Radeon RV740 */
1905 return CARD_ATI_RADEON_HD4700;
1908 /* Radeon R730 HD4600 - midend */
1909 if (strstr(gl_renderer, "(RV730")) /* Radeon RV730 */
1912 return CARD_ATI_RADEON_HD4600;
1915 /* Radeon R710 HD4500/HD4350 - lowend */
1916 if (strstr(gl_renderer, "(RV710")) /* Radeon RV710 */
1919 return CARD_ATI_RADEON_HD4350;
1922 /* Radeon R6xx HD2900/HD3800 - highend */
1923 if (strstr(gl_renderer, "(R600")
1924 || strstr(gl_renderer, "(RV670")
1925 || strstr(gl_renderer, "(R680"))
1927 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1928 return CARD_ATI_RADEON_HD2900;
1931 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1932 if (strstr(gl_renderer, "(RV630")
1933 || strstr(gl_renderer, "(RV635"))
1935 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1936 return CARD_ATI_RADEON_HD2600;
1939 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1940 if (strstr(gl_renderer, "(RV610")
1941 || strstr(gl_renderer, "(RV620"))
1943 *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */
1944 return CARD_ATI_RADEON_HD2350;
1947 /* Radeon R6xx/R7xx integrated */
1948 if (strstr(gl_renderer, "(RS780")
1949 || strstr(gl_renderer, "(RS880"))
1951 *vidmem = 128; /* 128MB */
1952 return CARD_ATI_RADEON_HD3200;
1956 if (WINE_D3D8_CAPABLE(gl_info))
1958 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1959 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1962 if (WINE_D3D7_CAPABLE(gl_info))
1964 *vidmem = 32; /* There are models with up to 64MB */
1965 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1968 *vidmem = 16; /* There are 16-32MB models */
1969 return CARD_ATI_RAGE_128PRO;
1973 static enum wined3d_pci_device select_card_nvidia_mesa(const struct wined3d_gl_info *gl_info,
1974 const char *gl_renderer, unsigned int *vidmem)
1976 FIXME_(d3d_caps)("Card selection not handled for Mesa Nouveau driver\n");
1977 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1978 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1979 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1980 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
1981 return CARD_NVIDIA_RIVA_128;
1984 static enum wined3d_pci_device select_card_intel_mesa(const struct wined3d_gl_info *gl_info,
1985 const char *gl_renderer, unsigned int *vidmem)
1987 FIXME_(d3d_caps)("Card selection not handled for Mesa Intel driver\n");
1988 return CARD_INTEL_I915G;
1992 struct vendor_card_selection
1994 enum wined3d_gl_vendor gl_vendor;
1995 enum wined3d_pci_vendor card_vendor;
1996 const char *description; /* Description of the card selector i.e. Apple OS/X Intel */
1997 enum wined3d_pci_device (*select_card)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1998 unsigned int *vidmem );
2001 static const struct vendor_card_selection vendor_card_select_table[] =
2003 {GL_VENDOR_NVIDIA, HW_VENDOR_NVIDIA, "Nvidia binary driver", select_card_nvidia_binary},
2004 {GL_VENDOR_APPLE, HW_VENDOR_NVIDIA, "Apple OSX NVidia binary driver", select_card_nvidia_binary},
2005 {GL_VENDOR_APPLE, HW_VENDOR_ATI, "Apple OSX AMD/ATI binary driver", select_card_ati_binary},
2006 {GL_VENDOR_APPLE, HW_VENDOR_INTEL, "Apple OSX Intel binary driver", select_card_intel_binary},
2007 {GL_VENDOR_FGLRX, HW_VENDOR_ATI, "AMD/ATI binary driver", select_card_ati_binary},
2008 {GL_VENDOR_MESA, HW_VENDOR_ATI, "Mesa AMD/ATI driver", select_card_ati_mesa},
2009 {GL_VENDOR_MESA, HW_VENDOR_NVIDIA, "Mesa Nouveau driver", select_card_nvidia_mesa},
2010 {GL_VENDOR_MESA, HW_VENDOR_INTEL, "Mesa Intel driver", select_card_intel_mesa},
2011 {GL_VENDOR_INTEL, HW_VENDOR_INTEL, "Mesa Intel driver", select_card_intel_mesa}
2015 static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
2016 enum wined3d_gl_vendor *gl_vendor, enum wined3d_pci_vendor *card_vendor, unsigned int *vidmem)
2018 /* Above is a list of Nvidia and ATI GPUs. Both vendors have dozens of
2019 * different GPUs with roughly the same features. In most cases GPUs from a
2020 * certain family differ in clockspeeds, the amount of video memory and the
2021 * number of shader pipelines.
2023 * A Direct3D device object contains the PCI id (vendor + device) of the
2024 * videocard which is used for rendering. Various applications use this
2025 * information to get a rough estimation of the features of the card and
2026 * some might use it for enabling 3d effects only on certain types of
2027 * videocards. In some cases games might even use it to work around bugs
2028 * which happen on certain videocards/driver combinations. The problem is
2029 * that OpenGL only exposes a rendering string containing the name of the
2030 * videocard and not the PCI id.
2032 * Various games depend on the PCI id, so somehow we need to provide one.
2033 * A simple option is to parse the renderer string and translate this to
2034 * the right PCI id. This is a lot of work because there are more than 200
2035 * GPUs just for Nvidia. Various cards share the same renderer string, so
2036 * the amount of code might be 'small' but there are quite a number of
2037 * exceptions which would make this a pain to maintain. Another way would
2038 * be to query the PCI id from the operating system (assuming this is the
2039 * videocard which is used for rendering which is not always the case).
2040 * This would work but it is not very portable. Second it would not work
2041 * well in, let's say, a remote X situation in which the amount of 3d
2042 * features which can be used is limited.
2044 * As said most games only use the PCI id to get an indication of the
2045 * capabilities of the card. It doesn't really matter if the given id is
2046 * the correct one if we return the id of a card with similar 3d features.
2048 * The code below checks the OpenGL capabilities of a videocard and matches
2049 * that to a certain level of Direct3D functionality. Once a card passes
2050 * the Direct3D9 check, we know that the card (in case of Nvidia) is at
2051 * least a GeforceFX. To give a better estimate we do a basic check on the
2052 * renderer string but if that won't pass we return a default card. This
2053 * way is better than maintaining a full card database as even without a
2054 * full database we can return a card with similar features. Second the
2055 * size of the database can be made quite small because when you know what
2056 * type of 3d functionality a card has, you know to which GPU family the
2057 * GPU must belong. Because of this you only have to check a small part of
2058 * the renderer string to distinguishes between different models from that
2061 * The code also selects a default amount of video memory which we will
2062 * use for an estimation of the amount of free texture memory. In case of
2063 * real D3D the amount of texture memory includes video memory and system
2064 * memory (to be specific AGP memory or in case of PCIE TurboCache /
2065 * HyperMemory). We don't know how much system memory can be addressed by
2066 * the system but we can make a reasonable estimation about the amount of
2067 * video memory. If the value is slightly wrong it doesn't matter as we
2068 * didn't include AGP-like memory which makes the amount of addressable
2069 * memory higher and second OpenGL isn't that critical it moves to system
2070 * memory behind our backs if really needed. Note that the amount of video
2071 * memory can be overruled using a registry setting. */
2075 for (i = 0; i < (sizeof(vendor_card_select_table) / sizeof(*vendor_card_select_table)); ++i)
2077 if ((vendor_card_select_table[i].gl_vendor != *gl_vendor)
2078 || (vendor_card_select_table[i].card_vendor != *card_vendor))
2080 TRACE_(d3d_caps)("Applying card_selector \"%s\".\n", vendor_card_select_table[i].description);
2081 return vendor_card_select_table[i].select_card(gl_info, gl_renderer, vidmem);
2084 FIXME_(d3d_caps)("No card selector available for GL vendor %d and card vendor %04x.\n",
2085 *gl_vendor, *card_vendor);
2087 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
2088 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
2089 * them a good generic choice. */
2090 *card_vendor = HW_VENDOR_NVIDIA;
2091 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
2092 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
2093 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
2094 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
2095 return CARD_NVIDIA_RIVA_128;
2098 static const struct fragment_pipeline *select_fragment_implementation(struct wined3d_adapter *adapter)
2100 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2101 int vs_selected_mode, ps_selected_mode;
2103 select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode);
2104 if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL)
2105 && gl_info->supported[ARB_FRAGMENT_PROGRAM]) return &arbfp_fragment_pipeline;
2106 else if (ps_selected_mode == SHADER_ATI) return &atifs_fragment_pipeline;
2107 else if (gl_info->supported[NV_REGISTER_COMBINERS]
2108 && gl_info->supported[NV_TEXTURE_SHADER2]) return &nvts_fragment_pipeline;
2109 else if (gl_info->supported[NV_REGISTER_COMBINERS]) return &nvrc_fragment_pipeline;
2110 else return &ffp_fragment_pipeline;
2113 static const shader_backend_t *select_shader_backend(struct wined3d_adapter *adapter)
2115 int vs_selected_mode, ps_selected_mode;
2117 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
2118 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) return &glsl_shader_backend;
2119 if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) return &arb_program_shader_backend;
2120 return &none_shader_backend;
2123 static const struct blit_shader *select_blit_implementation(struct wined3d_adapter *adapter)
2125 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2126 int vs_selected_mode, ps_selected_mode;
2128 select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode);
2129 if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL)
2130 && gl_info->supported[ARB_FRAGMENT_PROGRAM]) return &arbfp_blit;
2131 else return &ffp_blit;
2134 /* Context activation is done by the caller. */
2135 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_adapter *adapter)
2137 struct wined3d_driver_info *driver_info = &adapter->driver_info;
2138 struct wined3d_gl_info *gl_info = &adapter->gl_info;
2139 const char *GL_Extensions = NULL;
2140 const char *WGL_Extensions = NULL;
2141 const char *gl_vendor_str, *gl_renderer_str, *gl_version_str;
2142 struct fragment_caps fragment_caps;
2143 enum wined3d_gl_vendor gl_vendor;
2144 enum wined3d_pci_vendor card_vendor;
2145 enum wined3d_pci_device device;
2147 GLfloat gl_floatv[2];
2150 unsigned int vidmem=0;
2154 TRACE_(d3d_caps)("(%p)\n", gl_info);
2158 gl_renderer_str = (const char *)glGetString(GL_RENDERER);
2159 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_renderer_str));
2160 if (!gl_renderer_str)
2163 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
2167 gl_vendor_str = (const char *)glGetString(GL_VENDOR);
2168 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_vendor_str));
2172 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
2176 /* Parse the GL_VERSION field into major and minor information */
2177 gl_version_str = (const char *)glGetString(GL_VERSION);
2178 TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_version_str));
2179 if (!gl_version_str)
2182 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
2185 gl_version = wined3d_parse_gl_version(gl_version_str);
2188 * Initialize openGL extension related variables
2189 * with Default values
2191 memset(gl_info->supported, 0, sizeof(gl_info->supported));
2192 gl_info->limits.blends = 1;
2193 gl_info->limits.buffers = 1;
2194 gl_info->limits.textures = 1;
2195 gl_info->limits.fragment_samplers = 1;
2196 gl_info->limits.vertex_samplers = 0;
2197 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
2198 gl_info->limits.sampler_stages = 1;
2199 gl_info->limits.glsl_vs_float_constants = 0;
2200 gl_info->limits.glsl_ps_float_constants = 0;
2201 gl_info->limits.arb_vs_float_constants = 0;
2202 gl_info->limits.arb_vs_native_constants = 0;
2203 gl_info->limits.arb_vs_instructions = 0;
2204 gl_info->limits.arb_vs_temps = 0;
2205 gl_info->limits.arb_ps_float_constants = 0;
2206 gl_info->limits.arb_ps_local_constants = 0;
2207 gl_info->limits.arb_ps_instructions = 0;
2208 gl_info->limits.arb_ps_temps = 0;
2210 /* Retrieve opengl defaults */
2211 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
2212 gl_info->limits.clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
2213 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
2215 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
2216 gl_info->limits.lights = gl_max;
2217 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
2219 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
2220 gl_info->limits.texture_size = gl_max;
2221 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
2223 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
2224 gl_info->limits.pointsize_min = gl_floatv[0];
2225 gl_info->limits.pointsize_max = gl_floatv[1];
2226 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
2228 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
2229 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
2233 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
2239 TRACE_(d3d_caps)("GL_Extensions reported:\n");
2241 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
2243 while (*GL_Extensions)
2246 char current_ext[256];
2248 while (isspace(*GL_Extensions)) ++GL_Extensions;
2249 start = GL_Extensions;
2250 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
2252 len = GL_Extensions - start;
2253 if (!len || len >= sizeof(current_ext)) continue;
2255 memcpy(current_ext, start, len);
2256 current_ext[len] = '\0';
2257 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
2259 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
2261 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
2263 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
2264 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
2270 /* Now work out what GL support this card really has */
2271 #define USE_GL_FUNC(type, pfn, ext, replace) \
2273 DWORD ver = ver_for_ext(ext); \
2274 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
2275 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
2276 else gl_info->pfn = NULL; \
2281 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
2287 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
2288 * loading the functions, otherwise the code above will load the extension entry points instead of the
2289 * core functions, which may not work. */
2290 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
2292 if (!gl_info->supported[EXTENSION_MAP[i].extension]
2293 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
2295 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
2296 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
2300 if (gl_version >= MAKEDWORD_VERSION(2, 0)) gl_info->supported[WINED3D_GL_VERSION_2_0] = TRUE;
2302 if (gl_info->supported[APPLE_FENCE])
2304 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
2305 * The apple extension interacts with some other apple exts. Disable the NV
2306 * extension if the apple one is support to prevent confusion in other parts
2308 gl_info->supported[NV_FENCE] = FALSE;
2310 if (gl_info->supported[APPLE_FLOAT_PIXELS])
2312 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
2314 * The enums are the same:
2315 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
2316 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
2317 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
2318 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
2319 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
2321 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
2323 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
2324 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
2326 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
2328 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
2329 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
2332 if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
2334 /* GL_ARB_map_buffer_range and GL_APPLE_flush_buffer_range provide the same
2335 * functionality. Prefer the ARB extension */
2336 gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] = FALSE;
2338 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
2340 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
2341 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
2343 if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
2345 TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
2346 gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
2348 if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && gl_info->supported[EXT_VERTEX_ARRAY_BGRA])
2350 TRACE_(d3d_caps)(" IMPLIED: ARB_vertex_array_bgra support (by EXT_vertex_array_bgra).\n");
2351 gl_info->supported[ARB_VERTEX_ARRAY_BGRA] = TRUE;
2353 if (gl_info->supported[NV_TEXTURE_SHADER2])
2355 if (gl_info->supported[NV_REGISTER_COMBINERS])
2357 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
2358 * are supported. The nv extensions provide the same functionality as the
2359 * ATI one, and a bit more(signed pixelformats). */
2360 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
2364 if (gl_info->supported[NV_REGISTER_COMBINERS])
2366 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
2367 gl_info->limits.general_combiners = gl_max;
2368 TRACE_(d3d_caps)("Max general combiners: %d.\n", gl_max);
2370 if (gl_info->supported[ARB_DRAW_BUFFERS])
2372 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
2373 gl_info->limits.buffers = gl_max;
2374 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
2376 if (gl_info->supported[ARB_MULTITEXTURE])
2378 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
2379 gl_info->limits.textures = min(MAX_TEXTURES, gl_max);
2380 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->limits.textures);
2382 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
2385 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2386 gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
2390 gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, gl_max);
2392 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers);
2394 if (gl_info->supported[ARB_VERTEX_SHADER])
2397 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2398 gl_info->limits.vertex_samplers = tmp;
2399 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2400 gl_info->limits.combined_samplers = tmp;
2402 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
2403 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
2404 * an issue because then the sampler setup only depends on the two shaders. If a pixel
2405 * shader is used with fixed function vertex processing we're fine too because fixed function
2406 * vertex processing doesn't use any samplers. If fixed function fragment processing is
2407 * used we have to make sure that all vertex sampler setups are valid together with all
2408 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
2409 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
2410 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
2411 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
2412 * a fixed function pipeline anymore.
2414 * So this is just a check to check that our assumption holds true. If not, write a warning
2415 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
2416 if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12
2417 && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers)
2419 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
2420 gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers);
2421 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
2422 if (gl_info->limits.combined_samplers > MAX_TEXTURES)
2423 gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES;
2425 gl_info->limits.vertex_samplers = 0;
2430 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers;
2432 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers);
2433 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->limits.combined_samplers);
2435 if (gl_info->supported[ARB_VERTEX_BLEND])
2437 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
2438 gl_info->limits.blends = gl_max;
2439 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->limits.blends);
2441 if (gl_info->supported[EXT_TEXTURE3D])
2443 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
2444 gl_info->limits.texture3d_size = gl_max;
2445 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->limits.texture3d_size);
2447 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
2449 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
2450 gl_info->limits.anisotropy = gl_max;
2451 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->limits.anisotropy);
2453 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
2455 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
2456 gl_info->limits.arb_ps_float_constants = gl_max;
2457 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants);
2458 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
2459 gl_info->limits.arb_ps_native_constants = gl_max;
2460 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n",
2461 gl_info->limits.arb_ps_native_constants);
2462 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
2463 gl_info->limits.arb_ps_temps = gl_max;
2464 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps);
2465 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
2466 gl_info->limits.arb_ps_instructions = gl_max;
2467 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions);
2468 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
2469 gl_info->limits.arb_ps_local_constants = gl_max;
2470 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions);
2472 if (gl_info->supported[ARB_VERTEX_PROGRAM])
2474 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
2475 gl_info->limits.arb_vs_float_constants = gl_max;
2476 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants);
2477 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
2478 gl_info->limits.arb_vs_native_constants = gl_max;
2479 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native float constants: %d.\n",
2480 gl_info->limits.arb_vs_native_constants);
2481 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
2482 gl_info->limits.arb_vs_temps = gl_max;
2483 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps);
2484 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
2485 gl_info->limits.arb_vs_instructions = gl_max;
2486 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions);
2488 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
2490 if (gl_info->supported[ARB_VERTEX_SHADER])
2492 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
2493 gl_info->limits.glsl_vs_float_constants = gl_max / 4;
2494 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
2496 if (gl_info->supported[ARB_FRAGMENT_SHADER])
2498 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
2499 gl_info->limits.glsl_ps_float_constants = gl_max / 4;
2500 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants);
2501 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
2502 gl_info->limits.glsl_varyings = gl_max;
2503 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
2505 if (gl_info->supported[ARB_SHADING_LANGUAGE_100])
2507 const char *str = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
2508 unsigned int major, minor;
2510 TRACE_(d3d_caps)("GLSL version string: %s.\n", debugstr_a(str));
2512 /* The format of the GLSL version string is "major.minor[.release] [vendor info]". */
2513 sscanf(str, "%u.%u", &major, &minor);
2514 gl_info->glsl_version = MAKEDWORD_VERSION(major, minor);
2516 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
2518 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess);
2522 gl_info->limits.shininess = 128.0f;
2524 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
2526 /* If we have full NP2 texture support, disable
2527 * GL_ARB_texture_rectangle because we will never use it.
2528 * This saves a few redundant glDisable calls. */
2529 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
2531 if (gl_info->supported[ATI_FRAGMENT_SHADER])
2533 /* Disable NV_register_combiners and fragment shader if this is supported.
2534 * generally the NV extensions are preferred over the ATI ones, and this
2535 * extension is disabled if register_combiners and texture_shader2 are both
2536 * supported. So we reach this place only if we have incomplete NV dxlevel 8
2537 * fragment processing support. */
2538 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
2539 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
2540 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
2541 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
2543 if (gl_info->supported[NV_HALF_FLOAT])
2545 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
2546 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
2548 if (gl_info->supported[ARB_POINT_SPRITE])
2550 gl_info->limits.point_sprite_units = gl_info->limits.textures;
2554 gl_info->limits.point_sprite_units = 0;
2556 checkGLcall("extension detection");
2560 adapter->fragment_pipe = select_fragment_implementation(adapter);
2561 adapter->shader_backend = select_shader_backend(adapter);
2562 adapter->blitter = select_blit_implementation(adapter);
2564 adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
2565 gl_info->limits.texture_stages = fragment_caps.MaxTextureBlendStages;
2566 TRACE_(d3d_caps)("Max texture stages: %u.\n", gl_info->limits.texture_stages);
2568 /* In some cases the number of texture stages can be larger than the number
2569 * of samplers. The GF4 for example can use only 2 samplers (no fragment
2570 * shaders), but 8 texture stages (register combiners). */
2571 gl_info->limits.sampler_stages = max(gl_info->limits.fragment_samplers, gl_info->limits.texture_stages);
2573 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
2575 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbuffer;
2576 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbuffer;
2577 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffers;
2578 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffers;
2579 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorage;
2580 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisample;
2581 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameteriv;
2582 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebuffer;
2583 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebuffer;
2584 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffers;
2585 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffers;
2586 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatus;
2587 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1D;
2588 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2D;
2589 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3D;
2590 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbuffer;
2591 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameteriv;
2592 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebuffer;
2593 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmap;
2597 if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT])
2599 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbufferEXT;
2600 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbufferEXT;
2601 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffersEXT;
2602 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffersEXT;
2603 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorageEXT;
2604 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameterivEXT;
2605 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebufferEXT;
2606 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebufferEXT;
2607 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffersEXT;
2608 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffersEXT;
2609 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatusEXT;
2610 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1DEXT;
2611 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2DEXT;
2612 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3DEXT;
2613 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbufferEXT;
2614 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameterivEXT;
2615 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmapEXT;
2617 else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2619 WARN_(d3d_caps)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
2620 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
2622 if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
2624 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebufferEXT;
2626 if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
2628 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisampleEXT;
2632 /* MRTs are currently only supported when FBOs are used. */
2633 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
2635 gl_info->limits.buffers = 1;
2638 gl_vendor = wined3d_guess_gl_vendor(gl_info, gl_vendor_str, gl_renderer_str);
2639 card_vendor = wined3d_guess_card_vendor(gl_vendor_str, gl_renderer_str);
2640 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x/0x%04x)\n", debugstr_a(gl_vendor_str), gl_vendor, card_vendor);
2642 device = wined3d_guess_card(gl_info, gl_renderer_str, &gl_vendor, &card_vendor, &vidmem);
2643 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", card_vendor, device);
2645 /* If we have an estimate use it, else default to 64MB; */
2647 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
2649 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
2651 gl_info->wrap_lookup[WINED3DTADDRESS_WRAP - WINED3DTADDRESS_WRAP] = GL_REPEAT;
2652 gl_info->wrap_lookup[WINED3DTADDRESS_MIRROR - WINED3DTADDRESS_WRAP] =
2653 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
2654 gl_info->wrap_lookup[WINED3DTADDRESS_CLAMP - WINED3DTADDRESS_WRAP] = GL_CLAMP_TO_EDGE;
2655 gl_info->wrap_lookup[WINED3DTADDRESS_BORDER - WINED3DTADDRESS_WRAP] =
2656 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2657 gl_info->wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP] =
2658 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
2660 /* Make sure there's an active HDC else the WGL extensions will fail */
2661 hdc = pwglGetCurrentDC();
2663 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2664 if(GL_EXTCALL(wglGetExtensionsStringARB))
2665 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2667 if (NULL == WGL_Extensions) {
2668 ERR(" WGL_Extensions returns NULL\n");
2670 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2671 while (*WGL_Extensions != 0x00) {
2675 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2676 Start = WGL_Extensions;
2677 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2681 len = WGL_Extensions - Start;
2682 if (len == 0 || len >= sizeof(ThisExtn))
2685 memcpy(ThisExtn, Start, len);
2686 ThisExtn[len] = '\0';
2687 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
2689 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2690 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2691 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2693 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2694 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2695 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2701 fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device);
2702 init_driver_info(driver_info, card_vendor, device);
2703 add_gl_compat_wrappers(gl_info);
2708 /**********************************************************
2709 * IWineD3D implementation follows
2710 **********************************************************/
2712 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2713 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2715 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2717 return This->adapter_count;
2720 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void *init_function)
2722 FIXME("iface %p, init_function %p stub!\n", iface, init_function);
2727 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2728 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2730 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2732 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2736 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2739 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2740 of the same bpp but different resolutions */
2742 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2743 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2744 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2745 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2747 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2751 /* TODO: Store modes per adapter and read it from the adapter structure */
2752 if (Adapter == 0) { /* Display */
2753 const struct wined3d_format_desc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2754 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2759 memset(&mode, 0, sizeof(mode));
2760 mode.dmSize = sizeof(mode);
2762 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2766 if (Format == WINED3DFMT_UNKNOWN)
2768 /* This is for D3D8, do not enumerate P8 here */
2769 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2771 else if (mode.dmBitsPerPel == format_bits)
2777 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2780 FIXME_(d3d_caps)("Adapter not primary display\n");
2785 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2786 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2787 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2788 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2790 /* Validate the parameters as much as possible */
2791 if (NULL == pMode ||
2792 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2793 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2794 return WINED3DERR_INVALIDCALL;
2797 /* TODO: Store modes per adapter and read it from the adapter structure */
2800 const struct wined3d_format_desc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2801 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2807 ZeroMemory(&DevModeW, sizeof(DevModeW));
2808 DevModeW.dmSize = sizeof(DevModeW);
2810 /* If we are filtering to a specific format (D3D9), then need to skip
2811 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2812 just count through the ones with valid bit depths */
2813 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0))
2815 if (Format == WINED3DFMT_UNKNOWN)
2817 /* This is for D3D8, do not enumerate P8 here */
2818 if (DevModeW.dmBitsPerPel == 32 || DevModeW.dmBitsPerPel == 16) ++i;
2820 else if (DevModeW.dmBitsPerPel == format_bits)
2827 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2828 return WINED3DERR_INVALIDCALL;
2832 /* Now get the display mode via the calculated index */
2833 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2834 pMode->Width = DevModeW.dmPelsWidth;
2835 pMode->Height = DevModeW.dmPelsHeight;
2836 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2837 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2838 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2840 if (Format == WINED3DFMT_UNKNOWN) {
2841 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2843 pMode->Format = Format;
2846 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2847 return WINED3DERR_INVALIDCALL;
2850 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2851 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2852 DevModeW.dmBitsPerPel);
2857 FIXME_(d3d_caps)("Adapter not primary display\n");
2863 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE *pMode)
2865 TRACE("iface %p, adapter_idx %u, display_mode %p.\n", iface, Adapter, pMode);
2867 if (NULL == pMode ||
2868 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2869 return WINED3DERR_INVALIDCALL;
2872 if (Adapter == 0) { /* Display */
2876 ZeroMemory(&DevModeW, sizeof(DevModeW));
2877 DevModeW.dmSize = sizeof(DevModeW);
2879 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2880 pMode->Width = DevModeW.dmPelsWidth;
2881 pMode->Height = DevModeW.dmPelsHeight;
2882 bpp = DevModeW.dmBitsPerPel;
2883 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2884 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2886 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2889 pMode->Format = pixelformat_for_depth(bpp);
2891 FIXME_(d3d_caps)("Adapter not primary display\n");
2894 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2895 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2899 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2900 and fields being inserted in the middle, a new structure is used in place */
2901 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2902 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2903 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2904 struct wined3d_adapter *adapter;
2907 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2909 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2910 return WINED3DERR_INVALIDCALL;
2913 adapter = &This->adapters[Adapter];
2915 /* Return the information requested */
2916 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2918 if (pIdentifier->driver_size)
2920 const char *name = adapter->driver_info.name;
2921 len = min(strlen(name), pIdentifier->driver_size - 1);
2922 memcpy(pIdentifier->driver, name, len);
2923 pIdentifier->driver[len] = '\0';
2926 if (pIdentifier->description_size)
2928 const char *description = adapter->driver_info.description;
2929 len = min(strlen(description), pIdentifier->description_size - 1);
2930 memcpy(pIdentifier->description, description, len);
2931 pIdentifier->description[len] = '\0';
2934 /* Note that d3d8 doesn't supply a device name. */
2935 if (pIdentifier->device_name_size)
2937 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2939 len = strlen(device_name);
2940 if (len >= pIdentifier->device_name_size)
2942 ERR("Device name size too small.\n");
2943 return WINED3DERR_INVALIDCALL;
2946 memcpy(pIdentifier->device_name, device_name, len);
2947 pIdentifier->device_name[len] = '\0';
2950 pIdentifier->driver_version.u.HighPart = adapter->driver_info.version_high;
2951 pIdentifier->driver_version.u.LowPart = adapter->driver_info.version_low;
2952 pIdentifier->vendor_id = adapter->driver_info.vendor;
2953 pIdentifier->device_id = adapter->driver_info.device;
2954 pIdentifier->subsystem_id = 0;
2955 pIdentifier->revision = 0;
2956 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2957 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2958 memcpy(&pIdentifier->adapter_luid, &adapter->luid, sizeof(pIdentifier->adapter_luid));
2959 pIdentifier->video_memory = adapter->TextureRam;
2964 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2965 const WineD3D_PixelFormat *cfg, const struct wined3d_format_desc *format_desc)
2967 short redSize, greenSize, blueSize, alphaSize, colorBits;
2972 /* Float formats need FBOs. If FBOs are used this function isn't called */
2973 if (format_desc->Flags & WINED3DFMT_FLAG_FLOAT) return FALSE;
2975 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2976 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2978 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2982 if(cfg->redSize < redSize)
2985 if(cfg->greenSize < greenSize)
2988 if(cfg->blueSize < blueSize)
2991 if(cfg->alphaSize < alphaSize)
2997 /* Probably a RGBA_float or color index mode */
3001 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
3002 const WineD3D_PixelFormat *cfg, const struct wined3d_format_desc *format_desc)
3004 short depthSize, stencilSize;
3005 BOOL lockable = FALSE;
3010 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
3012 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
3016 /* Float formats need FBOs. If FBOs are used this function isn't called */
3017 if (format_desc->Flags & WINED3DFMT_FLAG_FLOAT) return FALSE;
3019 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32_FLOAT))
3022 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
3023 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
3024 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
3025 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
3028 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
3029 * allow more stencil bits than requested. */
3030 if(cfg->stencilSize < stencilSize)
3036 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3037 WINED3DFORMAT AdapterFormat,
3038 WINED3DFORMAT RenderTargetFormat,
3039 WINED3DFORMAT DepthStencilFormat) {
3040 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3042 const WineD3D_PixelFormat *cfgs;
3043 const struct wined3d_adapter *adapter;
3044 const struct wined3d_format_desc *rt_format_desc;
3045 const struct wined3d_format_desc *ds_format_desc;
3048 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
3050 DeviceType, debug_d3ddevicetype(DeviceType),
3051 AdapterFormat, debug_d3dformat(AdapterFormat),
3052 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
3053 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
3055 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3056 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
3057 return WINED3DERR_INVALIDCALL;
3060 adapter = &This->adapters[Adapter];
3061 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
3062 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
3063 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3065 if ((rt_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET) &&
3066 (ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) {
3067 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
3073 cfgs = adapter->cfgs;
3074 nCfgs = adapter->nCfgs;
3075 for (it = 0; it < nCfgs; ++it) {
3076 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
3078 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
3080 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
3086 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
3088 return WINED3DERR_NOTAVAILABLE;
3091 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3092 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
3094 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3095 const struct wined3d_format_desc *glDesc;
3096 const struct wined3d_adapter *adapter;
3098 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
3101 DeviceType, debug_d3ddevicetype(DeviceType),
3102 SurfaceFormat, debug_d3dformat(SurfaceFormat),
3107 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3108 return WINED3DERR_INVALIDCALL;
3111 /* TODO: handle Windowed, add more quality levels */
3113 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
3114 if(pQualityLevels) *pQualityLevels = 1;
3118 /* By default multisampling is disabled right now as it causes issues
3119 * on some Nvidia driver versions and it doesn't work well in combination
3121 if(!wined3d_settings.allow_multisampling)
3122 return WINED3DERR_NOTAVAILABLE;
3124 adapter = &This->adapters[Adapter];
3125 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
3126 if (!glDesc) return WINED3DERR_INVALIDCALL;
3128 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
3130 const WineD3D_PixelFormat *cfgs;
3132 cfgs = adapter->cfgs;
3133 nCfgs = adapter->nCfgs;
3134 for(i=0; i<nCfgs; i++) {
3135 if(cfgs[i].numSamples != MultiSampleType)
3138 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
3141 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
3144 *pQualityLevels = 1; /* Guess at a value! */
3148 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
3149 short redSize, greenSize, blueSize, alphaSize, colorBits;
3151 const WineD3D_PixelFormat *cfgs;
3153 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
3155 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
3156 return WINED3DERR_NOTAVAILABLE;
3159 cfgs = adapter->cfgs;
3160 nCfgs = adapter->nCfgs;
3161 for(i=0; i<nCfgs; i++) {
3162 if(cfgs[i].numSamples != MultiSampleType)
3164 if(cfgs[i].redSize != redSize)
3166 if(cfgs[i].greenSize != greenSize)
3168 if(cfgs[i].blueSize != blueSize)
3170 /* Not all drivers report alpha-less formats since they use 32-bit anyway, so accept alpha even if we didn't ask for it. */
3171 if(alphaSize && cfgs[i].alphaSize != alphaSize)
3173 if(cfgs[i].colorSize != (glDesc->byte_count << 3))
3176 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
3179 *pQualityLevels = 1; /* Guess at a value! */
3183 return WINED3DERR_NOTAVAILABLE;
3186 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3187 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed)
3189 HRESULT hr = WINED3DERR_NOTAVAILABLE;
3192 TRACE("iface %p, adapter_idx %u, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
3193 iface, Adapter, debug_d3ddevicetype(DeviceType), debug_d3dformat(DisplayFormat),
3194 debug_d3dformat(BackBufferFormat), Windowed);
3196 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3197 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
3198 return WINED3DERR_INVALIDCALL;
3201 /* The task of this function is to check whether a certain display / backbuffer format
3202 * combination is available on the given adapter. In fullscreen mode microsoft specified
3203 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
3204 * and display format should match exactly.
3205 * In windowed mode format conversion can occur and this depends on the driver. When format
3206 * conversion is done, this function should nevertheless fail and applications need to use
3207 * CheckDeviceFormatConversion.
3208 * At the moment we assume that fullscreen and windowed have the same capabilities */
3210 /* There are only 4 display formats */
3211 if (!(DisplayFormat == WINED3DFMT_B5G6R5_UNORM
3212 || DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
3213 || DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
3214 || DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM))
3216 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
3217 return WINED3DERR_NOTAVAILABLE;
3220 /* If the requested DisplayFormat is not available, don't continue */
3221 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
3223 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
3224 return WINED3DERR_NOTAVAILABLE;
3227 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
3228 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
3229 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
3230 return WINED3DERR_NOTAVAILABLE;
3233 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
3234 if (DisplayFormat == WINED3DFMT_B5G6R5_UNORM && BackBufferFormat != WINED3DFMT_B5G6R5_UNORM)
3236 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3237 return WINED3DERR_NOTAVAILABLE;
3240 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
3241 if (DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
3242 && !(BackBufferFormat == WINED3DFMT_B5G5R5X1_UNORM || BackBufferFormat == WINED3DFMT_B5G5R5A1_UNORM))
3244 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3245 return WINED3DERR_NOTAVAILABLE;
3248 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
3249 if (DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
3250 && !(BackBufferFormat == WINED3DFMT_B8G8R8X8_UNORM || BackBufferFormat == WINED3DFMT_B8G8R8A8_UNORM))
3252 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3253 return WINED3DERR_NOTAVAILABLE;
3256 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
3257 if (DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM
3258 && (BackBufferFormat != WINED3DFMT_B10G10R10A2_UNORM || Windowed))
3260 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3261 return WINED3DERR_NOTAVAILABLE;
3264 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
3265 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
3267 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3273 /* Check if we support bumpmapping for a format */
3274 static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3276 /* Ask the fixed function pipeline implementation if it can deal
3277 * with the conversion. If we've got a GL extension giving native
3278 * support this will be an identity conversion. */
3279 return (format_desc->Flags & WINED3DFMT_FLAG_BUMPMAP)
3280 && adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup);
3283 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
3284 static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter,
3285 const struct wined3d_format_desc *display_format_desc, const struct wined3d_format_desc *ds_format_desc)
3289 /* Only allow depth/stencil formats */
3290 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
3292 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3294 /* With FBOs WGL limitations do not apply, but the format needs to be FBO attachable */
3295 if (ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) return TRUE;
3299 /* Walk through all WGL pixel formats to find a match */
3300 for (it = 0; it < adapter->nCfgs; ++it)
3302 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
3303 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
3305 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
3316 static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3318 /* The flags entry of a format contains the filtering capability */
3319 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
3324 /* Check the render target capabilities of a format */
3325 static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter,
3326 const struct wined3d_format_desc *adapter_format_desc, const struct wined3d_format_desc *check_format_desc)
3328 /* Filter out non-RT formats */
3329 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
3330 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
3331 WineD3D_PixelFormat *cfgs = adapter->cfgs;
3333 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
3334 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
3336 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
3337 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
3339 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
3340 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
3341 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
3342 TRACE_(d3d_caps)("[FAILED]\n");
3346 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
3347 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
3348 for (it = 0; it < adapter->nCfgs; ++it)
3350 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
3351 &cfgs[it], check_format_desc))
3353 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
3354 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
3359 else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3361 /* For now return TRUE for FBOs until we have some proper checks.
3362 * Note that this function will only be called when the format is around for texturing. */
3368 static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3370 return adapter->gl_info.supported[EXT_TEXTURE_SRGB]
3371 && (format_desc->Flags & WINED3DFMT_FLAG_SRGB_READ);
3374 static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3376 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
3377 * doing the color fixup in shaders.
3378 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
3379 if (format_desc->Flags & WINED3DFMT_FLAG_SRGB_WRITE)
3381 int vs_selected_mode;
3382 int ps_selected_mode;
3383 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3385 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
3386 TRACE_(d3d_caps)("[OK]\n");
3391 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
3395 /* Check if a format support blending in combination with pixel shaders */
3396 static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapter,
3397 const struct wined3d_format_desc *format_desc)
3399 /* The flags entry of a format contains the post pixel shader blending capability */
3400 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
3405 static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3407 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
3408 * but we have to report mipmapping so we cannot reject this flag. Tests show that
3409 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
3410 * that wrapping is supported. The lack of filtering will sort out the mipmapping
3411 * capability anyway.
3413 * For now lets report this on all formats, but in the future we may want to
3414 * restrict it to some should games need that
3419 /* Check if a texture format is supported on the given adapter */
3420 static BOOL CheckTextureCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3422 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3424 switch (format_desc->format)
3427 * supported: RGB(A) formats
3429 case WINED3DFMT_B8G8R8_UNORM: /* Enable for dx7, blacklisted for 8 and 9 above */
3430 case WINED3DFMT_B8G8R8A8_UNORM:
3431 case WINED3DFMT_B8G8R8X8_UNORM:
3432 case WINED3DFMT_B5G6R5_UNORM:
3433 case WINED3DFMT_B5G5R5X1_UNORM:
3434 case WINED3DFMT_B5G5R5A1_UNORM:
3435 case WINED3DFMT_B4G4R4A4_UNORM:
3436 case WINED3DFMT_A8_UNORM:
3437 case WINED3DFMT_B4G4R4X4_UNORM:
3438 case WINED3DFMT_R8G8B8A8_UNORM:
3439 case WINED3DFMT_R8G8B8X8_UNORM:
3440 case WINED3DFMT_B10G10R10A2_UNORM:
3441 case WINED3DFMT_R10G10B10A2_UNORM:
3442 case WINED3DFMT_R16G16_UNORM:
3443 TRACE_(d3d_caps)("[OK]\n");
3446 case WINED3DFMT_B2G3R3_UNORM:
3447 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
3451 * Not supported: Palettized
3452 * Only some Geforce/Voodoo3/G400 cards offer 8-bit textures in case of <=Direct3D7.
3453 * Since it is not widely available, don't offer it. Further no Windows driver offers
3454 * WINED3DFMT_P8_UINT_A8_NORM, so don't offer it either.
3456 case WINED3DFMT_P8_UINT:
3457 case WINED3DFMT_P8_UINT_A8_UNORM:
3461 * Supported: (Alpha)-Luminance
3463 case WINED3DFMT_L8_UNORM:
3464 case WINED3DFMT_L8A8_UNORM:
3465 case WINED3DFMT_L16_UNORM:
3466 TRACE_(d3d_caps)("[OK]\n");
3469 /* Not supported on Windows, thus disabled */
3470 case WINED3DFMT_L4A4_UNORM:
3471 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
3475 * Supported: Depth/Stencil formats
3477 case WINED3DFMT_D16_LOCKABLE:
3478 case WINED3DFMT_D16_UNORM:
3479 case WINED3DFMT_S1_UINT_D15_UNORM:
3480 case WINED3DFMT_X8D24_UNORM:
3481 case WINED3DFMT_S4X4_UINT_D24_UNORM:
3482 case WINED3DFMT_D24_UNORM_S8_UINT:
3483 case WINED3DFMT_S8_UINT_D24_FLOAT:
3484 case WINED3DFMT_D32_UNORM:
3485 case WINED3DFMT_D32_FLOAT:
3489 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
3490 * GL_NV_texture_shader). Emulated by shaders
3492 case WINED3DFMT_R8G8_SNORM:
3493 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3494 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3495 case WINED3DFMT_R8G8B8A8_SNORM:
3496 case WINED3DFMT_R16G16_SNORM:
3497 /* Ask the shader backend if it can deal with the conversion. If
3498 * we've got a GL extension giving native support this will be an
3499 * identity conversion. */
3500 if (adapter->shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
3502 TRACE_(d3d_caps)("[OK]\n");
3505 TRACE_(d3d_caps)("[FAILED]\n");
3508 case WINED3DFMT_DXT1:
3509 case WINED3DFMT_DXT2:
3510 case WINED3DFMT_DXT3:
3511 case WINED3DFMT_DXT4:
3512 case WINED3DFMT_DXT5:
3513 if (gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC])
3515 TRACE_(d3d_caps)("[OK]\n");
3518 TRACE_(d3d_caps)("[FAILED]\n");
3523 * Odd formats - not supported
3525 case WINED3DFMT_VERTEXDATA:
3526 case WINED3DFMT_R16_UINT:
3527 case WINED3DFMT_R32_UINT:
3528 case WINED3DFMT_R16G16B16A16_SNORM:
3529 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM:
3530 case WINED3DFMT_R10G11B11_SNORM:
3531 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3535 * WINED3DFMT_R8G8_SNORM_Cx: Not supported right now
3537 case WINED3DFMT_R8G8_SNORM_Cx:
3538 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3542 case WINED3DFMT_UYVY:
3543 case WINED3DFMT_YUY2:
3544 if (gl_info->supported[APPLE_YCBCR_422])
3546 TRACE_(d3d_caps)("[OK]\n");
3549 TRACE_(d3d_caps)("[FAILED]\n");
3551 case WINED3DFMT_YV12:
3552 TRACE_(d3d_caps)("[FAILED]\n");
3556 case WINED3DFMT_R16G16B16A16_UNORM:
3557 case WINED3DFMT_B2G3R3A8_UNORM:
3558 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3561 /* Floating point formats */
3562 case WINED3DFMT_R16_FLOAT:
3563 case WINED3DFMT_R16G16_FLOAT:
3564 case WINED3DFMT_R16G16B16A16_FLOAT:
3565 if (gl_info->supported[ARB_TEXTURE_FLOAT] && gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3567 TRACE_(d3d_caps)("[OK]\n");
3570 TRACE_(d3d_caps)("[FAILED]\n");
3573 case WINED3DFMT_R32_FLOAT:
3574 case WINED3DFMT_R32G32_FLOAT:
3575 case WINED3DFMT_R32G32B32A32_FLOAT:
3576 if (gl_info->supported[ARB_TEXTURE_FLOAT])
3578 TRACE_(d3d_caps)("[OK]\n");
3581 TRACE_(d3d_caps)("[FAILED]\n");
3584 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3585 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3586 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3587 * We can do instancing with all shader versions, but we need vertex shaders.
3589 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3590 * to enable instancing. WineD3D doesn't need that and just ignores it.
3592 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3594 case WINED3DFMT_INST:
3595 TRACE("ATI Instancing check hack\n");
3596 if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
3598 TRACE_(d3d_caps)("[OK]\n");
3601 TRACE_(d3d_caps)("[FAILED]\n");
3604 /* Some weird FOURCC formats */
3605 case WINED3DFMT_R8G8_B8G8:
3606 case WINED3DFMT_G8R8_G8B8:
3607 case WINED3DFMT_MULTI2_ARGB8:
3608 TRACE_(d3d_caps)("[FAILED]\n");
3611 /* Vendor specific formats */
3612 case WINED3DFMT_ATI2N:
3613 if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC]
3614 || gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
3616 if (adapter->shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3617 && adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup))
3619 TRACE_(d3d_caps)("[OK]\n");
3623 TRACE_(d3d_caps)("[OK]\n");
3626 TRACE_(d3d_caps)("[FAILED]\n");
3629 case WINED3DFMT_NVHU:
3630 case WINED3DFMT_NVHS:
3631 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3632 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3633 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3634 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3635 * Applications have to deal with not having NVHS and NVHU.
3637 TRACE_(d3d_caps)("[FAILED]\n");
3640 case WINED3DFMT_UNKNOWN:
3644 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3650 static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter,
3651 const struct wined3d_format_desc *adapter_format_desc,
3652 const struct wined3d_format_desc *check_format_desc,
3653 WINED3DSURFTYPE SurfaceType)
3655 if(SurfaceType == SURFACE_GDI) {
3656 switch(check_format_desc->format)
3658 case WINED3DFMT_B8G8R8_UNORM:
3659 case WINED3DFMT_B8G8R8A8_UNORM:
3660 case WINED3DFMT_B8G8R8X8_UNORM:
3661 case WINED3DFMT_B5G6R5_UNORM:
3662 case WINED3DFMT_B5G5R5X1_UNORM:
3663 case WINED3DFMT_B5G5R5A1_UNORM:
3664 case WINED3DFMT_B4G4R4A4_UNORM:
3665 case WINED3DFMT_B2G3R3_UNORM:
3666 case WINED3DFMT_A8_UNORM:
3667 case WINED3DFMT_B2G3R3A8_UNORM:
3668 case WINED3DFMT_B4G4R4X4_UNORM:
3669 case WINED3DFMT_R10G10B10A2_UNORM:
3670 case WINED3DFMT_R8G8B8A8_UNORM:
3671 case WINED3DFMT_R8G8B8X8_UNORM:
3672 case WINED3DFMT_R16G16_UNORM:
3673 case WINED3DFMT_B10G10R10A2_UNORM:
3674 case WINED3DFMT_R16G16B16A16_UNORM:
3675 case WINED3DFMT_P8_UINT:
3676 TRACE_(d3d_caps)("[OK]\n");
3679 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3684 /* All format that are supported for textures are supported for surfaces as well */
3685 if (CheckTextureCapability(adapter, check_format_desc)) return TRUE;
3686 /* All depth stencil formats are supported on surfaces */
3687 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3689 /* If opengl can't process the format natively, the blitter may be able to convert it */
3690 if (adapter->blitter->blit_supported(&adapter->gl_info, BLIT_OP_BLIT,
3691 NULL, WINED3DPOOL_DEFAULT, 0, check_format_desc,
3692 NULL, WINED3DPOOL_DEFAULT, 0, adapter_format_desc))
3694 TRACE_(d3d_caps)("[OK]\n");
3698 /* Reject other formats */
3699 TRACE_(d3d_caps)("[FAILED]\n");
3703 static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter,
3704 const struct wined3d_format_desc *format_desc)
3706 return adapter->gl_info.limits.vertex_samplers
3707 && (format_desc->Flags & WINED3DFMT_FLAG_VTF);
3710 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3711 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3712 WINED3DSURFTYPE SurfaceType)
3714 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3715 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3716 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3717 const struct wined3d_format_desc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3718 const struct wined3d_format_desc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3719 DWORD UsageCaps = 0;
3721 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3724 DeviceType, debug_d3ddevicetype(DeviceType),
3725 AdapterFormat, debug_d3dformat(AdapterFormat),
3726 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3727 RType, debug_d3dresourcetype(RType),
3728 CheckFormat, debug_d3dformat(CheckFormat));
3730 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3731 return WINED3DERR_INVALIDCALL;
3736 case WINED3DRTYPE_CUBETEXTURE:
3737 /* Cubetexture allows:
3738 * - WINED3DUSAGE_AUTOGENMIPMAP
3739 * - WINED3DUSAGE_DEPTHSTENCIL
3740 * - WINED3DUSAGE_DYNAMIC
3741 * - WINED3DUSAGE_NONSECURE (d3d9ex)
3742 * - WINED3DUSAGE_RENDERTARGET
3743 * - WINED3DUSAGE_SOFTWAREPROCESSING
3744 * - WINED3DUSAGE_QUERY_WRAPANDMIP
3746 if (SurfaceType != SURFACE_OPENGL)
3748 TRACE_(d3d_caps)("[FAILED]\n");
3749 return WINED3DERR_NOTAVAILABLE;
3752 if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3754 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3755 return WINED3DERR_NOTAVAILABLE;
3758 if (!CheckTextureCapability(adapter, format_desc))
3760 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3761 return WINED3DERR_NOTAVAILABLE;
3764 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP)
3766 if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
3767 /* When autogenmipmap isn't around continue and return
3768 * WINED3DOK_NOAUTOGEN instead of D3D_OK. */
3769 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3771 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3774 /* Always report dynamic locking. */
3775 if (Usage & WINED3DUSAGE_DYNAMIC)
3776 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3778 if (Usage & WINED3DUSAGE_RENDERTARGET)
3780 if (!CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3782 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3783 return WINED3DERR_NOTAVAILABLE;
3785 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3788 /* Always report software processing. */
3789 if (Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3790 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3792 if (Usage & WINED3DUSAGE_QUERY_FILTER)
3794 if (!CheckFilterCapability(adapter, format_desc))
3796 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3797 return WINED3DERR_NOTAVAILABLE;
3799 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3802 if (Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
3804 if (!CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3806 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3807 return WINED3DERR_NOTAVAILABLE;
3809 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3812 if (Usage & WINED3DUSAGE_QUERY_SRGBREAD)
3814 if (!CheckSrgbReadCapability(adapter, format_desc))
3816 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3817 return WINED3DERR_NOTAVAILABLE;
3819 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3822 if (Usage & WINED3DUSAGE_QUERY_SRGBWRITE)
3824 if (!CheckSrgbWriteCapability(adapter, format_desc))
3826 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3827 return WINED3DERR_NOTAVAILABLE;
3829 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3832 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
3834 if (!CheckVertexTextureCapability(adapter, format_desc))
3836 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3837 return WINED3DERR_NOTAVAILABLE;
3839 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3842 if (Usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
3844 if (!CheckWrapAndMipCapability(adapter, format_desc))
3846 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3847 return WINED3DERR_NOTAVAILABLE;
3849 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3853 case WINED3DRTYPE_SURFACE:
3855 * - WINED3DUSAGE_DEPTHSTENCIL
3856 * - WINED3DUSAGE_NONSECURE (d3d9ex)
3857 * - WINED3DUSAGE_RENDERTARGET
3859 if (!CheckSurfaceCapability(adapter, adapter_format_desc, format_desc, SurfaceType))
3861 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3862 return WINED3DERR_NOTAVAILABLE;
3865 if (Usage & WINED3DUSAGE_DEPTHSTENCIL)
3867 if (!CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3869 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3870 return WINED3DERR_NOTAVAILABLE;
3872 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3875 if (Usage & WINED3DUSAGE_RENDERTARGET)
3877 if (!CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3879 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3880 return WINED3DERR_NOTAVAILABLE;
3882 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3885 if (Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
3887 if (!CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3889 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3890 return WINED3DERR_NOTAVAILABLE;
3892 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3896 case WINED3DRTYPE_TEXTURE:
3898 * - WINED3DUSAGE_AUTOGENMIPMAP
3899 * - WINED3DUSAGE_DEPTHSTENCIL
3900 * - WINED3DUSAGE_DMAP
3901 * - WINED3DUSAGE_DYNAMIC
3902 * - WINED3DUSAGE_NONSECURE (d3d9ex)
3903 * - WINED3DUSAGE_RENDERTARGET
3904 * - WINED3DUSAGE_SOFTWAREPROCESSING
3905 * - WINED3DUSAGE_TEXTAPI (d3d9ex)
3906 * - WINED3DUSAGE_QUERY_WRAPANDMIP
3908 if (SurfaceType != SURFACE_OPENGL)
3910 TRACE_(d3d_caps)("[FAILED]\n");
3911 return WINED3DERR_NOTAVAILABLE;
3914 if (!CheckTextureCapability(adapter, format_desc))
3916 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3917 return WINED3DERR_NOTAVAILABLE;
3920 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP)
3922 if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
3923 /* When autogenmipmap isn't around continue and return
3924 * WINED3DOK_NOAUTOGEN instead of D3D_OK. */
3925 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3927 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3930 /* Always report dynamic locking. */
3931 if (Usage & WINED3DUSAGE_DYNAMIC)
3932 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3934 if (Usage & WINED3DUSAGE_RENDERTARGET)
3936 if (!CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3938 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3939 return WINED3DERR_NOTAVAILABLE;
3941 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3944 /* Always report software processing. */
3945 if (Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3946 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3948 if (Usage & WINED3DUSAGE_QUERY_FILTER)
3950 if (!CheckFilterCapability(adapter, format_desc))
3952 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3953 return WINED3DERR_NOTAVAILABLE;
3955 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3958 if (Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP)
3960 if (!CheckBumpMapCapability(adapter, format_desc))
3962 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3963 return WINED3DERR_NOTAVAILABLE;
3965 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3968 if (Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
3970 if (!CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3972 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3973 return WINED3DERR_NOTAVAILABLE;
3975 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3978 if (Usage & WINED3DUSAGE_QUERY_SRGBREAD)
3980 if (!CheckSrgbReadCapability(adapter, format_desc))
3982 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3983 return WINED3DERR_NOTAVAILABLE;
3985 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3988 if (Usage & WINED3DUSAGE_QUERY_SRGBWRITE)
3990 if (!CheckSrgbWriteCapability(adapter, format_desc))
3992 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3993 return WINED3DERR_NOTAVAILABLE;
3995 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3998 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
4000 if (!CheckVertexTextureCapability(adapter, format_desc))
4002 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
4003 return WINED3DERR_NOTAVAILABLE;
4005 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
4008 if (Usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
4010 if (!CheckWrapAndMipCapability(adapter, format_desc))
4012 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
4013 return WINED3DERR_NOTAVAILABLE;
4015 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
4018 if (Usage & WINED3DUSAGE_DEPTHSTENCIL)
4020 if (!CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
4022 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
4023 return WINED3DERR_NOTAVAILABLE;
4025 if ((format_desc->Flags & WINED3DFMT_FLAG_SHADOW) && !gl_info->supported[ARB_SHADOW])
4027 TRACE_(d3d_caps)("[FAILED] - No shadow sampler support.\n");
4028 return WINED3DERR_NOTAVAILABLE;
4030 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
4034 case WINED3DRTYPE_VOLUMETEXTURE:
4035 case WINED3DRTYPE_VOLUME:
4036 /* Volume is to VolumeTexture what Surface is to Texture, but its
4037 * usage caps are not documented. Most driver seem to offer
4038 * (nearly) the same on Volume and VolumeTexture, so do that too.
4040 * Volumetexture allows:
4041 * - D3DUSAGE_DYNAMIC
4042 * - D3DUSAGE_NONSECURE (d3d9ex)
4043 * - D3DUSAGE_SOFTWAREPROCESSING
4044 * - D3DUSAGE_QUERY_WRAPANDMIP
4046 if (SurfaceType != SURFACE_OPENGL)
4048 TRACE_(d3d_caps)("[FAILED]\n");
4049 return WINED3DERR_NOTAVAILABLE;
4052 if (!gl_info->supported[EXT_TEXTURE3D])
4054 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
4055 return WINED3DERR_NOTAVAILABLE;
4058 if (!CheckTextureCapability(adapter, format_desc))
4060 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
4061 return WINED3DERR_NOTAVAILABLE;
4064 /* Filter formats that need conversion; For one part, this
4065 * conversion is unimplemented, and volume textures are huge, so
4066 * it would be a big performance hit. Unless we hit an application
4067 * needing one of those formats, don't advertize them to avoid
4068 * leading applications into temptation. The windows drivers don't
4069 * support most of those formats on volumes anyway, except for
4070 * WINED3DFMT_R32_FLOAT. */
4071 switch (CheckFormat)
4073 case WINED3DFMT_P8_UINT:
4074 case WINED3DFMT_L4A4_UNORM:
4075 case WINED3DFMT_R32_FLOAT:
4076 case WINED3DFMT_R16_FLOAT:
4077 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
4078 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
4079 case WINED3DFMT_R16G16_UNORM:
4080 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4081 return WINED3DERR_NOTAVAILABLE;
4083 case WINED3DFMT_R8G8B8A8_SNORM:
4084 case WINED3DFMT_R16G16_SNORM:
4085 if (!gl_info->supported[NV_TEXTURE_SHADER])
4087 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4088 return WINED3DERR_NOTAVAILABLE;
4092 case WINED3DFMT_R8G8_SNORM:
4093 if (!gl_info->supported[NV_TEXTURE_SHADER])
4095 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4096 return WINED3DERR_NOTAVAILABLE;
4100 case WINED3DFMT_DXT1:
4101 case WINED3DFMT_DXT2:
4102 case WINED3DFMT_DXT3:
4103 case WINED3DFMT_DXT4:
4104 case WINED3DFMT_DXT5:
4105 /* The GL_EXT_texture_compression_s3tc spec requires that
4106 * loading an s3tc compressed texture results in an error.
4107 * While the D3D refrast does support s3tc volumes, at
4108 * least the nvidia windows driver does not, so we're free
4109 * not to support this format. */
4110 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
4111 return WINED3DERR_NOTAVAILABLE;
4114 /* Do nothing, continue with checking the format below */
4118 /* Always report dynamic locking. */
4119 if (Usage & WINED3DUSAGE_DYNAMIC)
4120 UsageCaps |= WINED3DUSAGE_DYNAMIC;
4122 /* Always report software processing. */
4123 if (Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
4124 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
4126 if (Usage & WINED3DUSAGE_QUERY_FILTER)
4128 if (!CheckFilterCapability(adapter, format_desc))
4130 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
4131 return WINED3DERR_NOTAVAILABLE;
4133 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
4136 if (Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
4138 if (!CheckPostPixelShaderBlendingCapability(adapter, format_desc))
4140 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
4141 return WINED3DERR_NOTAVAILABLE;
4143 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
4146 if (Usage & WINED3DUSAGE_QUERY_SRGBREAD)
4148 if (!CheckSrgbReadCapability(adapter, format_desc))
4150 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
4151 return WINED3DERR_NOTAVAILABLE;
4153 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
4156 if (Usage & WINED3DUSAGE_QUERY_SRGBWRITE)
4158 if (!CheckSrgbWriteCapability(adapter, format_desc))
4160 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
4161 return WINED3DERR_NOTAVAILABLE;
4163 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
4166 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
4168 if (!CheckVertexTextureCapability(adapter, format_desc))
4170 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
4171 return WINED3DERR_NOTAVAILABLE;
4173 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
4176 if (Usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
4178 if (!CheckWrapAndMipCapability(adapter, format_desc))
4180 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
4181 return WINED3DERR_NOTAVAILABLE;
4183 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
4188 FIXME_(d3d_caps)("Unhandled resource type %s.\n", debug_d3dresourcetype(RType));
4189 return WINED3DERR_NOTAVAILABLE;
4192 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for
4193 * the situation in which WINED3DUSAGE_AUTOGENMIPMAP isn't around, then
4194 * WINED3DOK_NOAUTOGEN is returned if all the other usage flags match. */
4195 if (UsageCaps == Usage)
4197 if (UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP))
4198 return WINED3DOK_NOAUTOGEN;
4200 TRACE_(d3d_caps)("[FAILED] - Usage %#x requested for CheckFormat %s and RType %s but only %#x is available\n",
4201 Usage, debug_d3dformat(CheckFormat), debug_d3dresourcetype(RType), UsageCaps);
4203 return WINED3DERR_NOTAVAILABLE;
4206 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT adapter_idx,
4207 WINED3DDEVTYPE device_type, WINED3DFORMAT src_format, WINED3DFORMAT dst_format)
4209 FIXME("iface %p, adapter_idx %u, device_type %s, src_format %s, dst_format %s stub!\n",
4210 iface, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(src_format),
4211 debug_d3dformat(dst_format));
4216 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
4217 subset of a D3DCAPS9 structure. However, it has to come via a void *
4218 as the d3d8 interface cannot import the d3d9 header */
4219 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
4221 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4222 struct wined3d_adapter *adapter = &This->adapters[Adapter];
4223 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4224 int vs_selected_mode;
4225 int ps_selected_mode;
4226 struct shader_caps shader_caps;
4227 struct fragment_caps fragment_caps;
4228 DWORD ckey_caps, blit_caps, fx_caps;
4230 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
4232 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
4233 return WINED3DERR_INVALIDCALL;
4236 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
4238 /* ------------------------------------------------
4239 The following fields apply to both d3d8 and d3d9
4240 ------------------------------------------------ */
4241 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
4242 pCaps->AdapterOrdinal = Adapter;
4245 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
4246 WINED3DCAPS2_FULLSCREENGAMMA |
4247 WINED3DCAPS2_DYNAMICTEXTURES;
4248 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
4250 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
4253 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
4254 WINED3DCAPS3_COPY_TO_VIDMEM |
4255 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
4257 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
4258 WINED3DPRESENT_INTERVAL_ONE;
4260 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
4261 WINED3DCURSORCAPS_LOWRES;
4263 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
4264 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
4265 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
4266 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4267 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
4268 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
4269 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
4270 WINED3DDEVCAPS_PUREDEVICE |
4271 WINED3DDEVCAPS_HWRASTERIZATION |
4272 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
4273 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
4274 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
4275 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
4276 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
4277 WINED3DDEVCAPS_RTPATCHES;
4279 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
4280 WINED3DPMISCCAPS_CULLCCW |
4281 WINED3DPMISCCAPS_CULLCW |
4282 WINED3DPMISCCAPS_COLORWRITEENABLE |
4283 WINED3DPMISCCAPS_CLIPTLVERTS |
4284 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
4285 WINED3DPMISCCAPS_MASKZ |
4286 WINED3DPMISCCAPS_BLENDOP |
4287 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
4289 WINED3DPMISCCAPS_NULLREFERENCE
4290 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
4291 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
4292 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
4294 if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
4295 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
4296 if (gl_info->supported[EXT_DRAW_BUFFERS2])
4297 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS;
4299 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
4300 WINED3DPRASTERCAPS_PAT |
4301 WINED3DPRASTERCAPS_WFOG |
4302 WINED3DPRASTERCAPS_ZFOG |
4303 WINED3DPRASTERCAPS_FOGVERTEX |
4304 WINED3DPRASTERCAPS_FOGTABLE |
4305 WINED3DPRASTERCAPS_STIPPLE |
4306 WINED3DPRASTERCAPS_SUBPIXEL |
4307 WINED3DPRASTERCAPS_ZTEST |
4308 WINED3DPRASTERCAPS_SCISSORTEST |
4309 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
4310 WINED3DPRASTERCAPS_DEPTHBIAS;
4312 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4314 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
4315 WINED3DPRASTERCAPS_ZBIAS |
4316 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
4318 if (gl_info->supported[NV_FOG_DISTANCE])
4320 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
4323 WINED3DPRASTERCAPS_COLORPERSPECTIVE
4324 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
4325 WINED3DPRASTERCAPS_ANTIALIASEDGES
4326 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
4327 WINED3DPRASTERCAPS_WBUFFER */
4329 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
4330 WINED3DPCMPCAPS_EQUAL |
4331 WINED3DPCMPCAPS_GREATER |
4332 WINED3DPCMPCAPS_GREATEREQUAL |
4333 WINED3DPCMPCAPS_LESS |
4334 WINED3DPCMPCAPS_LESSEQUAL |
4335 WINED3DPCMPCAPS_NEVER |
4336 WINED3DPCMPCAPS_NOTEQUAL;
4338 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
4339 WINED3DPBLENDCAPS_BOTHSRCALPHA |
4340 WINED3DPBLENDCAPS_DESTALPHA |
4341 WINED3DPBLENDCAPS_DESTCOLOR |
4342 WINED3DPBLENDCAPS_INVDESTALPHA |
4343 WINED3DPBLENDCAPS_INVDESTCOLOR |
4344 WINED3DPBLENDCAPS_INVSRCALPHA |
4345 WINED3DPBLENDCAPS_INVSRCCOLOR |
4346 WINED3DPBLENDCAPS_ONE |
4347 WINED3DPBLENDCAPS_SRCALPHA |
4348 WINED3DPBLENDCAPS_SRCALPHASAT |
4349 WINED3DPBLENDCAPS_SRCCOLOR |
4350 WINED3DPBLENDCAPS_ZERO;
4352 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
4353 WINED3DPBLENDCAPS_DESTCOLOR |
4354 WINED3DPBLENDCAPS_INVDESTALPHA |
4355 WINED3DPBLENDCAPS_INVDESTCOLOR |
4356 WINED3DPBLENDCAPS_INVSRCALPHA |
4357 WINED3DPBLENDCAPS_INVSRCCOLOR |
4358 WINED3DPBLENDCAPS_ONE |
4359 WINED3DPBLENDCAPS_SRCALPHA |
4360 WINED3DPBLENDCAPS_SRCCOLOR |
4361 WINED3DPBLENDCAPS_ZERO;
4362 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
4363 * according to the glBlendFunc manpage
4365 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
4366 * legacy settings for srcblend only
4369 if (gl_info->supported[EXT_BLEND_COLOR])
4371 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
4372 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
4376 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
4377 WINED3DPCMPCAPS_EQUAL |
4378 WINED3DPCMPCAPS_GREATER |
4379 WINED3DPCMPCAPS_GREATEREQUAL |
4380 WINED3DPCMPCAPS_LESS |
4381 WINED3DPCMPCAPS_LESSEQUAL |
4382 WINED3DPCMPCAPS_NEVER |
4383 WINED3DPCMPCAPS_NOTEQUAL;
4385 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
4386 WINED3DPSHADECAPS_COLORGOURAUDRGB |
4387 WINED3DPSHADECAPS_ALPHAFLATBLEND |
4388 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
4389 WINED3DPSHADECAPS_COLORFLATRGB |
4390 WINED3DPSHADECAPS_FOGFLAT |
4391 WINED3DPSHADECAPS_FOGGOURAUD |
4392 WINED3DPSHADECAPS_SPECULARFLATRGB;
4394 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
4395 WINED3DPTEXTURECAPS_ALPHAPALETTE |
4396 WINED3DPTEXTURECAPS_TRANSPARENCY |
4397 WINED3DPTEXTURECAPS_BORDER |
4398 WINED3DPTEXTURECAPS_MIPMAP |
4399 WINED3DPTEXTURECAPS_PROJECTED |
4400 WINED3DPTEXTURECAPS_PERSPECTIVE;
4402 if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
4404 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
4405 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
4408 if (gl_info->supported[EXT_TEXTURE3D])
4410 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
4411 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
4412 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
4415 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4417 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
4418 WINED3DPTEXTURECAPS_MIPCUBEMAP |
4419 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
4423 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4424 WINED3DPTFILTERCAPS_MAGFPOINT |
4425 WINED3DPTFILTERCAPS_MINFLINEAR |
4426 WINED3DPTFILTERCAPS_MINFPOINT |
4427 WINED3DPTFILTERCAPS_MIPFLINEAR |
4428 WINED3DPTFILTERCAPS_MIPFPOINT |
4429 WINED3DPTFILTERCAPS_LINEAR |
4430 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4431 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4432 WINED3DPTFILTERCAPS_MIPLINEAR |
4433 WINED3DPTFILTERCAPS_MIPNEAREST |
4434 WINED3DPTFILTERCAPS_NEAREST;
4436 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4438 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4439 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4442 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4444 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4445 WINED3DPTFILTERCAPS_MAGFPOINT |
4446 WINED3DPTFILTERCAPS_MINFLINEAR |
4447 WINED3DPTFILTERCAPS_MINFPOINT |
4448 WINED3DPTFILTERCAPS_MIPFLINEAR |
4449 WINED3DPTFILTERCAPS_MIPFPOINT |
4450 WINED3DPTFILTERCAPS_LINEAR |
4451 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4452 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4453 WINED3DPTFILTERCAPS_MIPLINEAR |
4454 WINED3DPTFILTERCAPS_MIPNEAREST |
4455 WINED3DPTFILTERCAPS_NEAREST;
4457 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4459 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4460 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4463 pCaps->CubeTextureFilterCaps = 0;
4465 if (gl_info->supported[EXT_TEXTURE3D])
4467 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4468 WINED3DPTFILTERCAPS_MAGFPOINT |
4469 WINED3DPTFILTERCAPS_MINFLINEAR |
4470 WINED3DPTFILTERCAPS_MINFPOINT |
4471 WINED3DPTFILTERCAPS_MIPFLINEAR |
4472 WINED3DPTFILTERCAPS_MIPFPOINT |
4473 WINED3DPTFILTERCAPS_LINEAR |
4474 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4475 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4476 WINED3DPTFILTERCAPS_MIPLINEAR |
4477 WINED3DPTFILTERCAPS_MIPNEAREST |
4478 WINED3DPTFILTERCAPS_NEAREST;
4480 pCaps->VolumeTextureFilterCaps = 0;
4482 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4483 WINED3DPTADDRESSCAPS_CLAMP |
4484 WINED3DPTADDRESSCAPS_WRAP;
4486 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4488 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4490 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4492 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4494 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4496 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4499 if (gl_info->supported[EXT_TEXTURE3D])
4501 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4502 WINED3DPTADDRESSCAPS_CLAMP |
4503 WINED3DPTADDRESSCAPS_WRAP;
4504 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4506 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4508 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4510 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4512 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4514 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4517 pCaps->VolumeTextureAddressCaps = 0;
4519 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4520 WINED3DLINECAPS_ZTEST |
4521 WINED3DLINECAPS_BLEND |
4522 WINED3DLINECAPS_ALPHACMP |
4523 WINED3DLINECAPS_FOG;
4524 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4525 * idea how generating the smoothing alpha values works; the result is different
4528 pCaps->MaxTextureWidth = gl_info->limits.texture_size;
4529 pCaps->MaxTextureHeight = gl_info->limits.texture_size;
4531 if (gl_info->supported[EXT_TEXTURE3D])
4532 pCaps->MaxVolumeExtent = gl_info->limits.texture3d_size;
4534 pCaps->MaxVolumeExtent = 0;
4536 pCaps->MaxTextureRepeat = 32768;
4537 pCaps->MaxTextureAspectRatio = gl_info->limits.texture_size;
4538 pCaps->MaxVertexW = 1.0f;
4540 pCaps->GuardBandLeft = 0.0f;
4541 pCaps->GuardBandTop = 0.0f;
4542 pCaps->GuardBandRight = 0.0f;
4543 pCaps->GuardBandBottom = 0.0f;
4545 pCaps->ExtentsAdjust = 0.0f;
4547 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4548 WINED3DSTENCILCAPS_INCRSAT |
4549 WINED3DSTENCILCAPS_INVERT |
4550 WINED3DSTENCILCAPS_KEEP |
4551 WINED3DSTENCILCAPS_REPLACE |
4552 WINED3DSTENCILCAPS_ZERO;
4553 if (gl_info->supported[EXT_STENCIL_WRAP])
4555 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4556 WINED3DSTENCILCAPS_INCR;
4558 if (gl_info->supported[EXT_STENCIL_TWO_SIDE] || gl_info->supported[ATI_SEPARATE_STENCIL])
4560 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4563 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4565 pCaps->MaxUserClipPlanes = gl_info->limits.clipplanes;
4566 pCaps->MaxActiveLights = gl_info->limits.lights;
4568 pCaps->MaxVertexBlendMatrices = gl_info->limits.blends;
4569 pCaps->MaxVertexBlendMatrixIndex = 0;
4571 pCaps->MaxAnisotropy = gl_info->limits.anisotropy;
4572 pCaps->MaxPointSize = gl_info->limits.pointsize_max;
4575 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4576 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4577 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4578 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4579 WINED3DVTXPCAPS_LOCALVIEWER |
4580 WINED3DVTXPCAPS_VERTEXFOG |
4581 WINED3DVTXPCAPS_TEXGEN;
4583 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4584 pCaps->MaxVertexIndex = 0xFFFFF;
4585 pCaps->MaxStreams = MAX_STREAMS;
4586 pCaps->MaxStreamStride = 1024;
4588 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4589 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4590 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4591 pCaps->MaxNpatchTessellationLevel = 0;
4592 pCaps->MasterAdapterOrdinal = 0;
4593 pCaps->AdapterOrdinalInGroup = 0;
4594 pCaps->NumberOfAdaptersInGroup = 1;
4596 pCaps->NumSimultaneousRTs = gl_info->limits.buffers;
4598 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4599 WINED3DPTFILTERCAPS_MAGFPOINT |
4600 WINED3DPTFILTERCAPS_MINFLINEAR |
4601 WINED3DPTFILTERCAPS_MAGFLINEAR;
4602 pCaps->VertexTextureFilterCaps = 0;
4604 adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
4605 adapter->fragment_pipe->get_caps(&adapter->gl_info, &fragment_caps);
4607 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4608 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4610 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4611 * Ignore shader model capabilities if disabled in config
4613 if(vs_selected_mode == SHADER_NONE) {
4614 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4615 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4616 pCaps->MaxVertexShaderConst = 0;
4618 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4619 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4622 if(ps_selected_mode == SHADER_NONE) {
4623 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4624 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4625 pCaps->PixelShader1xMaxValue = 0.0f;
4627 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4628 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4631 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4632 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4633 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4635 /* The following caps are shader specific, but they are things we cannot detect, or which
4636 * are the same among all shader models. So to avoid code duplication set the shader version
4637 * specific, but otherwise constant caps here
4639 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4640 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4641 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4642 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4643 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4644 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_vs_temps);
4645 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4647 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4648 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
4650 else if (pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0))
4652 pCaps->VS20Caps.Caps = 0;
4653 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4654 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_vs_temps);
4655 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4657 pCaps->MaxVShaderInstructionsExecuted = 65535;
4658 pCaps->MaxVertexShader30InstructionSlots = 0;
4659 } else { /* VS 1.x */
4660 pCaps->VS20Caps.Caps = 0;
4661 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4662 pCaps->VS20Caps.NumTemps = 0;
4663 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4665 pCaps->MaxVShaderInstructionsExecuted = 0;
4666 pCaps->MaxVertexShader30InstructionSlots = 0;
4669 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4670 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4671 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4673 /* 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 */
4674 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4675 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4676 WINED3DPS20CAPS_PREDICATION |
4677 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4678 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4679 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4680 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_ps_temps);
4681 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4682 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4684 pCaps->MaxPShaderInstructionsExecuted = 65535;
4685 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS,
4686 adapter->gl_info.limits.arb_ps_instructions);
4688 else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0))
4690 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4691 pCaps->PS20Caps.Caps = 0;
4692 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4693 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_ps_temps);
4694 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4695 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4697 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4698 pCaps->MaxPixelShader30InstructionSlots = 0;
4699 } else { /* PS 1.x */
4700 pCaps->PS20Caps.Caps = 0;
4701 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4702 pCaps->PS20Caps.NumTemps = 0;
4703 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4704 pCaps->PS20Caps.NumInstructionSlots = 0;
4706 pCaps->MaxPShaderInstructionsExecuted = 0;
4707 pCaps->MaxPixelShader30InstructionSlots = 0;
4710 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4711 /* OpenGL supports all the formats below, perhaps not always
4712 * without conversion, but it supports them.
4713 * Further GLSL doesn't seem to have an official unsigned type so
4714 * don't advertise it yet as I'm not sure how we handle it.
4715 * We might need to add some clamping in the shader engine to
4717 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4718 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4719 WINED3DDTCAPS_UBYTE4N |
4720 WINED3DDTCAPS_SHORT2N |
4721 WINED3DDTCAPS_SHORT4N;
4722 if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
4724 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4725 WINED3DDTCAPS_FLOAT16_4;
4728 pCaps->DeclTypes = 0;
4730 /* Set DirectDraw helper Caps */
4731 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4732 WINEDDCKEYCAPS_SRCBLT;
4733 fx_caps = WINEDDFXCAPS_BLTALPHA |
4734 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4735 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4736 WINEDDFXCAPS_BLTROTATION90 |
4737 WINEDDFXCAPS_BLTSHRINKX |
4738 WINEDDFXCAPS_BLTSHRINKXN |
4739 WINEDDFXCAPS_BLTSHRINKY |
4740 WINEDDFXCAPS_BLTSHRINKXN |
4741 WINEDDFXCAPS_BLTSTRETCHX |
4742 WINEDDFXCAPS_BLTSTRETCHXN |
4743 WINEDDFXCAPS_BLTSTRETCHY |
4744 WINEDDFXCAPS_BLTSTRETCHYN;
4745 blit_caps = WINEDDCAPS_BLT |
4746 WINEDDCAPS_BLTCOLORFILL |
4747 WINEDDCAPS_BLTDEPTHFILL |
4748 WINEDDCAPS_BLTSTRETCH |
4749 WINEDDCAPS_CANBLTSYSMEM |
4750 WINEDDCAPS_CANCLIP |
4751 WINEDDCAPS_CANCLIPSTRETCHED |
4752 WINEDDCAPS_COLORKEY |
4753 WINEDDCAPS_COLORKEYHWASSIST |
4754 WINEDDCAPS_ALIGNBOUNDARYSRC;
4756 /* Fill the ddraw caps structure */
4757 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4758 WINEDDCAPS_PALETTE |
4760 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4761 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4762 WINEDDCAPS2_PRIMARYGAMMA |
4763 WINEDDCAPS2_WIDESURFACES |
4764 WINEDDCAPS2_CANRENDERWINDOWED;
4765 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4766 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4767 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4768 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4769 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4770 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4771 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4772 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4773 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4775 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4776 WINEDDSCAPS_BACKBUFFER |
4778 WINEDDSCAPS_FRONTBUFFER |
4779 WINEDDSCAPS_OFFSCREENPLAIN |
4780 WINEDDSCAPS_PALETTE |
4781 WINEDDSCAPS_PRIMARYSURFACE |
4782 WINEDDSCAPS_SYSTEMMEMORY |
4783 WINEDDSCAPS_VIDEOMEMORY |
4784 WINEDDSCAPS_VISIBLE;
4785 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4787 /* Set D3D caps if OpenGL is available. */
4788 if (adapter->opengl)
4790 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4791 WINEDDSCAPS_MIPMAP |
4792 WINEDDSCAPS_TEXTURE |
4793 WINEDDSCAPS_ZBUFFER;
4794 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4800 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT adapter_idx,
4801 WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, IUnknown *parent,
4802 IWineD3DDeviceParent *device_parent, IWineD3DDevice **device)
4804 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4805 IWineD3DDeviceImpl *object;
4808 TRACE("iface %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x.\n"
4809 "parent %p, device_parent %p, device %p.\n",
4810 iface, adapter_idx, device_type, focus_window, flags,
4811 parent, device_parent, device);
4813 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4814 * number and create a device without a 3D adapter for 2D only operation. */
4815 if (IWineD3D_GetAdapterCount(iface) && adapter_idx >= IWineD3D_GetAdapterCount(iface))
4817 return WINED3DERR_INVALIDCALL;
4820 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4823 ERR("Failed to allocate device memory.\n");
4824 return E_OUTOFMEMORY;
4827 hr = device_init(object, This, adapter_idx, device_type, focus_window, flags, parent, device_parent);
4830 WARN("Failed to initialize device, hr %#x.\n", hr);
4831 HeapFree(GetProcessHeap(), 0, object);
4835 TRACE("Created device %p.\n", object);
4836 *device = (IWineD3DDevice *)object;
4838 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *device);
4843 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4844 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4845 IUnknown_AddRef(This->parent);
4846 *pParent = This->parent;
4850 static void WINE_GLAPI invalid_func(const void *data)
4852 ERR("Invalid vertex attribute function called\n");
4856 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4858 ERR("Invalid texcoord function called\n");
4862 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4863 * the extension detection and are used in drawStridedSlow
4865 static void WINE_GLAPI position_d3dcolor(const void *data)
4867 DWORD pos = *((const DWORD *)data);
4869 FIXME("Add a test for fixed function position from d3dcolor type\n");
4870 glVertex4s(D3DCOLOR_B_R(pos),
4876 static void WINE_GLAPI position_float4(const void *data)
4878 const GLfloat *pos = data;
4880 if (pos[3] != 0.0f && pos[3] != 1.0f)
4882 float w = 1.0f / pos[3];
4884 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4892 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4894 DWORD diffuseColor = *((const DWORD *)data);
4896 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4897 D3DCOLOR_B_G(diffuseColor),
4898 D3DCOLOR_B_B(diffuseColor),
4899 D3DCOLOR_B_A(diffuseColor));
4902 static void WINE_GLAPI specular_d3dcolor(const void *data)
4904 DWORD specularColor = *((const DWORD *)data);
4905 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4906 D3DCOLOR_B_G(specularColor),
4907 D3DCOLOR_B_B(specularColor)};
4909 specular_func_3ubv(d);
4912 static void WINE_GLAPI warn_no_specular_func(const void *data)
4914 WARN("GL_EXT_secondary_color not supported\n");
4917 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4919 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4920 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4921 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4922 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4923 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4924 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4925 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4926 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4927 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4928 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4929 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4930 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4931 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4932 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4933 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4934 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4935 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4937 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4938 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4939 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4940 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4941 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4942 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4943 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4944 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4945 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4946 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4947 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4948 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4949 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4950 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4951 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4952 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4953 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4955 /* No 4 component entry points here */
4956 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4957 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4958 if (gl_info->supported[EXT_SECONDARY_COLOR])
4960 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4964 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4966 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4967 if (gl_info->supported[EXT_SECONDARY_COLOR])
4969 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4970 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4974 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4976 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4977 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4978 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4979 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4980 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4981 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4982 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4983 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4984 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4985 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4986 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4987 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4989 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4990 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4992 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4993 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4994 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4995 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4996 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4997 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4998 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4999 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
5000 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
5001 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
5002 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
5003 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
5004 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
5005 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
5006 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
5007 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
5008 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
5010 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
5011 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
5012 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
5013 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
5014 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
5015 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
5016 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
5017 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
5018 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
5019 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
5020 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
5021 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
5022 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
5023 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
5024 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
5025 if (gl_info->supported[NV_HALF_FLOAT])
5027 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
5028 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
5029 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
5031 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
5032 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
5036 static BOOL InitAdapters(IWineD3DImpl *This)
5038 static HMODULE mod_gl;
5040 int ps_selected_mode, vs_selected_mode;
5042 /* No need to hold any lock. The calling library makes sure only one thread calls
5043 * wined3d simultaneously
5046 TRACE("Initializing adapters\n");
5049 #ifdef USE_WIN32_OPENGL
5050 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
5051 mod_gl = LoadLibraryA("opengl32.dll");
5053 ERR("Can't load opengl32.dll!\n");
5057 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
5058 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
5059 mod_gl = GetModuleHandleA("gdi32.dll");
5063 /* Load WGL core functions from opengl32.dll */
5064 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
5068 if(!pwglGetProcAddress) {
5069 ERR("Unable to load wglGetProcAddress!\n");
5073 /* Dynamically load all GL core functions */
5077 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
5078 * otherwise because we have to use winex11.drv's override
5080 #ifdef USE_WIN32_OPENGL
5081 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
5082 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
5084 wglFinish = (void*)pwglGetProcAddress("wglFinish");
5085 wglFlush = (void*)pwglGetProcAddress("wglFlush");
5088 glEnableWINE = glEnable;
5089 glDisableWINE = glDisable;
5091 /* For now only one default adapter */
5093 struct wined3d_adapter *adapter = &This->adapters[0];
5094 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
5095 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
5099 WineD3D_PixelFormat *cfgs;
5100 DISPLAY_DEVICEW DisplayDevice;
5103 TRACE("Initializing default adapter\n");
5104 adapter->ordinal = 0;
5105 adapter->monitorPoint.x = -1;
5106 adapter->monitorPoint.y = -1;
5108 if (!AllocateLocallyUniqueId(&adapter->luid))
5110 DWORD err = GetLastError();
5111 ERR("Failed to set adapter LUID (%#x).\n", err);
5114 TRACE("Allocated LUID %08x:%08x for adapter.\n",
5115 adapter->luid.HighPart, adapter->luid.LowPart);
5117 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
5119 ERR("Failed to get a gl context for default adapter\n");
5123 ret = IWineD3DImpl_FillGLCaps(adapter);
5125 ERR("Failed to initialize gl caps for default adapter\n");
5126 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5129 ret = initPixelFormats(&adapter->gl_info, adapter->driver_info.vendor);
5131 ERR("Failed to init gl formats\n");
5132 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5136 hdc = fake_gl_ctx.dc;
5138 /* Use the VideoRamSize registry setting when set */
5139 if(wined3d_settings.emulated_textureram)
5140 adapter->TextureRam = wined3d_settings.emulated_textureram;
5142 adapter->TextureRam = adapter->gl_info.vidmem;
5143 adapter->UsedTextureRam = 0;
5144 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
5146 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
5147 DisplayDevice.cb = sizeof(DisplayDevice);
5148 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
5149 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
5150 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
5152 if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
5159 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
5160 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
5162 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
5163 cfgs = adapter->cfgs;
5164 attribs[nAttribs++] = WGL_RED_BITS_ARB;
5165 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
5166 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
5167 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
5168 attribs[nAttribs++] = WGL_COLOR_BITS_ARB;
5169 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
5170 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
5171 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
5172 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
5173 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
5174 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
5176 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
5178 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
5183 /* Cache the pixel format */
5184 cfgs->iPixelFormat = iPixelFormat;
5185 cfgs->redSize = values[0];
5186 cfgs->greenSize = values[1];
5187 cfgs->blueSize = values[2];
5188 cfgs->alphaSize = values[3];
5189 cfgs->colorSize = values[4];
5190 cfgs->depthSize = values[5];
5191 cfgs->stencilSize = values[6];
5192 cfgs->windowDrawable = values[7];
5193 cfgs->iPixelType = values[8];
5194 cfgs->doubleBuffer = values[9];
5195 cfgs->auxBuffers = values[10];
5197 cfgs->numSamples = 0;
5198 /* Check multisample support */
5199 if (gl_info->supported[ARB_MULTISAMPLE])
5201 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
5203 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
5204 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
5205 * value[1] = number of multi sample buffers*/
5207 cfgs->numSamples = value[1];
5211 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
5212 "depth=%d, stencil=%d, samples=%d, windowDrawable=%d\n",
5213 cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer,
5214 cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize,
5215 cfgs->depthSize, cfgs->stencilSize, cfgs->numSamples, cfgs->windowDrawable);
5221 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
5222 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
5223 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
5225 cfgs = adapter->cfgs;
5226 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
5228 PIXELFORMATDESCRIPTOR ppfd;
5230 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
5234 /* We only want HW acceleration using an OpenGL ICD driver.
5235 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
5236 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
5238 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
5240 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
5244 cfgs->iPixelFormat = iPixelFormat;
5245 cfgs->redSize = ppfd.cRedBits;
5246 cfgs->greenSize = ppfd.cGreenBits;
5247 cfgs->blueSize = ppfd.cBlueBits;
5248 cfgs->alphaSize = ppfd.cAlphaBits;
5249 cfgs->colorSize = ppfd.cColorBits;
5250 cfgs->depthSize = ppfd.cDepthBits;
5251 cfgs->stencilSize = ppfd.cStencilBits;
5252 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
5253 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
5254 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
5255 cfgs->auxBuffers = ppfd.cAuxBuffers;
5256 cfgs->numSamples = 0;
5258 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
5259 "depth=%d, stencil=%d, windowDrawable=%d\n",
5260 cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer,
5261 cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize,
5262 cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable);
5267 /* 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 */
5270 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
5272 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5273 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
5278 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
5279 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
5280 * but just fake it using D24(X8?) which is fine. D3D also allows that.
5281 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
5282 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
5283 * driver is allowed to consume more bits EXCEPT for stencil bits.
5285 * Mark an adapter with this broken stencil behavior.
5287 adapter->brokenStencil = TRUE;
5288 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
5290 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
5291 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
5292 adapter->brokenStencil = FALSE;
5297 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5299 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
5300 fillGLAttribFuncs(&adapter->gl_info);
5301 adapter->opengl = TRUE;
5303 This->adapter_count = 1;
5304 TRACE("%u adapters successfully initialized\n", This->adapter_count);
5309 /* Initialize an adapter for ddraw-only memory counting */
5310 memset(This->adapters, 0, sizeof(This->adapters));
5311 This->adapters[0].ordinal = 0;
5312 This->adapters[0].opengl = FALSE;
5313 This->adapters[0].monitorPoint.x = -1;
5314 This->adapters[0].monitorPoint.y = -1;
5316 This->adapters[0].driver_info.name = "Display";
5317 This->adapters[0].driver_info.description = "WineD3D DirectDraw Emulation";
5318 if(wined3d_settings.emulated_textureram) {
5319 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
5321 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
5324 initPixelFormatsNoGL(&This->adapters[0].gl_info);
5326 This->adapter_count = 1;
5330 /**********************************************************
5331 * IWineD3D VTbl follows
5332 **********************************************************/
5334 static const struct IWineD3DVtbl IWineD3D_Vtbl =
5337 IWineD3DImpl_QueryInterface,
5338 IWineD3DImpl_AddRef,
5339 IWineD3DImpl_Release,
5341 IWineD3DImpl_GetParent,
5342 IWineD3DImpl_GetAdapterCount,
5343 IWineD3DImpl_RegisterSoftwareDevice,
5344 IWineD3DImpl_GetAdapterMonitor,
5345 IWineD3DImpl_GetAdapterModeCount,
5346 IWineD3DImpl_EnumAdapterModes,
5347 IWineD3DImpl_GetAdapterDisplayMode,
5348 IWineD3DImpl_GetAdapterIdentifier,
5349 IWineD3DImpl_CheckDeviceMultiSampleType,
5350 IWineD3DImpl_CheckDepthStencilMatch,
5351 IWineD3DImpl_CheckDeviceType,
5352 IWineD3DImpl_CheckDeviceFormat,
5353 IWineD3DImpl_CheckDeviceFormatConversion,
5354 IWineD3DImpl_GetDeviceCaps,
5355 IWineD3DImpl_CreateDevice
5358 static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
5360 const struct wined3d_parent_ops wined3d_null_parent_ops =
5362 wined3d_null_wined3d_object_destroyed,
5365 HRESULT wined3d_init(IWineD3DImpl *wined3d, UINT version, IUnknown *parent)
5367 wined3d->lpVtbl = &IWineD3D_Vtbl;
5368 wined3d->dxVersion = version;
5370 wined3d->parent = parent;
5372 if (!InitAdapters(wined3d))
5374 WARN("Failed to initialize adapters.\n");
5377 MESSAGE("Direct3D%u is not available without OpenGL.\n", version);