wined3d: Start moving paletted texture support to the blit_shader.
[wine/hacks.git] / dlls / wined3d / directx.c
blob9b70eb34f7b41ce7a2ca55b9532a38898ecb206d
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
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
26 #include "config.h"
27 #include "wined3d_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
32 #define GLINFO_LOCATION (*gl_info)
33 #define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024)
34 #define MAKEDWORD_VERSION(maj, min) ((maj & 0xffff) << 16) | (min & 0xffff)
36 /* The d3d device ID */
37 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
39 /* Extension detection */
40 static const struct {
41 const char *extension_string;
42 GL_SupportedExt extension;
43 DWORD version;
44 } EXTENSION_MAP[] = {
45 /* APPLE */
46 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
47 {"GL_APPLE_fence", APPLE_FENCE, 0 },
48 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
49 {"GL_APPLE_flush_buffer_range", APPLE_FLUSH_BUFFER_RANGE, 0 },
50 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
51 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
53 /* ARB */
54 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
55 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
56 {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP, 0 },
57 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
58 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
59 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
60 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
61 {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT, 0 },
62 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
63 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
64 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
65 {"GL_ARB_imaging", ARB_IMAGING, 0 },
66 {"GL_ARB_map_buffer_range", ARB_MAP_BUFFER_RANGE, 0 },
67 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
68 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
69 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
70 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
71 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
72 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
73 {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX, 0 },
74 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
75 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
76 {"GL_ARB_shading_language_100", ARB_SHADING_LANGUAGE_100, 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 },
95 /* ATI */
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 },
102 /* EXT */
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_fog_coord", EXT_FOG_COORD, 0 },
108 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
109 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
110 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
111 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
112 {"GL_EXT_gpu_shader4", EXT_GPU_SHADER4, 0 },
113 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
114 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
115 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
116 {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 },
117 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
118 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
119 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
120 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
121 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
122 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
123 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
124 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
125 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
126 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
127 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
128 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
129 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
131 /* NV */
132 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
133 {"GL_NV_fence", NV_FENCE, 0 },
134 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
135 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
136 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
137 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
138 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
139 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
140 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
141 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
142 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
143 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
144 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
145 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
146 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
147 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
148 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
149 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
150 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
152 /* SGI */
153 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
156 /**********************************************************
157 * Utility functions follow
158 **********************************************************/
160 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
162 const struct min_lookup minMipLookup[] =
164 /* NONE POINT LINEAR */
165 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
166 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
167 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
170 const struct min_lookup minMipLookup_noFilter[] =
172 /* NONE POINT LINEAR */
173 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
174 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
175 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
178 const struct min_lookup minMipLookup_noMip[] =
180 /* NONE POINT LINEAR */
181 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
182 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
183 {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */
186 const GLenum magLookup[] =
188 /* NONE POINT LINEAR */
189 GL_NEAREST, GL_NEAREST, GL_LINEAR,
192 const GLenum magLookup_noFilter[] =
194 /* NONE POINT LINEAR */
195 GL_NEAREST, GL_NEAREST, GL_NEAREST,
198 /* drawStridedSlow attributes */
199 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
200 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
201 glAttribFunc specular_func_3ubv;
202 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
203 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
204 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
207 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
208 * i.e., there is no GL Context - Get a default rendering context to enable the
209 * function query some info from GL.
212 struct wined3d_fake_gl_ctx
214 HDC dc;
215 HWND wnd;
216 HGLRC gl_ctx;
217 HDC restore_dc;
218 HGLRC restore_gl_ctx;
221 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
223 TRACE_(d3d_caps)("Destroying fake GL context.\n");
225 if (!pwglMakeCurrent(NULL, NULL))
227 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
230 if (!pwglDeleteContext(ctx->gl_ctx))
232 DWORD err = GetLastError();
233 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
236 ReleaseDC(ctx->wnd, ctx->dc);
237 DestroyWindow(ctx->wnd);
239 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
241 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
245 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
247 PIXELFORMATDESCRIPTOR pfd;
248 int iPixelFormat;
250 TRACE("getting context...\n");
252 ctx->restore_dc = pwglGetCurrentDC();
253 ctx->restore_gl_ctx = pwglGetCurrentContext();
255 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
256 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
257 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
258 if (!ctx->wnd)
260 ERR_(d3d_caps)("Failed to create a window.\n");
261 goto fail;
264 ctx->dc = GetDC(ctx->wnd);
265 if (!ctx->dc)
267 ERR_(d3d_caps)("Failed to get a DC.\n");
268 goto fail;
271 /* PixelFormat selection */
272 ZeroMemory(&pfd, sizeof(pfd));
273 pfd.nSize = sizeof(pfd);
274 pfd.nVersion = 1;
275 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
276 pfd.iPixelType = PFD_TYPE_RGBA;
277 pfd.cColorBits = 32;
278 pfd.iLayerType = PFD_MAIN_PLANE;
280 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
281 if (!iPixelFormat)
283 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
284 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
285 goto fail;
287 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
288 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
290 /* Create a GL context. */
291 ctx->gl_ctx = pwglCreateContext(ctx->dc);
292 if (!ctx->gl_ctx)
294 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
295 goto fail;
298 /* Make it the current GL context. */
299 if (!context_set_current(NULL))
301 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
304 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
306 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
307 goto fail;
310 return TRUE;
312 fail:
313 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
314 ctx->gl_ctx = NULL;
315 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
316 ctx->dc = NULL;
317 if (ctx->wnd) DestroyWindow(ctx->wnd);
318 ctx->wnd = NULL;
319 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
321 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
324 return FALSE;
327 /* Adjust the amount of used texture memory */
328 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram)
330 struct wined3d_adapter *adapter = D3DDevice->adapter;
332 adapter->UsedTextureRam += glram;
333 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
334 return adapter->UsedTextureRam;
337 static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
339 HeapFree(GetProcessHeap(), 0, adapter->gl_info.gl_formats);
340 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
343 /**********************************************************
344 * IUnknown parts follows
345 **********************************************************/
347 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
351 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
352 if (IsEqualGUID(riid, &IID_IUnknown)
353 || IsEqualGUID(riid, &IID_IWineD3DBase)
354 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
355 IUnknown_AddRef(iface);
356 *ppobj = This;
357 return S_OK;
359 *ppobj = NULL;
360 return E_NOINTERFACE;
363 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
364 IWineD3DImpl *This = (IWineD3DImpl *)iface;
365 ULONG refCount = InterlockedIncrement(&This->ref);
367 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
368 return refCount;
371 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
372 IWineD3DImpl *This = (IWineD3DImpl *)iface;
373 ULONG ref;
374 TRACE("(%p) : Releasing from %d\n", This, This->ref);
375 ref = InterlockedDecrement(&This->ref);
376 if (ref == 0) {
377 unsigned int i;
379 for (i = 0; i < This->adapter_count; ++i)
381 wined3d_adapter_cleanup(&This->adapters[i]);
383 HeapFree(GetProcessHeap(), 0, This);
386 return ref;
389 /**********************************************************
390 * IWineD3D parts follows
391 **********************************************************/
393 /* GL locking is done by the caller */
394 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
396 GLuint prog;
397 BOOL ret = FALSE;
398 const char *testcode =
399 "!!ARBvp1.0\n"
400 "PARAM C[66] = { program.env[0..65] };\n"
401 "ADDRESS A0;"
402 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
403 "ARL A0.x, zero.x;\n"
404 "MOV result.position, C[A0.x + 65];\n"
405 "END\n";
407 while(glGetError());
408 GL_EXTCALL(glGenProgramsARB(1, &prog));
409 if(!prog) {
410 ERR("Failed to create an ARB offset limit test program\n");
412 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
413 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
414 strlen(testcode), testcode));
415 if(glGetError() != 0) {
416 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
417 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
418 ret = TRUE;
419 } else TRACE("OpenGL implementation allows offsets > 63\n");
421 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
422 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
423 checkGLcall("ARB vp offset limit test cleanup");
425 return ret;
428 static DWORD ver_for_ext(GL_SupportedExt ext)
430 unsigned int i;
431 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
432 if(EXTENSION_MAP[i].extension == ext) {
433 return EXTENSION_MAP[i].version;
436 return 0;
439 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
440 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
442 if (card_vendor != HW_VENDOR_ATI) return FALSE;
443 if (device == CARD_ATI_RADEON_9500) return TRUE;
444 if (device == CARD_ATI_RADEON_X700) return TRUE;
445 if (device == CARD_ATI_RADEON_X1600) return TRUE;
446 return FALSE;
449 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
450 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
452 if (card_vendor == HW_VENDOR_NVIDIA)
454 if (device == CARD_NVIDIA_GEFORCEFX_5800 || device == CARD_NVIDIA_GEFORCEFX_5600)
456 return TRUE;
459 return FALSE;
462 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
463 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
465 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
466 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
467 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
469 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
470 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
471 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
472 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
473 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
474 * the chance that other implementations support them is rather small since Win32 QuickTime uses
475 * DirectDraw, not OpenGL.
477 * This test has been moved into wined3d_guess_gl_vendor()
479 if (gl_vendor == GL_VENDOR_APPLE)
481 return TRUE;
483 return FALSE;
486 /* Context activation is done by the caller. */
487 static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
489 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
490 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
491 * all the texture. This function detects this bug by its symptom and disables PBOs
492 * if the test fails.
494 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
495 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
496 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
497 * read back is compared to the original. If they are equal PBOs are assumed to work,
498 * otherwise the PBO extension is disabled. */
499 GLuint texture, pbo;
500 static const unsigned int pattern[] =
502 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
503 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
504 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
505 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
507 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
509 /* No PBO -> No point in testing them. */
510 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
512 ENTER_GL();
514 while (glGetError());
515 glGenTextures(1, &texture);
516 glBindTexture(GL_TEXTURE_2D, texture);
518 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
519 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
520 checkGLcall("Specifying the PBO test texture");
522 GL_EXTCALL(glGenBuffersARB(1, &pbo));
523 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
524 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
525 checkGLcall("Specifying the PBO test pbo");
527 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
528 checkGLcall("Loading the PBO test texture");
530 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
531 wglFinish(); /* just to be sure */
533 memset(check, 0, sizeof(check));
534 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
535 checkGLcall("Reading back the PBO test texture");
537 glDeleteTextures(1, &texture);
538 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
539 checkGLcall("PBO test cleanup");
541 LEAVE_GL();
543 if (memcmp(check, pattern, sizeof(check)))
545 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
546 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
547 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
549 else
551 TRACE_(d3d_caps)("PBO test successful.\n");
555 static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
556 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
558 return (card_vendor == HW_VENDOR_INTEL) && (gl_vendor == GL_VENDOR_APPLE);
561 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
562 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
564 if (gl_vendor != GL_VENDOR_APPLE) return FALSE;
565 if (card_vendor != HW_VENDOR_ATI) return FALSE;
566 if (device == CARD_ATI_RADEON_X1600) return FALSE;
567 return TRUE;
570 static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
571 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
573 return (gl_vendor == GL_VENDOR_ATI);
577 static BOOL match_dx10_capable(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 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
581 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
582 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
583 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
584 * hardcoded
586 * dx10 cards usually have 64 varyings */
587 return gl_info->limits.glsl_varyings > 44;
590 /* A GL context is provided by the caller */
591 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
592 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
594 GLenum error;
595 DWORD data[16];
597 if (!gl_info->supported[EXT_SECONDARY_COLOR]) return FALSE;
599 ENTER_GL();
600 while(glGetError());
601 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
602 error = glGetError();
603 LEAVE_GL();
605 if(error == GL_NO_ERROR)
607 TRACE("GL Implementation accepts 4 component specular color pointers\n");
608 return TRUE;
610 else
612 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
613 debug_glerror(error));
614 return FALSE;
618 static BOOL match_apple_nvts(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
619 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
621 if (!match_apple(gl_info, gl_renderer, gl_vendor, card_vendor, device)) return FALSE;
622 return gl_info->supported[NV_TEXTURE_SHADER];
625 /* A GL context is provided by the caller */
626 static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
627 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
629 GLuint prog;
630 BOOL ret = FALSE;
631 GLint pos;
632 const char *testcode =
633 "!!ARBvp1.0\n"
634 "OPTION NV_vertex_program2;\n"
635 "MOV result.clip[0], 0.0;\n"
636 "MOV result.position, 0.0;\n"
637 "END\n";
639 if (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]) return FALSE;
641 ENTER_GL();
642 while(glGetError());
644 GL_EXTCALL(glGenProgramsARB(1, &prog));
645 if(!prog)
647 ERR("Failed to create the NVvp clip test program\n");
648 LEAVE_GL();
649 return FALSE;
651 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
652 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
653 strlen(testcode), testcode));
654 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
655 if(pos != -1)
657 WARN("GL_NV_vertex_program2_option result.clip[] test failed\n");
658 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
659 ret = TRUE;
660 while(glGetError());
662 else TRACE("GL_NV_vertex_program2_option result.clip[] test passed\n");
664 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
665 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
666 checkGLcall("GL_NV_vertex_program2_option result.clip[] test cleanup");
668 LEAVE_GL();
669 return ret;
672 static BOOL match_fbo_tex_update(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
673 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
675 char data[4 * 4 * 4];
676 GLuint tex, fbo;
677 GLenum status;
679 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return FALSE;
681 memset(data, 0xcc, sizeof(data));
683 glGenTextures(1, &tex);
684 glBindTexture(GL_TEXTURE_2D, tex);
685 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
686 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
687 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
688 checkGLcall("glTexImage2D");
690 gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
691 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
692 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
693 checkGLcall("glFramebufferTexture2D");
695 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
696 if (status != GL_FRAMEBUFFER_COMPLETE) ERR("FBO status %#x\n", status);
697 checkGLcall("glCheckFramebufferStatus");
699 memset(data, 0x11, sizeof(data));
700 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
701 checkGLcall("glTexSubImage2D");
703 glClearColor(0.996, 0.729, 0.745, 0.792);
704 glClear(GL_COLOR_BUFFER_BIT);
705 checkGLcall("glClear");
707 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
708 checkGLcall("glGetTexImage");
710 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
711 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
712 glBindTexture(GL_TEXTURE_2D, 0);
713 checkGLcall("glBindTexture");
715 gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
716 glDeleteTextures(1, &tex);
717 checkGLcall("glDeleteTextures");
719 return *(DWORD *)data == 0x11111111;
722 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
724 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->limits.arb_vs_native_constants);
725 gl_info->limits.glsl_vs_float_constants = gl_info->limits.arb_vs_native_constants;
726 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->limits.arb_ps_native_constants);
727 gl_info->limits.glsl_ps_float_constants = gl_info->limits.arb_ps_native_constants;
730 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
732 quirk_arb_constants(gl_info);
733 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
734 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
735 * allow 48 different offsets or other helper immediate values. */
736 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
737 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
740 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
741 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
742 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
743 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
744 * most games, but avoids the crash
746 * A more sophisticated way would be to find all units that need texture coordinates and enable
747 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
748 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
750 * Note that disabling the extension entirely does not gain predictability because there is no point
751 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
752 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
754 if (gl_info->supported[ARB_POINT_SPRITE])
756 TRACE("Limiting point sprites to one texture unit.\n");
757 gl_info->limits.point_sprite_units = 1;
761 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
763 quirk_arb_constants(gl_info);
765 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
766 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
767 * If real NP2 textures are used, the driver falls back to software. We could just remove the
768 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
769 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
770 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
771 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
773 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
774 * has this extension promoted to core. The extension loading code sets this extension supported
775 * due to that, so this code works on fglrx as well. */
776 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
778 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
779 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
780 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
783 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
784 * it is generally more efficient. Reserve just 8 constants. */
785 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
786 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
789 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
791 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
792 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
793 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
794 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
795 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
796 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
798 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
799 * triggering the software fallback. There is not much we can do here apart from disabling the
800 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
801 * in IWineD3DImpl_FillGLCaps).
802 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
803 * post-processing effects in the game "Max Payne 2").
804 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
805 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
806 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
807 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
810 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
812 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
813 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
814 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
815 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
816 * according to the spec.
818 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
819 * makes the shader slower and eats instruction slots which should be available to the d3d app.
821 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
822 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
823 * this workaround is activated on cards that do not need it, it won't break things, just affect
824 * performance negatively. */
825 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
826 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
829 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
831 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
834 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
836 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
839 static void quirk_apple_nvts(struct wined3d_gl_info *gl_info)
841 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
842 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
845 static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info)
847 gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN;
850 static void quirk_fbo_tex_update(struct wined3d_gl_info *gl_info)
852 gl_info->quirks |= WINED3D_QUIRK_FBO_TEX_UPDATE;
855 struct driver_quirk
857 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
858 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device);
859 void (*apply)(struct wined3d_gl_info *gl_info);
860 const char *description;
863 static const struct driver_quirk quirk_table[] =
866 match_ati_r300_to_500,
867 quirk_ati_dx9,
868 "ATI GLSL constant and normalized texrect quirk"
870 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
871 * used it falls back to software. While the compiler can detect if the shader uses all declared
872 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
873 * using relative addressing falls back to software.
875 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
877 match_apple,
878 quirk_apple_glsl_constants,
879 "Apple GLSL uniform override"
882 match_geforce5,
883 quirk_no_np2,
884 "Geforce 5 NP2 disable"
887 match_apple_intel,
888 quirk_texcoord_w,
889 "Init texcoord .w for Apple Intel GPU driver"
892 match_apple_nonr500ati,
893 quirk_texcoord_w,
894 "Init texcoord .w for Apple ATI >= r600 GPU driver"
897 match_fglrx,
898 quirk_one_point_sprite,
899 "Fglrx point sprite crash workaround"
902 match_dx10_capable,
903 quirk_clip_varying,
904 "Reserved varying for gl_ClipPos"
907 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
908 * GL implementations accept it. The Mac GL is the only implementation known to
909 * reject it.
911 * If we can pass 4 component specular colors, do it, because (a) we don't have
912 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
913 * passes specular alpha to the pixel shader if any is used. Otherwise the
914 * specular alpha is used to pass the fog coordinate, which we pass to opengl
915 * via GL_EXT_fog_coord.
917 match_allows_spec_alpha,
918 quirk_allows_specular_alpha,
919 "Allow specular alpha quirk"
922 /* The pixel formats provided by GL_NV_texture_shader are broken on OSX
923 * (rdar://5682521).
925 match_apple_nvts,
926 quirk_apple_nvts,
927 "Apple NV_texture_shader disable"
930 match_broken_nv_clip,
931 quirk_disable_nvvp_clip,
932 "Apple NV_vertex_program clip bug quirk"
935 match_fbo_tex_update,
936 quirk_fbo_tex_update,
937 "FBO rebind for attachment updates"
941 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
942 * reporting a driver version is moot because we are not the Windows driver, and we have different
943 * bugs, features, etc.
945 * The driver version has the form "x.y.z.w".
947 * "x" is the Windows version the driver is meant for:
948 * 4 -> 95/98/NT4
949 * 5 -> 2000
950 * 6 -> 2000/XP
951 * 7 -> Vista
952 * 8 -> Win 7
954 * "y" is the Direct3D level the driver supports:
955 * 11 -> d3d6
956 * 12 -> d3d7
957 * 13 -> d3d8
958 * 14 -> d3d9
959 * 15 -> d3d10
961 * "z" is unknown, possibly vendor specific.
963 * "w" is the vendor specific driver version.
965 struct driver_version_information
967 WORD vendor; /* reported PCI card vendor ID */
968 WORD card; /* reported PCI card device ID */
969 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
970 WORD d3d_level; /* driver hiword to report */
971 WORD lopart_hi, lopart_lo; /* driver loword to report */
974 static const struct driver_version_information driver_version_table[] =
976 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
977 * 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
978 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
979 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
981 * All version numbers used below are from the Linux nvidia drivers. */
982 {HW_VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 1, 8, 6 },
983 {HW_VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 1, 8, 6 },
984 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 1, 8, 6 },
985 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 6, 4, 3 },
986 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 1, 8, 6 },
987 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 6, 10, 9371 },
988 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 6, 10, 9371 },
989 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 6, 10, 9371 },
990 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 15, 11, 7516 },
991 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 15, 11, 7516 },
992 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 15, 11, 7516 },
993 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 15, 11, 8618 },
994 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 15, 11, 8618 },
995 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 15, 11, 8618 },
996 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 15, 11, 8585 },
997 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 15, 11, 8585 },
998 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 15, 11, 8618 },
999 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 15, 11, 8618 },
1000 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 15, 11, 8618 },
1001 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 15, 11, 8618 },
1002 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 15, 11, 8585 },
1003 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 15, 11, 8618 },
1004 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 15, 11, 8618 },
1005 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 15, 11, 8618 },
1006 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 15, 11, 8618 },
1007 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 15, 11, 8618 },
1008 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 15, 11, 8618 },
1009 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 15, 11, 8618 },
1010 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 15, 11, 8618 },
1011 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 15, 11, 8618 },
1012 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GT240, "NVIDIA GeForce GT 240", 15, 11, 8618 },
1014 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
1015 {HW_VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 14, 10, 6764 },
1016 {HW_VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 14, 10, 6764 },
1017 {HW_VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 14, 10, 6764 },
1018 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 14, 10, 6764 },
1019 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 14, 10, 6764 },
1020 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 14, 10, 6764 },
1021 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 14, 10, 6764 },
1022 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 14, 10, 6764 },
1023 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 14, 10, 6764 },
1024 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 14, 10, 6764 },
1025 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD5700, "ATI Radeon HD 5700 Series", 14, 10, 8681 },
1026 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD5800, "ATI Radeon HD 5800 Series", 14, 10, 8681 },
1028 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
1031 static void init_driver_info(struct wined3d_driver_info *driver_info,
1032 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
1034 OSVERSIONINFOW os_version;
1035 WORD driver_os_version;
1036 unsigned int i;
1038 if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1040 TRACE_(d3d_caps)("Overriding PCI vendor ID with: %04x\n", wined3d_settings.pci_vendor_id);
1041 vendor = wined3d_settings.pci_vendor_id;
1043 driver_info->vendor = vendor;
1045 if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1047 TRACE_(d3d_caps)("Overriding PCI device ID with: %04x\n", wined3d_settings.pci_device_id);
1048 device = wined3d_settings.pci_device_id;
1050 driver_info->device = device;
1052 switch (vendor)
1054 case HW_VENDOR_ATI:
1055 driver_info->name = "ati2dvag.dll";
1056 break;
1058 case HW_VENDOR_NVIDIA:
1059 driver_info->name = "nv4_disp.dll";
1060 break;
1062 case HW_VENDOR_INTEL:
1063 default:
1064 FIXME_(d3d_caps)("Unhandled vendor %04x.\n", vendor);
1065 driver_info->name = "Display";
1066 break;
1069 memset(&os_version, 0, sizeof(os_version));
1070 os_version.dwOSVersionInfoSize = sizeof(os_version);
1071 if (!GetVersionExW(&os_version))
1073 ERR("Failed to get OS version, reporting 2000/XP.\n");
1074 driver_os_version = 6;
1076 else
1078 TRACE("OS version %u.%u.\n", os_version.dwMajorVersion, os_version.dwMinorVersion);
1079 switch (os_version.dwMajorVersion)
1081 case 4:
1082 driver_os_version = 4;
1083 break;
1085 case 5:
1086 driver_os_version = 6;
1087 break;
1089 case 6:
1090 if (os_version.dwMinorVersion == 0)
1092 driver_os_version = 7;
1094 else
1096 if (os_version.dwMinorVersion > 1)
1098 FIXME("Unhandled OS version %u.%u, reporting Win 7.\n",
1099 os_version.dwMajorVersion, os_version.dwMinorVersion);
1101 driver_os_version = 8;
1103 break;
1105 default:
1106 FIXME("Unhandled OS version %u.%u, reporting 2000/XP.\n",
1107 os_version.dwMajorVersion, os_version.dwMinorVersion);
1108 driver_os_version = 6;
1109 break;
1113 driver_info->description = "Direct3D HAL";
1114 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
1115 driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
1117 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
1119 if (vendor == driver_version_table[i].vendor && device == driver_version_table[i].card)
1121 TRACE_(d3d_caps)("Found card %04x:%04x in driver DB.\n", vendor, device);
1123 driver_info->description = driver_version_table[i].description;
1124 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, driver_version_table[i].d3d_level);
1125 driver_info->version_low = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
1126 driver_version_table[i].lopart_lo);
1127 break;
1131 TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08x-0x%08x.\n",
1132 driver_info->version_high, driver_info->version_low);
1135 /* Context activation is done by the caller. */
1136 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer,
1137 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
1139 unsigned int i;
1141 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
1143 if (!quirk_table[i].match(gl_info, gl_renderer, gl_vendor, card_vendor, device)) continue;
1144 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
1145 quirk_table[i].apply(gl_info);
1148 /* Find out if PBOs work as they are supposed to. */
1149 test_pbo_functionality(gl_info);
1152 static DWORD wined3d_parse_gl_version(const char *gl_version)
1154 const char *ptr = gl_version;
1155 int major, minor;
1157 major = atoi(ptr);
1158 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
1160 while (isdigit(*ptr)) ++ptr;
1161 if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version));
1163 minor = atoi(ptr);
1165 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
1167 return MAKEDWORD_VERSION(major, minor);
1170 static enum wined3d_gl_vendor wined3d_guess_gl_vendor(struct wined3d_gl_info *gl_info, const char *gl_vendor_string, const char *gl_renderer)
1173 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
1174 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
1175 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
1177 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
1178 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
1179 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
1180 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
1181 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
1182 * the chance that other implementations support them is rather small since Win32 QuickTime uses
1183 * DirectDraw, not OpenGL. */
1184 if (gl_info->supported[APPLE_FENCE]
1185 && gl_info->supported[APPLE_CLIENT_STORAGE]
1186 && gl_info->supported[APPLE_FLUSH_RENDER]
1187 && gl_info->supported[APPLE_YCBCR_422])
1188 return GL_VENDOR_APPLE;
1190 if (strstr(gl_vendor_string, "NVIDIA"))
1191 return GL_VENDOR_NVIDIA;
1193 if (strstr(gl_vendor_string, "ATI"))
1194 return GL_VENDOR_ATI;
1196 if (strstr(gl_vendor_string, "Intel(R)")
1197 || strstr(gl_renderer, "Intel(R)")
1198 || strstr(gl_vendor_string, "Intel Inc."))
1199 return GL_VENDOR_INTEL;
1201 if (strstr(gl_vendor_string, "Mesa")
1202 || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
1203 || strstr(gl_vendor_string, "DRI R300 Project")
1204 || strstr(gl_vendor_string, "X.Org R300 Project")
1205 || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
1206 || strstr(gl_vendor_string, "VMware, Inc.")
1207 || strstr(gl_renderer, "Mesa")
1208 || strstr(gl_renderer, "Gallium"))
1209 return GL_VENDOR_MESA;
1211 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning GL_VENDOR_WINE.\n", debugstr_a(gl_vendor_string));
1213 return GL_VENDOR_WINE;
1216 static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_string, const char *gl_renderer)
1218 if (strstr(gl_vendor_string, "NVIDIA"))
1219 return HW_VENDOR_NVIDIA;
1221 if (strstr(gl_vendor_string, "ATI")
1222 || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
1223 || strstr(gl_vendor_string, "X.Org R300 Project")
1224 || strstr(gl_vendor_string, "DRI R300 Project"))
1225 return HW_VENDOR_ATI;
1227 if (strstr(gl_vendor_string, "Intel(R)")
1228 || strstr(gl_renderer, "Intel(R)")
1229 || strstr(gl_vendor_string, "Intel Inc."))
1230 return HW_VENDOR_INTEL;
1232 if (strstr(gl_vendor_string, "Mesa")
1233 || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
1234 || strstr(gl_vendor_string, "VMware, Inc."))
1235 return HW_VENDOR_WINE;
1237 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning HW_VENDOR_NVIDIA.\n", debugstr_a(gl_vendor_string));
1239 return HW_VENDOR_NVIDIA;
1244 enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1245 unsigned int *vidmem )
1247 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1248 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1250 if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3])
1252 /* Geforce 200 - highend */
1253 if (strstr(gl_renderer, "GTX 280")
1254 || strstr(gl_renderer, "GTX 285")
1255 || strstr(gl_renderer, "GTX 295"))
1257 *vidmem = 1024;
1258 return CARD_NVIDIA_GEFORCE_GTX280;
1261 /* Geforce 200 - midend high */
1262 if (strstr(gl_renderer, "GTX 275"))
1264 *vidmem = 896;
1265 return CARD_NVIDIA_GEFORCE_GTX275;
1268 /* Geforce 200 - midend */
1269 if (strstr(gl_renderer, "GTX 260"))
1271 *vidmem = 1024;
1272 return CARD_NVIDIA_GEFORCE_GTX260;
1274 /* Geforce 200 - midend */
1275 if (strstr(gl_renderer, "GT 240"))
1277 *vidmem = 512;
1278 return CARD_NVIDIA_GEFORCE_GT240;
1281 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1282 if (strstr(gl_renderer, "9800")
1283 || strstr(gl_renderer, "GTS 150")
1284 || strstr(gl_renderer, "GTS 250"))
1286 *vidmem = 512;
1287 return CARD_NVIDIA_GEFORCE_9800GT;
1290 /* Geforce9 - midend */
1291 if (strstr(gl_renderer, "9600"))
1293 *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1294 return CARD_NVIDIA_GEFORCE_9600GT;
1297 /* Geforce9 - midend low / Geforce 200 - low */
1298 if (strstr(gl_renderer, "9500")
1299 || strstr(gl_renderer, "GT 120")
1300 || strstr(gl_renderer, "GT 130"))
1302 *vidmem = 256; /* The 9500GT has 256-1024MB */
1303 return CARD_NVIDIA_GEFORCE_9500GT;
1306 /* Geforce9 - lowend */
1307 if (strstr(gl_renderer, "9400"))
1309 *vidmem = 256; /* The 9400GT has 256-1024MB */
1310 return CARD_NVIDIA_GEFORCE_9400GT;
1313 /* Geforce9 - lowend low */
1314 if (strstr(gl_renderer, "9100")
1315 || strstr(gl_renderer, "9200")
1316 || strstr(gl_renderer, "9300")
1317 || strstr(gl_renderer, "G 100"))
1319 *vidmem = 256; /* The 9100-9300 cards have 256MB */
1320 return CARD_NVIDIA_GEFORCE_9200;
1323 /* Geforce8 - highend */
1324 if (strstr(gl_renderer, "8800"))
1326 *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1327 return CARD_NVIDIA_GEFORCE_8800GTS;
1330 /* Geforce8 - midend mobile */
1331 if (strstr(gl_renderer, "8600 M"))
1333 *vidmem = 512;
1334 return CARD_NVIDIA_GEFORCE_8600MGT;
1337 /* Geforce8 - midend */
1338 if (strstr(gl_renderer, "8600")
1339 || strstr(gl_renderer, "8700"))
1341 *vidmem = 256;
1342 return CARD_NVIDIA_GEFORCE_8600GT;
1345 /* Geforce8 - lowend */
1346 if (strstr(gl_renderer, "8100")
1347 || strstr(gl_renderer, "8200")
1348 || strstr(gl_renderer, "8300")
1349 || strstr(gl_renderer, "8400")
1350 || strstr(gl_renderer, "8500"))
1352 *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1353 return CARD_NVIDIA_GEFORCE_8300GS;
1356 /* Geforce7 - highend */
1357 if (strstr(gl_renderer, "7800")
1358 || strstr(gl_renderer, "7900")
1359 || strstr(gl_renderer, "7950")
1360 || strstr(gl_renderer, "Quadro FX 4")
1361 || strstr(gl_renderer, "Quadro FX 5"))
1363 *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1364 return CARD_NVIDIA_GEFORCE_7800GT;
1367 /* Geforce7 midend */
1368 if (strstr(gl_renderer, "7600")
1369 || strstr(gl_renderer, "7700"))
1371 *vidmem = 256; /* The 7600 uses 256-512MB */
1372 return CARD_NVIDIA_GEFORCE_7600;
1375 /* Geforce7 lower medium */
1376 if (strstr(gl_renderer, "7400"))
1378 *vidmem = 256; /* The 7400 uses 256-512MB */
1379 return CARD_NVIDIA_GEFORCE_7400;
1382 /* Geforce7 lowend */
1383 if (strstr(gl_renderer, "7300"))
1385 *vidmem = 256; /* Mac Pros with this card have 256 MB */
1386 return CARD_NVIDIA_GEFORCE_7300;
1389 /* Geforce6 highend */
1390 if (strstr(gl_renderer, "6800"))
1392 *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1393 return CARD_NVIDIA_GEFORCE_6800;
1396 /* Geforce6 - midend */
1397 if (strstr(gl_renderer, "6600")
1398 || strstr(gl_renderer, "6610")
1399 || strstr(gl_renderer, "6700"))
1401 *vidmem = 128; /* A 6600GT has 128-256MB */
1402 return CARD_NVIDIA_GEFORCE_6600GT;
1405 /* Geforce6/7 lowend */
1406 *vidmem = 64; /* */
1407 return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1410 if (WINE_D3D9_CAPABLE(gl_info))
1412 /* GeforceFX - highend */
1413 if (strstr(gl_renderer, "5800")
1414 || strstr(gl_renderer, "5900")
1415 || strstr(gl_renderer, "5950")
1416 || strstr(gl_renderer, "Quadro FX"))
1418 *vidmem = 256; /* 5800-5900 cards use 256MB */
1419 return CARD_NVIDIA_GEFORCEFX_5800;
1422 /* GeforceFX - midend */
1423 if (strstr(gl_renderer, "5600")
1424 || strstr(gl_renderer, "5650")
1425 || strstr(gl_renderer, "5700")
1426 || strstr(gl_renderer, "5750"))
1428 *vidmem = 128; /* A 5600 uses 128-256MB */
1429 return CARD_NVIDIA_GEFORCEFX_5600;
1432 /* GeforceFX - lowend */
1433 *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1434 return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1437 if (WINE_D3D8_CAPABLE(gl_info))
1439 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1441 *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1442 return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1445 *vidmem = 64; /* Geforce3 cards have 64-128MB */
1446 return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1449 if (WINE_D3D7_CAPABLE(gl_info))
1451 if (strstr(gl_renderer, "GeForce4 MX"))
1453 /* Most Geforce4MX GPUs have at least 64MB of memory, some
1454 * early models had 32MB but most have 64MB or even 128MB. */
1455 *vidmem = 64;
1456 return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1459 if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1461 *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1462 return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1465 if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1467 *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1468 return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1471 /* Most Geforce1 cards have 32MB, there are also some rare 16
1472 * and 64MB (Dell) models. */
1473 *vidmem = 32;
1474 return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1477 if (strstr(gl_renderer, "TNT2"))
1479 *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1480 return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1483 *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1484 return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1488 enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1489 unsigned int *vidmem )
1491 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1493 * Beware: renderer string do not match exact card model,
1494 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1495 if (WINE_D3D9_CAPABLE(gl_info))
1497 /* Radeon EG CYPRESS XT / PRO HD5800 - highend */
1498 if (strstr(gl_renderer, "HD 5800") /* Radeon EG CYPRESS HD58xx generic renderer string */
1499 || strstr(gl_renderer, "HD 5850") /* Radeon EG CYPRESS XT */
1500 || strstr(gl_renderer, "HD 5870")) /* Radeon EG CYPRESS PRO */
1502 *vidmem = 1024; /* note: HD58xx cards use 1024MB */
1503 return CARD_ATI_RADEON_HD5800;
1506 /* Radeon EG JUNIPER XT / LE HD5700 - midend */
1507 if (strstr(gl_renderer, "HD 5700") /* Radeon EG JUNIPER HD57xx generic renderer string */
1508 || strstr(gl_renderer, "HD 5750") /* Radeon EG JUNIPER LE */
1509 || strstr(gl_renderer, "HD 5770")) /* Radeon EG JUNIPER XT */
1511 *vidmem = 512; /* note: HD5770 cards use 1024MB and HD5750 cards use 512MB or 1024MB */
1512 return CARD_ATI_RADEON_HD5700;
1515 /* Radeon R7xx HD4800 - highend */
1516 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1517 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1518 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1519 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1520 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1522 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1523 return CARD_ATI_RADEON_HD4800;
1526 /* Radeon R740 HD4700 - midend */
1527 if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1528 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1530 *vidmem = 512;
1531 return CARD_ATI_RADEON_HD4700;
1534 /* Radeon R730 HD4600 - midend */
1535 if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1536 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1537 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1539 *vidmem = 512;
1540 return CARD_ATI_RADEON_HD4600;
1543 /* Radeon R710 HD4500/HD4350 - lowend */
1544 if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1545 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1547 *vidmem = 256;
1548 return CARD_ATI_RADEON_HD4350;
1551 /* Radeon R6xx HD2900/HD3800 - highend */
1552 if (strstr(gl_renderer, "HD 2900")
1553 || strstr(gl_renderer, "HD 3870")
1554 || strstr(gl_renderer, "HD 3850"))
1556 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1557 return CARD_ATI_RADEON_HD2900;
1560 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1561 if (strstr(gl_renderer, "HD 2600")
1562 || strstr(gl_renderer, "HD 3830")
1563 || strstr(gl_renderer, "HD 3690")
1564 || strstr(gl_renderer, "HD 3650"))
1566 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1567 return CARD_ATI_RADEON_HD2600;
1570 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1571 if (strstr(gl_renderer, "HD 2300")
1572 || strstr(gl_renderer, "HD 2400")
1573 || strstr(gl_renderer, "HD 3470")
1574 || strstr(gl_renderer, "HD 3450")
1575 || strstr(gl_renderer, "HD 3430")
1576 || strstr(gl_renderer, "HD 3400"))
1578 *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1579 return CARD_ATI_RADEON_HD2300;
1582 /* Radeon R6xx/R7xx integrated */
1583 if (strstr(gl_renderer, "HD 3100")
1584 || strstr(gl_renderer, "HD 3200")
1585 || strstr(gl_renderer, "HD 3300"))
1587 *vidmem = 128; /* 128MB */
1588 return CARD_ATI_RADEON_HD3200;
1591 /* Radeon R5xx */
1592 if (strstr(gl_renderer, "X1600")
1593 || strstr(gl_renderer, "X1650")
1594 || strstr(gl_renderer, "X1800")
1595 || strstr(gl_renderer, "X1900")
1596 || strstr(gl_renderer, "X1950"))
1598 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1599 return CARD_ATI_RADEON_X1600;
1602 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1603 if (strstr(gl_renderer, "X700")
1604 || strstr(gl_renderer, "X800")
1605 || strstr(gl_renderer, "X850")
1606 || strstr(gl_renderer, "X1300")
1607 || strstr(gl_renderer, "X1400")
1608 || strstr(gl_renderer, "X1450")
1609 || strstr(gl_renderer, "X1550"))
1611 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1612 return CARD_ATI_RADEON_X700;
1615 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1616 if (strstr(gl_renderer, "Radeon Xpress"))
1618 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1619 return CARD_ATI_RADEON_XPRESS_200M;
1622 /* Radeon R3xx */
1623 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1624 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1627 if (WINE_D3D8_CAPABLE(gl_info))
1629 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1630 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1633 if (WINE_D3D7_CAPABLE(gl_info))
1635 *vidmem = 32; /* There are models with up to 64MB */
1636 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1639 *vidmem = 16; /* There are 16-32MB models */
1640 return CARD_ATI_RAGE_128PRO;
1644 enum wined3d_pci_device select_card_intel_binary(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1645 unsigned int *vidmem )
1647 if (strstr(gl_renderer, "X3100"))
1649 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1650 *vidmem = 128;
1651 return CARD_INTEL_X3100;
1654 if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1656 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1657 *vidmem = 64;
1658 return CARD_INTEL_I945GM;
1661 if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM;
1662 if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G;
1663 if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G;
1664 if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G;
1665 if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G;
1666 return CARD_INTEL_I915G;
1670 enum wined3d_pci_device (select_card_ati_mesa)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1671 unsigned int *vidmem )
1673 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1675 * Beware: renderer string do not match exact card model,
1676 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1677 if (strstr(gl_renderer, "Gallium"))
1679 /* Radeon R7xx HD4800 - highend */
1680 if (strstr(gl_renderer, "R700") /* Radeon R7xx HD48xx generic renderer string */
1681 || strstr(gl_renderer, "RV770") /* Radeon RV770 */
1682 || strstr(gl_renderer, "RV790")) /* Radeon RV790 */
1684 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1685 return CARD_ATI_RADEON_HD4800;
1688 /* Radeon R740 HD4700 - midend */
1689 if (strstr(gl_renderer, "RV740")) /* Radeon RV740 */
1691 *vidmem = 512;
1692 return CARD_ATI_RADEON_HD4700;
1695 /* Radeon R730 HD4600 - midend */
1696 if (strstr(gl_renderer, "RV730")) /* Radeon RV730 */
1698 *vidmem = 512;
1699 return CARD_ATI_RADEON_HD4600;
1702 /* Radeon R710 HD4500/HD4350 - lowend */
1703 if (strstr(gl_renderer, "RV710")) /* Radeon RV710 */
1705 *vidmem = 256;
1706 return CARD_ATI_RADEON_HD4350;
1709 /* Radeon R6xx HD2900/HD3800 - highend */
1710 if (strstr(gl_renderer, "R600")
1711 || strstr(gl_renderer, "RV670")
1712 || strstr(gl_renderer, "R680"))
1714 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1715 return CARD_ATI_RADEON_HD2900;
1718 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1719 if (strstr(gl_renderer, "RV630")
1720 || strstr(gl_renderer, "RV635"))
1722 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1723 return CARD_ATI_RADEON_HD2600;
1726 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1727 if (strstr(gl_renderer, "RV610")
1728 || strstr(gl_renderer, "RV620"))
1730 *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1731 return CARD_ATI_RADEON_HD2300;
1734 /* Radeon R6xx/R7xx integrated */
1735 if (strstr(gl_renderer, "RS780")
1736 || strstr(gl_renderer, "RS880"))
1738 *vidmem = 128; /* 128MB */
1739 return CARD_ATI_RADEON_HD3200;
1742 /* Radeon R5xx */
1743 if (strstr(gl_renderer, "RV530")
1744 || strstr(gl_renderer, "RV535")
1745 || strstr(gl_renderer, "RV560")
1746 || strstr(gl_renderer, "R520")
1747 || strstr(gl_renderer, "RV570")
1748 || strstr(gl_renderer, "R580"))
1750 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1751 return CARD_ATI_RADEON_X1600;
1754 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1755 if (strstr(gl_renderer, "R410")
1756 || strstr(gl_renderer, "R420")
1757 || strstr(gl_renderer, "R423")
1758 || strstr(gl_renderer, "R430")
1759 || strstr(gl_renderer, "R480")
1760 || strstr(gl_renderer, "R481")
1761 || strstr(gl_renderer, "RV410")
1762 || strstr(gl_renderer, "RV515")
1763 || strstr(gl_renderer, "RV516"))
1765 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1766 return CARD_ATI_RADEON_X700;
1769 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1770 if (strstr(gl_renderer, "RS400")
1771 || strstr(gl_renderer, "RS480")
1772 || strstr(gl_renderer, "RS482")
1773 || strstr(gl_renderer, "RS485")
1774 || strstr(gl_renderer, "RS600")
1775 || strstr(gl_renderer, "RS690")
1776 || strstr(gl_renderer, "RS740"))
1778 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1779 return CARD_ATI_RADEON_XPRESS_200M;
1782 /* Radeon R3xx */
1783 if (strstr(gl_renderer, "R300")
1784 || strstr(gl_renderer, "RV350")
1785 || strstr(gl_renderer, "RV351")
1786 || strstr(gl_renderer, "RV360")
1787 || strstr(gl_renderer, "RV370")
1788 || strstr(gl_renderer, "R350")
1789 || strstr(gl_renderer, "R360"))
1791 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1792 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1796 if (WINE_D3D9_CAPABLE(gl_info))
1798 /* Radeon R7xx HD4800 - highend */
1799 if (strstr(gl_renderer, "(R700") /* Radeon R7xx HD48xx generic renderer string */
1800 || strstr(gl_renderer, "(RV770") /* Radeon RV770 */
1801 || strstr(gl_renderer, "(RV790")) /* Radeon RV790 */
1803 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1804 return CARD_ATI_RADEON_HD4800;
1807 /* Radeon R740 HD4700 - midend */
1808 if (strstr(gl_renderer, "(RV740")) /* Radeon RV740 */
1810 *vidmem = 512;
1811 return CARD_ATI_RADEON_HD4700;
1814 /* Radeon R730 HD4600 - midend */
1815 if (strstr(gl_renderer, "(RV730")) /* Radeon RV730 */
1817 *vidmem = 512;
1818 return CARD_ATI_RADEON_HD4600;
1821 /* Radeon R710 HD4500/HD4350 - lowend */
1822 if (strstr(gl_renderer, "(RV710")) /* Radeon RV710 */
1824 *vidmem = 256;
1825 return CARD_ATI_RADEON_HD4350;
1828 /* Radeon R6xx HD2900/HD3800 - highend */
1829 if (strstr(gl_renderer, "(R600")
1830 || strstr(gl_renderer, "(RV670")
1831 || strstr(gl_renderer, "(R680"))
1833 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1834 return CARD_ATI_RADEON_HD2900;
1837 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1838 if (strstr(gl_renderer, "(RV630")
1839 || strstr(gl_renderer, "(RV635"))
1841 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1842 return CARD_ATI_RADEON_HD2600;
1845 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1846 if (strstr(gl_renderer, "(RV610")
1847 || strstr(gl_renderer, "(RV620"))
1849 *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1850 return CARD_ATI_RADEON_HD2300;
1853 /* Radeon R6xx/R7xx integrated */
1854 if (strstr(gl_renderer, "(RS780")
1855 || strstr(gl_renderer, "(RS880"))
1857 *vidmem = 128; /* 128MB */
1858 return CARD_ATI_RADEON_HD3200;
1862 if (WINE_D3D8_CAPABLE(gl_info))
1864 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1865 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1868 if (WINE_D3D7_CAPABLE(gl_info))
1870 *vidmem = 32; /* There are models with up to 64MB */
1871 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1874 *vidmem = 16; /* There are 16-32MB models */
1875 return CARD_ATI_RAGE_128PRO;
1879 enum wined3d_pci_device (select_card_nvidia_mesa)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1880 unsigned int *vidmem )
1882 FIXME_(d3d_caps)("Card selection not handled for Mesa Nouveau driver\n");
1883 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1884 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1885 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1886 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
1887 return CARD_NVIDIA_RIVA_128;
1890 enum wined3d_pci_device (select_card_intel_mesa)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1891 unsigned int *vidmem )
1893 FIXME_(d3d_caps)("Card selection not handled for Mesa Intel driver\n");
1894 return CARD_INTEL_I915G;
1898 struct vendor_card_selection
1900 enum wined3d_gl_vendor gl_vendor;
1901 enum wined3d_pci_vendor card_vendor;
1902 const char *description; /* Description of the card selector i.e. Apple OS/X Intel */
1903 enum wined3d_pci_device (*select_card)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1904 unsigned int *vidmem );
1907 static const struct vendor_card_selection vendor_card_select_table[] =
1909 {GL_VENDOR_NVIDIA, HW_VENDOR_NVIDIA, "Nvidia binary driver", select_card_nvidia_binary},
1910 {GL_VENDOR_APPLE, HW_VENDOR_NVIDIA, "Apple OSX NVidia binary driver", select_card_nvidia_binary},
1911 {GL_VENDOR_APPLE, HW_VENDOR_ATI, "Apple OSX AMD/ATI binary driver", select_card_ati_binary},
1912 {GL_VENDOR_APPLE, HW_VENDOR_INTEL, "Apple OSX Intel binary driver", select_card_intel_binary},
1913 {GL_VENDOR_ATI, HW_VENDOR_ATI, "AMD/ATI binary driver", select_card_ati_binary},
1914 {GL_VENDOR_MESA, HW_VENDOR_ATI, "Mesa AMD/ATI driver", select_card_ati_mesa},
1915 {GL_VENDOR_MESA, HW_VENDOR_NVIDIA, "Mesa Nouveau driver", select_card_nvidia_mesa},
1916 {GL_VENDOR_MESA, HW_VENDOR_INTEL, "Mesa Intel driver", select_card_intel_mesa}
1920 static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1921 enum wined3d_gl_vendor *gl_vendor, enum wined3d_pci_vendor *card_vendor, unsigned int *vidmem)
1923 /* Above is a list of Nvidia and ATI GPUs. Both vendors have dozens of
1924 * different GPUs with roughly the same features. In most cases GPUs from a
1925 * certain family differ in clockspeeds, the amount of video memory and the
1926 * number of shader pipelines.
1928 * A Direct3D device object contains the PCI id (vendor + device) of the
1929 * videocard which is used for rendering. Various applications use this
1930 * information to get a rough estimation of the features of the card and
1931 * some might use it for enabling 3d effects only on certain types of
1932 * videocards. In some cases games might even use it to work around bugs
1933 * which happen on certain videocards/driver combinations. The problem is
1934 * that OpenGL only exposes a rendering string containing the name of the
1935 * videocard and not the PCI id.
1937 * Various games depend on the PCI id, so somehow we need to provide one.
1938 * A simple option is to parse the renderer string and translate this to
1939 * the right PCI id. This is a lot of work because there are more than 200
1940 * GPUs just for Nvidia. Various cards share the same renderer string, so
1941 * the amount of code might be 'small' but there are quite a number of
1942 * exceptions which would make this a pain to maintain. Another way would
1943 * be to query the PCI id from the operating system (assuming this is the
1944 * videocard which is used for rendering which is not always the case).
1945 * This would work but it is not very portable. Second it would not work
1946 * well in, let's say, a remote X situation in which the amount of 3d
1947 * features which can be used is limited.
1949 * As said most games only use the PCI id to get an indication of the
1950 * capabilities of the card. It doesn't really matter if the given id is
1951 * the correct one if we return the id of a card with similar 3d features.
1953 * The code below checks the OpenGL capabilities of a videocard and matches
1954 * that to a certain level of Direct3D functionality. Once a card passes
1955 * the Direct3D9 check, we know that the card (in case of Nvidia) is at
1956 * least a GeforceFX. To give a better estimate we do a basic check on the
1957 * renderer string but if that won't pass we return a default card. This
1958 * way is better than maintaining a full card database as even without a
1959 * full database we can return a card with similar features. Second the
1960 * size of the database can be made quite small because when you know what
1961 * type of 3d functionality a card has, you know to which GPU family the
1962 * GPU must belong. Because of this you only have to check a small part of
1963 * the renderer string to distinguishes between different models from that
1964 * family.
1966 * The code also selects a default amount of video memory which we will
1967 * use for an estimation of the amount of free texture memory. In case of
1968 * real D3D the amount of texture memory includes video memory and system
1969 * memory (to be specific AGP memory or in case of PCIE TurboCache /
1970 * HyperMemory). We don't know how much system memory can be addressed by
1971 * the system but we can make a reasonable estimation about the amount of
1972 * video memory. If the value is slightly wrong it doesn't matter as we
1973 * didn't include AGP-like memory which makes the amount of addressable
1974 * memory higher and second OpenGL isn't that critical it moves to system
1975 * memory behind our backs if really needed. Note that the amount of video
1976 * memory can be overruled using a registry setting. */
1978 int i;
1980 for (i = 0; i < (sizeof(vendor_card_select_table) / sizeof(*vendor_card_select_table)); ++i)
1982 if ((vendor_card_select_table[i].gl_vendor != *gl_vendor)
1983 || (vendor_card_select_table[i].card_vendor != *card_vendor))
1984 continue;
1985 TRACE_(d3d_caps)("Applying card_selector \"%s\".\n", vendor_card_select_table[i].description);
1986 return vendor_card_select_table[i].select_card(gl_info, gl_renderer, vidmem);
1989 FIXME_(d3d_caps)("No card selector available for GL vendor %d and card vendor %04x.\n",
1990 *gl_vendor, *card_vendor);
1992 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1993 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1994 * them a good generic choice. */
1995 *card_vendor = HW_VENDOR_NVIDIA;
1996 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1997 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1998 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1999 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
2000 return CARD_NVIDIA_RIVA_128;
2003 static const struct fragment_pipeline *select_fragment_implementation(struct wined3d_adapter *adapter)
2005 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2006 int vs_selected_mode, ps_selected_mode;
2008 select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode);
2009 if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL)
2010 && gl_info->supported[ARB_FRAGMENT_PROGRAM]) return &arbfp_fragment_pipeline;
2011 else if (ps_selected_mode == SHADER_ATI) return &atifs_fragment_pipeline;
2012 else if (gl_info->supported[NV_REGISTER_COMBINERS]
2013 && gl_info->supported[NV_TEXTURE_SHADER2]) return &nvts_fragment_pipeline;
2014 else if (gl_info->supported[NV_REGISTER_COMBINERS]) return &nvrc_fragment_pipeline;
2015 else return &ffp_fragment_pipeline;
2018 static const shader_backend_t *select_shader_backend(struct wined3d_adapter *adapter)
2020 int vs_selected_mode, ps_selected_mode;
2022 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
2023 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) return &glsl_shader_backend;
2024 if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) return &arb_program_shader_backend;
2025 return &none_shader_backend;
2028 static const struct blit_shader *select_blit_implementation(struct wined3d_adapter *adapter)
2030 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2031 int vs_selected_mode, ps_selected_mode;
2033 select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode);
2034 if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL)
2035 && gl_info->supported[ARB_FRAGMENT_PROGRAM]) return &arbfp_blit;
2036 else return &ffp_blit;
2039 /* Context activation is done by the caller. */
2040 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_adapter *adapter)
2042 struct wined3d_driver_info *driver_info = &adapter->driver_info;
2043 struct wined3d_gl_info *gl_info = &adapter->gl_info;
2044 const char *GL_Extensions = NULL;
2045 const char *WGL_Extensions = NULL;
2046 const char *gl_vendor_str, *gl_renderer_str, *gl_version_str;
2047 struct fragment_caps fragment_caps;
2048 enum wined3d_gl_vendor gl_vendor;
2049 enum wined3d_pci_vendor card_vendor;
2050 enum wined3d_pci_device device;
2051 GLint gl_max;
2052 GLfloat gl_floatv[2];
2053 unsigned i;
2054 HDC hdc;
2055 unsigned int vidmem=0;
2056 DWORD gl_version;
2057 size_t len;
2059 TRACE_(d3d_caps)("(%p)\n", gl_info);
2061 ENTER_GL();
2063 gl_renderer_str = (const char *)glGetString(GL_RENDERER);
2064 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_renderer_str));
2065 if (!gl_renderer_str)
2067 LEAVE_GL();
2068 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
2069 return FALSE;
2072 gl_vendor_str = (const char *)glGetString(GL_VENDOR);
2073 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_vendor_str));
2074 if (!gl_vendor_str)
2076 LEAVE_GL();
2077 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
2078 return FALSE;
2081 /* Parse the GL_VERSION field into major and minor information */
2082 gl_version_str = (const char *)glGetString(GL_VERSION);
2083 TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_version_str));
2084 if (!gl_version_str)
2086 LEAVE_GL();
2087 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
2088 return FALSE;
2090 gl_version = wined3d_parse_gl_version(gl_version_str);
2093 * Initialize openGL extension related variables
2094 * with Default values
2096 memset(gl_info->supported, 0, sizeof(gl_info->supported));
2097 gl_info->limits.buffers = 1;
2098 gl_info->limits.textures = 1;
2099 gl_info->limits.fragment_samplers = 1;
2100 gl_info->limits.vertex_samplers = 0;
2101 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
2102 gl_info->limits.sampler_stages = 1;
2103 gl_info->limits.glsl_vs_float_constants = 0;
2104 gl_info->limits.glsl_ps_float_constants = 0;
2105 gl_info->limits.arb_vs_float_constants = 0;
2106 gl_info->limits.arb_vs_native_constants = 0;
2107 gl_info->limits.arb_vs_instructions = 0;
2108 gl_info->limits.arb_vs_temps = 0;
2109 gl_info->limits.arb_ps_float_constants = 0;
2110 gl_info->limits.arb_ps_local_constants = 0;
2111 gl_info->limits.arb_ps_instructions = 0;
2112 gl_info->limits.arb_ps_temps = 0;
2114 /* Retrieve opengl defaults */
2115 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
2116 gl_info->limits.clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
2117 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
2119 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
2120 gl_info->limits.lights = gl_max;
2121 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
2123 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
2124 gl_info->limits.texture_size = gl_max;
2125 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
2127 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
2128 gl_info->limits.pointsize_min = gl_floatv[0];
2129 gl_info->limits.pointsize_max = gl_floatv[1];
2130 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
2132 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
2133 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
2134 if (!GL_Extensions)
2136 LEAVE_GL();
2137 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
2138 return FALSE;
2141 LEAVE_GL();
2143 TRACE_(d3d_caps)("GL_Extensions reported:\n");
2145 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
2147 while (*GL_Extensions)
2149 const char *start;
2150 char current_ext[256];
2152 while (isspace(*GL_Extensions)) ++GL_Extensions;
2153 start = GL_Extensions;
2154 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
2156 len = GL_Extensions - start;
2157 if (!len || len >= sizeof(current_ext)) continue;
2159 memcpy(current_ext, start, len);
2160 current_ext[len] = '\0';
2161 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
2163 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
2165 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
2167 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
2168 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
2169 break;
2174 /* Now work out what GL support this card really has */
2175 #define USE_GL_FUNC(type, pfn, ext, replace) \
2177 DWORD ver = ver_for_ext(ext); \
2178 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
2179 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
2180 else gl_info->pfn = NULL; \
2182 GL_EXT_FUNCS_GEN;
2183 #undef USE_GL_FUNC
2185 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
2186 WGL_EXT_FUNCS_GEN;
2187 #undef USE_GL_FUNC
2189 ENTER_GL();
2191 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
2192 * loading the functions, otherwise the code above will load the extension entry points instead of the
2193 * core functions, which may not work. */
2194 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
2196 if (!gl_info->supported[EXTENSION_MAP[i].extension]
2197 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
2199 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
2200 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
2204 if (gl_info->supported[APPLE_FENCE])
2206 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
2207 * The apple extension interacts with some other apple exts. Disable the NV
2208 * extension if the apple one is support to prevent confusion in other parts
2209 * of the code. */
2210 gl_info->supported[NV_FENCE] = FALSE;
2212 if (gl_info->supported[APPLE_FLOAT_PIXELS])
2214 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
2216 * The enums are the same:
2217 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
2218 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
2219 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
2220 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
2221 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
2223 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
2225 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
2226 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
2228 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
2230 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
2231 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
2234 if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
2236 /* GL_ARB_map_buffer_range and GL_APPLE_flush_buffer_range provide the same
2237 * functionality. Prefer the ARB extension */
2238 gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] = FALSE;
2240 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
2242 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
2243 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
2245 if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
2247 TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
2248 gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
2250 if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && gl_info->supported[EXT_VERTEX_ARRAY_BGRA])
2252 TRACE_(d3d_caps)(" IMPLIED: ARB_vertex_array_bgra support (by EXT_vertex_array_bgra).\n");
2253 gl_info->supported[ARB_VERTEX_ARRAY_BGRA] = TRUE;
2255 if (gl_info->supported[NV_TEXTURE_SHADER2])
2257 if (gl_info->supported[NV_REGISTER_COMBINERS])
2259 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
2260 * are supported. The nv extensions provide the same functionality as the
2261 * ATI one, and a bit more(signed pixelformats). */
2262 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
2266 if (gl_info->supported[NV_REGISTER_COMBINERS])
2268 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
2269 gl_info->limits.general_combiners = gl_max;
2270 TRACE_(d3d_caps)("Max general combiners: %d.\n", gl_max);
2272 if (gl_info->supported[ARB_DRAW_BUFFERS])
2274 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
2275 gl_info->limits.buffers = gl_max;
2276 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
2278 if (gl_info->supported[ARB_MULTITEXTURE])
2280 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
2281 gl_info->limits.textures = min(MAX_TEXTURES, gl_max);
2282 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->limits.textures);
2284 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
2286 GLint tmp;
2287 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2288 gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
2290 else
2292 gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, gl_max);
2294 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers);
2296 if (gl_info->supported[ARB_VERTEX_SHADER])
2298 GLint tmp;
2299 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2300 gl_info->limits.vertex_samplers = tmp;
2301 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2302 gl_info->limits.combined_samplers = tmp;
2304 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
2305 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
2306 * an issue because then the sampler setup only depends on the two shaders. If a pixel
2307 * shader is used with fixed function vertex processing we're fine too because fixed function
2308 * vertex processing doesn't use any samplers. If fixed function fragment processing is
2309 * used we have to make sure that all vertex sampler setups are valid together with all
2310 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
2311 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
2312 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
2313 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
2314 * a fixed function pipeline anymore.
2316 * So this is just a check to check that our assumption holds true. If not, write a warning
2317 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
2318 if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12
2319 && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers)
2321 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
2322 gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers);
2323 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
2324 if (gl_info->limits.combined_samplers > MAX_TEXTURES)
2325 gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES;
2326 else
2327 gl_info->limits.vertex_samplers = 0;
2330 else
2332 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers;
2334 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers);
2335 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->limits.combined_samplers);
2337 if (gl_info->supported[ARB_VERTEX_BLEND])
2339 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
2340 gl_info->limits.blends = gl_max;
2341 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->limits.blends);
2343 if (gl_info->supported[EXT_TEXTURE3D])
2345 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
2346 gl_info->limits.texture3d_size = gl_max;
2347 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->limits.texture3d_size);
2349 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
2351 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
2352 gl_info->limits.anisotropy = gl_max;
2353 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->limits.anisotropy);
2355 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
2357 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
2358 gl_info->limits.arb_ps_float_constants = gl_max;
2359 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants);
2360 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
2361 gl_info->limits.arb_ps_native_constants = gl_max;
2362 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n",
2363 gl_info->limits.arb_ps_native_constants);
2364 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
2365 gl_info->limits.arb_ps_temps = gl_max;
2366 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps);
2367 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
2368 gl_info->limits.arb_ps_instructions = gl_max;
2369 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions);
2370 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
2371 gl_info->limits.arb_ps_local_constants = gl_max;
2372 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions);
2374 if (gl_info->supported[ARB_VERTEX_PROGRAM])
2376 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
2377 gl_info->limits.arb_vs_float_constants = gl_max;
2378 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants);
2379 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
2380 gl_info->limits.arb_vs_native_constants = gl_max;
2381 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native float constants: %d.\n",
2382 gl_info->limits.arb_vs_native_constants);
2383 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
2384 gl_info->limits.arb_vs_temps = gl_max;
2385 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps);
2386 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
2387 gl_info->limits.arb_vs_instructions = gl_max;
2388 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions);
2390 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
2392 if (gl_info->supported[ARB_VERTEX_SHADER])
2394 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
2395 gl_info->limits.glsl_vs_float_constants = gl_max / 4;
2396 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
2398 if (gl_info->supported[ARB_FRAGMENT_SHADER])
2400 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
2401 gl_info->limits.glsl_ps_float_constants = gl_max / 4;
2402 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants);
2403 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
2404 gl_info->limits.glsl_varyings = gl_max;
2405 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
2407 if (gl_info->supported[ARB_SHADING_LANGUAGE_100])
2409 const char *str = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
2410 TRACE_(d3d_caps)("GLSL version string: %s.\n", debugstr_a(str));
2412 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
2414 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess);
2416 else
2418 gl_info->limits.shininess = 128.0f;
2420 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
2422 /* If we have full NP2 texture support, disable
2423 * GL_ARB_texture_rectangle because we will never use it.
2424 * This saves a few redundant glDisable calls. */
2425 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
2427 if (gl_info->supported[ATI_FRAGMENT_SHADER])
2429 /* Disable NV_register_combiners and fragment shader if this is supported.
2430 * generally the NV extensions are preferred over the ATI ones, and this
2431 * extension is disabled if register_combiners and texture_shader2 are both
2432 * supported. So we reach this place only if we have incomplete NV dxlevel 8
2433 * fragment processing support. */
2434 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
2435 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
2436 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
2437 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
2439 if (gl_info->supported[NV_HALF_FLOAT])
2441 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
2442 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
2444 if (gl_info->supported[ARB_POINT_SPRITE])
2446 gl_info->limits.point_sprite_units = gl_info->limits.textures;
2448 else
2450 gl_info->limits.point_sprite_units = 0;
2452 checkGLcall("extension detection");
2454 LEAVE_GL();
2456 adapter->fragment_pipe = select_fragment_implementation(adapter);
2457 adapter->shader_backend = select_shader_backend(adapter);
2458 adapter->blitter = select_blit_implementation(adapter);
2460 adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
2461 gl_info->limits.texture_stages = fragment_caps.MaxTextureBlendStages;
2462 TRACE_(d3d_caps)("Max texture stages: %u.\n", gl_info->limits.texture_stages);
2464 /* In some cases the number of texture stages can be larger than the number
2465 * of samplers. The GF4 for example can use only 2 samplers (no fragment
2466 * shaders), but 8 texture stages (register combiners). */
2467 gl_info->limits.sampler_stages = max(gl_info->limits.fragment_samplers, gl_info->limits.texture_stages);
2469 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
2471 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbuffer;
2472 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbuffer;
2473 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffers;
2474 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffers;
2475 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorage;
2476 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisample;
2477 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameteriv;
2478 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebuffer;
2479 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebuffer;
2480 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffers;
2481 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffers;
2482 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatus;
2483 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1D;
2484 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2D;
2485 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3D;
2486 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbuffer;
2487 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameteriv;
2488 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebuffer;
2489 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmap;
2491 else
2493 if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT])
2495 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbufferEXT;
2496 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbufferEXT;
2497 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffersEXT;
2498 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffersEXT;
2499 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorageEXT;
2500 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameterivEXT;
2501 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebufferEXT;
2502 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebufferEXT;
2503 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffersEXT;
2504 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffersEXT;
2505 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatusEXT;
2506 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1DEXT;
2507 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2DEXT;
2508 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3DEXT;
2509 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbufferEXT;
2510 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameterivEXT;
2511 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmapEXT;
2513 else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2515 WARN_(d3d_caps)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
2516 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
2518 if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
2520 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebufferEXT;
2522 if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
2524 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisampleEXT;
2528 /* MRTs are currently only supported when FBOs are used. */
2529 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
2531 gl_info->limits.buffers = 1;
2534 gl_vendor = wined3d_guess_gl_vendor(gl_info, gl_vendor_str, gl_renderer_str);
2535 card_vendor = wined3d_guess_card_vendor(gl_vendor_str, gl_renderer_str);
2536 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x/0x%04x)\n", debugstr_a(gl_vendor_str), gl_vendor, card_vendor);
2538 device = wined3d_guess_card(gl_info, gl_renderer_str, &gl_vendor, &card_vendor, &vidmem);
2539 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", card_vendor, device);
2541 /* If we have an estimate use it, else default to 64MB; */
2542 if(vidmem)
2543 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
2544 else
2545 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
2547 gl_info->wrap_lookup[WINED3DTADDRESS_WRAP - WINED3DTADDRESS_WRAP] = GL_REPEAT;
2548 gl_info->wrap_lookup[WINED3DTADDRESS_MIRROR - WINED3DTADDRESS_WRAP] =
2549 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
2550 gl_info->wrap_lookup[WINED3DTADDRESS_CLAMP - WINED3DTADDRESS_WRAP] = GL_CLAMP_TO_EDGE;
2551 gl_info->wrap_lookup[WINED3DTADDRESS_BORDER - WINED3DTADDRESS_WRAP] =
2552 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2553 gl_info->wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP] =
2554 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
2556 /* Make sure there's an active HDC else the WGL extensions will fail */
2557 hdc = pwglGetCurrentDC();
2558 if (hdc) {
2559 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2560 if(GL_EXTCALL(wglGetExtensionsStringARB))
2561 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2563 if (NULL == WGL_Extensions) {
2564 ERR(" WGL_Extensions returns NULL\n");
2565 } else {
2566 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2567 while (*WGL_Extensions != 0x00) {
2568 const char *Start;
2569 char ThisExtn[256];
2571 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2572 Start = WGL_Extensions;
2573 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2574 WGL_Extensions++;
2577 len = WGL_Extensions - Start;
2578 if (len == 0 || len >= sizeof(ThisExtn))
2579 continue;
2581 memcpy(ThisExtn, Start, len);
2582 ThisExtn[len] = '\0';
2583 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
2585 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2586 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2587 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2589 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2590 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2591 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2597 fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device);
2598 init_driver_info(driver_info, card_vendor, device);
2599 add_gl_compat_wrappers(gl_info);
2601 return TRUE;
2604 /**********************************************************
2605 * IWineD3D implementation follows
2606 **********************************************************/
2608 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2609 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2611 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2613 return This->adapter_count;
2616 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void *init_function)
2618 FIXME("iface %p, init_function %p stub!\n", iface, init_function);
2620 return WINED3D_OK;
2623 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2624 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2626 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2628 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2629 return NULL;
2632 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2635 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2636 of the same bpp but different resolutions */
2638 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2639 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2640 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2641 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2643 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2644 return 0;
2647 /* TODO: Store modes per adapter and read it from the adapter structure */
2648 if (Adapter == 0) { /* Display */
2649 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2650 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2651 unsigned int i = 0;
2652 unsigned int j = 0;
2653 DEVMODEW mode;
2655 memset(&mode, 0, sizeof(mode));
2656 mode.dmSize = sizeof(mode);
2658 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2660 ++j;
2662 if (Format == WINED3DFMT_UNKNOWN)
2664 /* This is for D3D8, do not enumerate P8 here */
2665 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2667 else if (mode.dmBitsPerPel == format_bits)
2669 ++i;
2673 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2674 return i;
2675 } else {
2676 FIXME_(d3d_caps)("Adapter not primary display\n");
2678 return 0;
2681 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2682 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2683 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2684 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2686 /* Validate the parameters as much as possible */
2687 if (NULL == pMode ||
2688 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2689 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2690 return WINED3DERR_INVALIDCALL;
2693 /* TODO: Store modes per adapter and read it from the adapter structure */
2694 if (Adapter == 0)
2696 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2697 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2698 DEVMODEW DevModeW;
2699 int ModeIdx = 0;
2700 UINT i = 0;
2701 int j = 0;
2703 ZeroMemory(&DevModeW, sizeof(DevModeW));
2704 DevModeW.dmSize = sizeof(DevModeW);
2706 /* If we are filtering to a specific format (D3D9), then need to skip
2707 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2708 just count through the ones with valid bit depths */
2709 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0))
2711 if (Format == WINED3DFMT_UNKNOWN)
2713 /* This is for D3D8, do not enumerate P8 here */
2714 if (DevModeW.dmBitsPerPel == 32 || DevModeW.dmBitsPerPel == 16) ++i;
2716 else if (DevModeW.dmBitsPerPel == format_bits)
2718 ++i;
2722 if (i == 0) {
2723 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2724 return WINED3DERR_INVALIDCALL;
2726 ModeIdx = j - 1;
2728 /* Now get the display mode via the calculated index */
2729 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2730 pMode->Width = DevModeW.dmPelsWidth;
2731 pMode->Height = DevModeW.dmPelsHeight;
2732 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2733 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2734 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2736 if (Format == WINED3DFMT_UNKNOWN) {
2737 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2738 } else {
2739 pMode->Format = Format;
2741 } else {
2742 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2743 return WINED3DERR_INVALIDCALL;
2746 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2747 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2748 DevModeW.dmBitsPerPel);
2751 else
2753 FIXME_(d3d_caps)("Adapter not primary display\n");
2756 return WINED3D_OK;
2759 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE *pMode)
2761 TRACE("iface %p, adapter_idx %u, display_mode %p.\n", iface, Adapter, pMode);
2763 if (NULL == pMode ||
2764 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2765 return WINED3DERR_INVALIDCALL;
2768 if (Adapter == 0) { /* Display */
2769 int bpp = 0;
2770 DEVMODEW DevModeW;
2772 ZeroMemory(&DevModeW, sizeof(DevModeW));
2773 DevModeW.dmSize = sizeof(DevModeW);
2775 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2776 pMode->Width = DevModeW.dmPelsWidth;
2777 pMode->Height = DevModeW.dmPelsHeight;
2778 bpp = DevModeW.dmBitsPerPel;
2779 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2780 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2782 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2785 pMode->Format = pixelformat_for_depth(bpp);
2786 } else {
2787 FIXME_(d3d_caps)("Adapter not primary display\n");
2790 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2791 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2792 return WINED3D_OK;
2795 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2796 and fields being inserted in the middle, a new structure is used in place */
2797 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2798 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2799 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2800 struct wined3d_adapter *adapter;
2801 size_t len;
2803 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2805 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2806 return WINED3DERR_INVALIDCALL;
2809 adapter = &This->adapters[Adapter];
2811 /* Return the information requested */
2812 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2814 if (pIdentifier->driver_size)
2816 const char *name = adapter->driver_info.name;
2817 len = min(strlen(name), pIdentifier->driver_size - 1);
2818 memcpy(pIdentifier->driver, name, len);
2819 pIdentifier->driver[len] = '\0';
2822 if (pIdentifier->description_size)
2824 const char *description = adapter->driver_info.description;
2825 len = min(strlen(description), pIdentifier->description_size - 1);
2826 memcpy(pIdentifier->description, description, len);
2827 pIdentifier->description[len] = '\0';
2830 /* Note that d3d8 doesn't supply a device name. */
2831 if (pIdentifier->device_name_size)
2833 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2835 len = strlen(device_name);
2836 if (len >= pIdentifier->device_name_size)
2838 ERR("Device name size too small.\n");
2839 return WINED3DERR_INVALIDCALL;
2842 memcpy(pIdentifier->device_name, device_name, len);
2843 pIdentifier->device_name[len] = '\0';
2846 pIdentifier->driver_version.u.HighPart = adapter->driver_info.version_high;
2847 pIdentifier->driver_version.u.LowPart = adapter->driver_info.version_low;
2848 pIdentifier->vendor_id = adapter->driver_info.vendor;
2849 pIdentifier->device_id = adapter->driver_info.device;
2850 pIdentifier->subsystem_id = 0;
2851 pIdentifier->revision = 0;
2852 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2853 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2854 memcpy(&pIdentifier->adapter_luid, &adapter->luid, sizeof(pIdentifier->adapter_luid));
2855 pIdentifier->video_memory = adapter->TextureRam;
2857 return WINED3D_OK;
2860 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2861 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2863 short redSize, greenSize, blueSize, alphaSize, colorBits;
2865 if(!cfg)
2866 return FALSE;
2868 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2869 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2871 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2872 return FALSE;
2875 if(cfg->redSize < redSize)
2876 return FALSE;
2878 if(cfg->greenSize < greenSize)
2879 return FALSE;
2881 if(cfg->blueSize < blueSize)
2882 return FALSE;
2884 if(cfg->alphaSize < alphaSize)
2885 return FALSE;
2887 return TRUE;
2888 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2889 if (format_desc->format == WINED3DFMT_R16_FLOAT)
2890 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2891 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2892 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2893 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2894 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2895 if (format_desc->format == WINED3DFMT_R32_FLOAT)
2896 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2897 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2898 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2899 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2900 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
2901 } else {
2902 /* Probably a color index mode */
2903 return FALSE;
2906 return FALSE;
2909 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2910 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2912 short depthSize, stencilSize;
2913 BOOL lockable = FALSE;
2915 if(!cfg)
2916 return FALSE;
2918 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2920 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2921 return FALSE;
2924 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32_FLOAT))
2925 lockable = TRUE;
2927 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2928 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2929 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2930 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2931 return FALSE;
2933 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2934 * allow more stencil bits than requested. */
2935 if(cfg->stencilSize < stencilSize)
2936 return FALSE;
2938 return TRUE;
2941 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2942 WINED3DFORMAT AdapterFormat,
2943 WINED3DFORMAT RenderTargetFormat,
2944 WINED3DFORMAT DepthStencilFormat) {
2945 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2946 int nCfgs;
2947 const WineD3D_PixelFormat *cfgs;
2948 const struct wined3d_adapter *adapter;
2949 const struct GlPixelFormatDesc *rt_format_desc;
2950 const struct GlPixelFormatDesc *ds_format_desc;
2951 int it;
2953 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2954 This, Adapter,
2955 DeviceType, debug_d3ddevicetype(DeviceType),
2956 AdapterFormat, debug_d3dformat(AdapterFormat),
2957 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2958 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2960 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2961 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2962 return WINED3DERR_INVALIDCALL;
2965 adapter = &This->adapters[Adapter];
2966 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
2967 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2968 cfgs = adapter->cfgs;
2969 nCfgs = adapter->nCfgs;
2970 for (it = 0; it < nCfgs; ++it) {
2971 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2973 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2975 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
2976 return WINED3D_OK;
2980 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2982 return WINED3DERR_NOTAVAILABLE;
2985 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2986 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
2988 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2989 const struct GlPixelFormatDesc *glDesc;
2990 const struct wined3d_adapter *adapter;
2992 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2993 This,
2994 Adapter,
2995 DeviceType, debug_d3ddevicetype(DeviceType),
2996 SurfaceFormat, debug_d3dformat(SurfaceFormat),
2997 Windowed,
2998 MultiSampleType,
2999 pQualityLevels);
3001 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3002 return WINED3DERR_INVALIDCALL;
3005 /* TODO: handle Windowed, add more quality levels */
3007 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
3008 if(pQualityLevels) *pQualityLevels = 1;
3009 return WINED3D_OK;
3012 /* By default multisampling is disabled right now as it causes issues
3013 * on some Nvidia driver versions and it doesn't work well in combination
3014 * with FBOs yet. */
3015 if(!wined3d_settings.allow_multisampling)
3016 return WINED3DERR_NOTAVAILABLE;
3018 adapter = &This->adapters[Adapter];
3019 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
3020 if (!glDesc) return WINED3DERR_INVALIDCALL;
3022 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
3023 int i, nCfgs;
3024 const WineD3D_PixelFormat *cfgs;
3026 cfgs = adapter->cfgs;
3027 nCfgs = adapter->nCfgs;
3028 for(i=0; i<nCfgs; i++) {
3029 if(cfgs[i].numSamples != MultiSampleType)
3030 continue;
3032 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
3033 continue;
3035 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
3037 if(pQualityLevels)
3038 *pQualityLevels = 1; /* Guess at a value! */
3039 return WINED3D_OK;
3042 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
3043 short redSize, greenSize, blueSize, alphaSize, colorBits;
3044 int i, nCfgs;
3045 const WineD3D_PixelFormat *cfgs;
3047 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
3049 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
3050 return WINED3DERR_NOTAVAILABLE;
3053 cfgs = adapter->cfgs;
3054 nCfgs = adapter->nCfgs;
3055 for(i=0; i<nCfgs; i++) {
3056 if(cfgs[i].numSamples != MultiSampleType)
3057 continue;
3058 if(cfgs[i].redSize != redSize)
3059 continue;
3060 if(cfgs[i].greenSize != greenSize)
3061 continue;
3062 if(cfgs[i].blueSize != blueSize)
3063 continue;
3064 /* Not all drivers report alpha-less formats since they use 32-bit anyway, so accept alpha even if we didn't ask for it. */
3065 if(alphaSize && cfgs[i].alphaSize != alphaSize)
3066 continue;
3067 if(cfgs[i].colorSize != (glDesc->byte_count << 3))
3068 continue;
3070 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
3072 if(pQualityLevels)
3073 *pQualityLevels = 1; /* Guess at a value! */
3074 return WINED3D_OK;
3077 return WINED3DERR_NOTAVAILABLE;
3080 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3081 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed)
3083 HRESULT hr = WINED3DERR_NOTAVAILABLE;
3084 UINT nmodes;
3086 TRACE("iface %p, adapter_idx %u, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
3087 iface, Adapter, debug_d3ddevicetype(DeviceType), debug_d3dformat(DisplayFormat),
3088 debug_d3dformat(BackBufferFormat), Windowed);
3090 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3091 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
3092 return WINED3DERR_INVALIDCALL;
3095 /* The task of this function is to check whether a certain display / backbuffer format
3096 * combination is available on the given adapter. In fullscreen mode microsoft specified
3097 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
3098 * and display format should match exactly.
3099 * In windowed mode format conversion can occur and this depends on the driver. When format
3100 * conversion is done, this function should nevertheless fail and applications need to use
3101 * CheckDeviceFormatConversion.
3102 * At the moment we assume that fullscreen and windowed have the same capabilities */
3104 /* There are only 4 display formats */
3105 if (!(DisplayFormat == WINED3DFMT_B5G6R5_UNORM
3106 || DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
3107 || DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
3108 || DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM))
3110 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
3111 return WINED3DERR_NOTAVAILABLE;
3114 /* If the requested DisplayFormat is not available, don't continue */
3115 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
3116 if(!nmodes) {
3117 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
3118 return WINED3DERR_NOTAVAILABLE;
3121 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
3122 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
3123 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
3124 return WINED3DERR_NOTAVAILABLE;
3127 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
3128 if (DisplayFormat == WINED3DFMT_B5G6R5_UNORM && BackBufferFormat != WINED3DFMT_B5G6R5_UNORM)
3130 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3131 return WINED3DERR_NOTAVAILABLE;
3134 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
3135 if (DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
3136 && !(BackBufferFormat == WINED3DFMT_B5G5R5X1_UNORM || BackBufferFormat == WINED3DFMT_B5G5R5A1_UNORM))
3138 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3139 return WINED3DERR_NOTAVAILABLE;
3142 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
3143 if (DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
3144 && !(BackBufferFormat == WINED3DFMT_B8G8R8X8_UNORM || BackBufferFormat == WINED3DFMT_B8G8R8A8_UNORM))
3146 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3147 return WINED3DERR_NOTAVAILABLE;
3150 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
3151 if (DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM
3152 && (BackBufferFormat != WINED3DFMT_B10G10R10A2_UNORM || Windowed))
3154 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3155 return WINED3DERR_NOTAVAILABLE;
3158 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
3159 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
3160 if(FAILED(hr))
3161 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3163 return hr;
3167 /* Check if we support bumpmapping for a format */
3168 static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter,
3169 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
3171 switch(format_desc->format)
3173 case WINED3DFMT_R8G8_SNORM:
3174 case WINED3DFMT_R16G16_SNORM:
3175 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3176 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3177 case WINED3DFMT_R8G8B8A8_SNORM:
3178 /* Ask the fixed function pipeline implementation if it can deal
3179 * with the conversion. If we've got a GL extension giving native
3180 * support this will be an identity conversion. */
3181 if (adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup))
3183 TRACE_(d3d_caps)("[OK]\n");
3184 return TRUE;
3186 TRACE_(d3d_caps)("[FAILED]\n");
3187 return FALSE;
3189 default:
3190 TRACE_(d3d_caps)("[FAILED]\n");
3191 return FALSE;
3195 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
3196 static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter,
3197 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
3199 int it=0;
3201 /* Only allow depth/stencil formats */
3202 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
3204 /* Walk through all WGL pixel formats to find a match */
3205 for (it = 0; it < adapter->nCfgs; ++it)
3207 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
3208 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
3210 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
3212 return TRUE;
3217 return FALSE;
3220 static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
3222 /* The flags entry of a format contains the filtering capability */
3223 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
3225 return FALSE;
3228 /* Check the render target capabilities of a format */
3229 static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter,
3230 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
3232 /* Filter out non-RT formats */
3233 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
3235 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
3236 WineD3D_PixelFormat *cfgs = adapter->cfgs;
3237 int it;
3238 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
3239 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
3241 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
3242 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
3244 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
3245 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
3246 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
3247 TRACE_(d3d_caps)("[FAILED]\n");
3248 return FALSE;
3251 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
3252 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
3253 for (it = 0; it < adapter->nCfgs; ++it)
3255 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
3256 &cfgs[it], check_format_desc))
3258 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
3259 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
3260 return TRUE;
3264 else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3266 /* For now return TRUE for FBOs until we have some proper checks.
3267 * Note that this function will only be called when the format is around for texturing. */
3268 return TRUE;
3270 return FALSE;
3273 static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
3275 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3277 /* Check for supported sRGB formats (Texture loading and framebuffer) */
3278 if (!gl_info->supported[EXT_TEXTURE_SRGB])
3280 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
3281 return FALSE;
3284 switch (format_desc->format)
3286 case WINED3DFMT_B8G8R8A8_UNORM:
3287 case WINED3DFMT_B8G8R8X8_UNORM:
3288 case WINED3DFMT_B4G4R4A4_UNORM:
3289 case WINED3DFMT_L8_UNORM:
3290 case WINED3DFMT_L8A8_UNORM:
3291 case WINED3DFMT_DXT1:
3292 case WINED3DFMT_DXT2:
3293 case WINED3DFMT_DXT3:
3294 case WINED3DFMT_DXT4:
3295 case WINED3DFMT_DXT5:
3296 TRACE_(d3d_caps)("[OK]\n");
3297 return TRUE;
3299 default:
3300 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
3301 return FALSE;
3303 return FALSE;
3306 static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter,
3307 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
3309 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
3310 * doing the color fixup in shaders.
3311 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
3312 if ((format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) || (format_desc->format == WINED3DFMT_B8G8R8A8_UNORM))
3314 int vs_selected_mode;
3315 int ps_selected_mode;
3316 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3318 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
3319 TRACE_(d3d_caps)("[OK]\n");
3320 return TRUE;
3324 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
3325 return FALSE;
3328 /* Check if a format support blending in combination with pixel shaders */
3329 static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapter,
3330 const struct GlPixelFormatDesc *format_desc)
3332 /* The flags entry of a format contains the post pixel shader blending capability */
3333 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
3335 return FALSE;
3338 static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
3340 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
3341 * but we have to report mipmapping so we cannot reject this flag. Tests show that
3342 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
3343 * that wrapping is supported. The lack of filtering will sort out the mipmapping
3344 * capability anyway.
3346 * For now lets report this on all formats, but in the future we may want to
3347 * restrict it to some should games need that
3349 return TRUE;
3352 /* Check if a texture format is supported on the given adapter */
3353 static BOOL CheckTextureCapability(struct wined3d_adapter *adapter,
3354 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
3356 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3358 switch (format_desc->format)
3360 /*****
3361 * supported: RGB(A) formats
3363 case WINED3DFMT_B8G8R8_UNORM: /* Enable for dx7, blacklisted for 8 and 9 above */
3364 case WINED3DFMT_B8G8R8A8_UNORM:
3365 case WINED3DFMT_B8G8R8X8_UNORM:
3366 case WINED3DFMT_B5G6R5_UNORM:
3367 case WINED3DFMT_B5G5R5X1_UNORM:
3368 case WINED3DFMT_B5G5R5A1_UNORM:
3369 case WINED3DFMT_B4G4R4A4_UNORM:
3370 case WINED3DFMT_A8_UNORM:
3371 case WINED3DFMT_B4G4R4X4_UNORM:
3372 case WINED3DFMT_R8G8B8A8_UNORM:
3373 case WINED3DFMT_R8G8B8X8_UNORM:
3374 case WINED3DFMT_B10G10R10A2_UNORM:
3375 case WINED3DFMT_R10G10B10A2_UNORM:
3376 case WINED3DFMT_R16G16_UNORM:
3377 TRACE_(d3d_caps)("[OK]\n");
3378 return TRUE;
3380 case WINED3DFMT_B2G3R3_UNORM:
3381 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
3382 return FALSE;
3384 /*****
3385 * supported: Palettized
3387 case WINED3DFMT_P8_UINT:
3388 TRACE_(d3d_caps)("[OK]\n");
3389 return TRUE;
3390 /* No Windows driver offers WINED3DFMT_P8_UINT_A8_UNORM, so don't offer it either */
3391 case WINED3DFMT_P8_UINT_A8_UNORM:
3392 return FALSE;
3394 /*****
3395 * Supported: (Alpha)-Luminance
3397 case WINED3DFMT_L8_UNORM:
3398 case WINED3DFMT_L8A8_UNORM:
3399 case WINED3DFMT_L16_UNORM:
3400 TRACE_(d3d_caps)("[OK]\n");
3401 return TRUE;
3403 /* Not supported on Windows, thus disabled */
3404 case WINED3DFMT_L4A4_UNORM:
3405 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
3406 return FALSE;
3408 /*****
3409 * Supported: Depth/Stencil formats
3411 case WINED3DFMT_D16_LOCKABLE:
3412 case WINED3DFMT_D16_UNORM:
3413 case WINED3DFMT_S1_UINT_D15_UNORM:
3414 case WINED3DFMT_X8D24_UNORM:
3415 case WINED3DFMT_S4X4_UINT_D24_UNORM:
3416 case WINED3DFMT_D24_UNORM_S8_UINT:
3417 case WINED3DFMT_S8_UINT_D24_FLOAT:
3418 case WINED3DFMT_D32_UNORM:
3419 case WINED3DFMT_D32_FLOAT:
3420 return TRUE;
3422 /*****
3423 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
3424 * GL_NV_texture_shader). Emulated by shaders
3426 case WINED3DFMT_R8G8_SNORM:
3427 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3428 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3429 case WINED3DFMT_R8G8B8A8_SNORM:
3430 case WINED3DFMT_R16G16_SNORM:
3431 /* Ask the shader backend if it can deal with the conversion. If
3432 * we've got a GL extension giving native support this will be an
3433 * identity conversion. */
3434 if (adapter->shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
3436 TRACE_(d3d_caps)("[OK]\n");
3437 return TRUE;
3439 TRACE_(d3d_caps)("[FAILED]\n");
3440 return FALSE;
3442 case WINED3DFMT_DXT1:
3443 case WINED3DFMT_DXT2:
3444 case WINED3DFMT_DXT3:
3445 case WINED3DFMT_DXT4:
3446 case WINED3DFMT_DXT5:
3447 if (gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC])
3449 TRACE_(d3d_caps)("[OK]\n");
3450 return TRUE;
3452 TRACE_(d3d_caps)("[FAILED]\n");
3453 return FALSE;
3456 /*****
3457 * Odd formats - not supported
3459 case WINED3DFMT_VERTEXDATA:
3460 case WINED3DFMT_R16_UINT:
3461 case WINED3DFMT_R32_UINT:
3462 case WINED3DFMT_R16G16B16A16_SNORM:
3463 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM:
3464 case WINED3DFMT_R10G11B11_SNORM:
3465 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3466 return FALSE;
3468 /*****
3469 * WINED3DFMT_R8G8_SNORM_Cx: Not supported right now
3471 case WINED3DFMT_R8G8_SNORM_Cx:
3472 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3473 return FALSE;
3475 /* YUV formats */
3476 case WINED3DFMT_UYVY:
3477 case WINED3DFMT_YUY2:
3478 if (gl_info->supported[APPLE_YCBCR_422])
3480 TRACE_(d3d_caps)("[OK]\n");
3481 return TRUE;
3483 TRACE_(d3d_caps)("[FAILED]\n");
3484 return FALSE;
3485 case WINED3DFMT_YV12:
3486 TRACE_(d3d_caps)("[FAILED]\n");
3487 return FALSE;
3489 /* Not supported */
3490 case WINED3DFMT_R16G16B16A16_UNORM:
3491 case WINED3DFMT_B2G3R3A8_UNORM:
3492 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3493 return FALSE;
3495 /* Floating point formats */
3496 case WINED3DFMT_R16_FLOAT:
3497 case WINED3DFMT_R16G16_FLOAT:
3498 case WINED3DFMT_R16G16B16A16_FLOAT:
3499 if (gl_info->supported[ARB_TEXTURE_FLOAT] && gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3501 TRACE_(d3d_caps)("[OK]\n");
3502 return TRUE;
3504 TRACE_(d3d_caps)("[FAILED]\n");
3505 return FALSE;
3507 case WINED3DFMT_R32_FLOAT:
3508 case WINED3DFMT_R32G32_FLOAT:
3509 case WINED3DFMT_R32G32B32A32_FLOAT:
3510 if (gl_info->supported[ARB_TEXTURE_FLOAT])
3512 TRACE_(d3d_caps)("[OK]\n");
3513 return TRUE;
3515 TRACE_(d3d_caps)("[FAILED]\n");
3516 return FALSE;
3518 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3519 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3520 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3521 * We can do instancing with all shader versions, but we need vertex shaders.
3523 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3524 * to enable instancing. WineD3D doesn't need that and just ignores it.
3526 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3528 case WINED3DFMT_INST:
3529 TRACE("ATI Instancing check hack\n");
3530 if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
3532 TRACE_(d3d_caps)("[OK]\n");
3533 return TRUE;
3535 TRACE_(d3d_caps)("[FAILED]\n");
3536 return FALSE;
3538 /* Some weird FOURCC formats */
3539 case WINED3DFMT_R8G8_B8G8:
3540 case WINED3DFMT_G8R8_G8B8:
3541 case WINED3DFMT_MULTI2_ARGB8:
3542 TRACE_(d3d_caps)("[FAILED]\n");
3543 return FALSE;
3545 /* Vendor specific formats */
3546 case WINED3DFMT_ATI2N:
3547 if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC]
3548 || gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
3550 if (adapter->shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3551 && adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup))
3553 TRACE_(d3d_caps)("[OK]\n");
3554 return TRUE;
3557 TRACE_(d3d_caps)("[OK]\n");
3558 return TRUE;
3560 TRACE_(d3d_caps)("[FAILED]\n");
3561 return FALSE;
3563 case WINED3DFMT_NVHU:
3564 case WINED3DFMT_NVHS:
3565 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3566 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3567 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3568 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3569 * Applications have to deal with not having NVHS and NVHU.
3571 TRACE_(d3d_caps)("[FAILED]\n");
3572 return FALSE;
3574 case WINED3DFMT_UNKNOWN:
3575 return FALSE;
3577 default:
3578 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3579 break;
3581 return FALSE;
3584 static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
3585 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
3587 if(SurfaceType == SURFACE_GDI) {
3588 switch(check_format_desc->format)
3590 case WINED3DFMT_B8G8R8_UNORM:
3591 case WINED3DFMT_B8G8R8A8_UNORM:
3592 case WINED3DFMT_B8G8R8X8_UNORM:
3593 case WINED3DFMT_B5G6R5_UNORM:
3594 case WINED3DFMT_B5G5R5X1_UNORM:
3595 case WINED3DFMT_B5G5R5A1_UNORM:
3596 case WINED3DFMT_B4G4R4A4_UNORM:
3597 case WINED3DFMT_B2G3R3_UNORM:
3598 case WINED3DFMT_A8_UNORM:
3599 case WINED3DFMT_B2G3R3A8_UNORM:
3600 case WINED3DFMT_B4G4R4X4_UNORM:
3601 case WINED3DFMT_R10G10B10A2_UNORM:
3602 case WINED3DFMT_R8G8B8A8_UNORM:
3603 case WINED3DFMT_R8G8B8X8_UNORM:
3604 case WINED3DFMT_R16G16_UNORM:
3605 case WINED3DFMT_B10G10R10A2_UNORM:
3606 case WINED3DFMT_R16G16B16A16_UNORM:
3607 case WINED3DFMT_P8_UINT:
3608 TRACE_(d3d_caps)("[OK]\n");
3609 return TRUE;
3610 default:
3611 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3612 return FALSE;
3616 /* All format that are supported for textures are supported for surfaces as well */
3617 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3618 /* All depth stencil formats are supported on surfaces */
3619 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3621 /* If opengl can't process the format natively, the blitter may be able to convert it */
3622 if (adapter->blitter->color_fixup_supported(&adapter->gl_info, check_format_desc->color_fixup))
3624 TRACE_(d3d_caps)("[OK]\n");
3625 return TRUE;
3628 /* Reject other formats */
3629 TRACE_(d3d_caps)("[FAILED]\n");
3630 return FALSE;
3633 static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
3635 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3637 if (!gl_info->limits.vertex_samplers)
3639 TRACE_(d3d_caps)("[FAILED]\n");
3640 return FALSE;
3643 switch (format_desc->format)
3645 case WINED3DFMT_R32G32B32A32_FLOAT:
3646 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
3648 TRACE_(d3d_caps)("[FAILED]\n");
3649 return FALSE;
3651 TRACE_(d3d_caps)("[OK]\n");
3652 return TRUE;
3654 default:
3655 TRACE_(d3d_caps)("[FAILED]\n");
3656 return FALSE;
3658 return FALSE;
3661 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3662 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3663 WINED3DSURFTYPE SurfaceType)
3665 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3666 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3667 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3668 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3669 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3670 DWORD UsageCaps = 0;
3672 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3673 This,
3674 Adapter,
3675 DeviceType, debug_d3ddevicetype(DeviceType),
3676 AdapterFormat, debug_d3dformat(AdapterFormat),
3677 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3678 RType, debug_d3dresourcetype(RType),
3679 CheckFormat, debug_d3dformat(CheckFormat));
3681 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3682 return WINED3DERR_INVALIDCALL;
3685 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3687 if(SurfaceType != SURFACE_OPENGL) {
3688 TRACE("[FAILED]\n");
3689 return WINED3DERR_NOTAVAILABLE;
3692 /* Cubetexture allows:
3693 * - D3DUSAGE_AUTOGENMIPMAP
3694 * - D3DUSAGE_DEPTHSTENCIL
3695 * - D3DUSAGE_DYNAMIC
3696 * - D3DUSAGE_NONSECURE (d3d9ex)
3697 * - D3DUSAGE_RENDERTARGET
3698 * - D3DUSAGE_SOFTWAREPROCESSING
3699 * - D3DUSAGE_QUERY_WRAPANDMIP
3701 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3703 /* Check if the texture format is around */
3704 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3706 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3707 /* Check for automatic mipmap generation support */
3708 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3710 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3711 } else {
3712 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3713 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3717 /* Always report dynamic locking */
3718 if(Usage & WINED3DUSAGE_DYNAMIC)
3719 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3721 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3722 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3724 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3725 } else {
3726 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3727 return WINED3DERR_NOTAVAILABLE;
3731 /* Always report software processing */
3732 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3733 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3735 /* Check QUERY_FILTER support */
3736 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3737 if (CheckFilterCapability(adapter, format_desc))
3739 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3740 } else {
3741 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3742 return WINED3DERR_NOTAVAILABLE;
3746 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3747 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3748 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3750 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3751 } else {
3752 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3753 return WINED3DERR_NOTAVAILABLE;
3757 /* Check QUERY_SRGBREAD support */
3758 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3759 if (CheckSrgbReadCapability(adapter, format_desc))
3761 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3762 } else {
3763 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3764 return WINED3DERR_NOTAVAILABLE;
3768 /* Check QUERY_SRGBWRITE support */
3769 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3770 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3772 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3773 } else {
3774 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3775 return WINED3DERR_NOTAVAILABLE;
3779 /* Check QUERY_VERTEXTEXTURE support */
3780 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3781 if (CheckVertexTextureCapability(adapter, format_desc))
3783 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3784 } else {
3785 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3786 return WINED3DERR_NOTAVAILABLE;
3790 /* Check QUERY_WRAPANDMIP support */
3791 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3792 if (CheckWrapAndMipCapability(adapter, format_desc))
3794 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3795 } else {
3796 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3797 return WINED3DERR_NOTAVAILABLE;
3800 } else {
3801 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3802 return WINED3DERR_NOTAVAILABLE;
3804 } else {
3805 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3806 return WINED3DERR_NOTAVAILABLE;
3808 } else if(RType == WINED3DRTYPE_SURFACE) {
3809 /* Surface allows:
3810 * - D3DUSAGE_DEPTHSTENCIL
3811 * - D3DUSAGE_NONSECURE (d3d9ex)
3812 * - D3DUSAGE_RENDERTARGET
3815 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3817 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3818 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3820 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3821 } else {
3822 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3823 return WINED3DERR_NOTAVAILABLE;
3827 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3828 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3830 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3831 } else {
3832 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3833 return WINED3DERR_NOTAVAILABLE;
3837 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3838 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3839 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3841 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3842 } else {
3843 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3844 return WINED3DERR_NOTAVAILABLE;
3847 } else {
3848 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3849 return WINED3DERR_NOTAVAILABLE;
3852 } else if(RType == WINED3DRTYPE_TEXTURE) {
3853 /* Texture allows:
3854 * - D3DUSAGE_AUTOGENMIPMAP
3855 * - D3DUSAGE_DEPTHSTENCIL
3856 * - D3DUSAGE_DMAP
3857 * - D3DUSAGE_DYNAMIC
3858 * - D3DUSAGE_NONSECURE (d3d9ex)
3859 * - D3DUSAGE_RENDERTARGET
3860 * - D3DUSAGE_SOFTWAREPROCESSING
3861 * - D3DUSAGE_TEXTAPI (d3d9ex)
3862 * - D3DUSAGE_QUERY_WRAPANDMIP
3865 if(SurfaceType != SURFACE_OPENGL) {
3866 TRACE("[FAILED]\n");
3867 return WINED3DERR_NOTAVAILABLE;
3870 /* Check if the texture format is around */
3871 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3873 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3874 /* Check for automatic mipmap generation support */
3875 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3877 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3878 } else {
3879 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3880 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3884 /* Always report dynamic locking */
3885 if(Usage & WINED3DUSAGE_DYNAMIC)
3886 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3888 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3889 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3891 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3892 } else {
3893 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3894 return WINED3DERR_NOTAVAILABLE;
3898 /* Always report software processing */
3899 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3900 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3902 /* Check QUERY_FILTER support */
3903 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3904 if (CheckFilterCapability(adapter, format_desc))
3906 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3907 } else {
3908 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3909 return WINED3DERR_NOTAVAILABLE;
3913 /* Check QUERY_LEGACYBUMPMAP support */
3914 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3915 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3917 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3918 } else {
3919 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3920 return WINED3DERR_NOTAVAILABLE;
3924 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3925 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3926 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3928 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3929 } else {
3930 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3931 return WINED3DERR_NOTAVAILABLE;
3935 /* Check QUERY_SRGBREAD support */
3936 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3937 if (CheckSrgbReadCapability(adapter, format_desc))
3939 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3940 } else {
3941 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3942 return WINED3DERR_NOTAVAILABLE;
3946 /* Check QUERY_SRGBWRITE support */
3947 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3948 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3950 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3951 } else {
3952 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3953 return WINED3DERR_NOTAVAILABLE;
3957 /* Check QUERY_VERTEXTEXTURE support */
3958 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3959 if (CheckVertexTextureCapability(adapter, format_desc))
3961 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3962 } else {
3963 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3964 return WINED3DERR_NOTAVAILABLE;
3968 /* Check QUERY_WRAPANDMIP support */
3969 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3970 if (CheckWrapAndMipCapability(adapter, format_desc))
3972 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3973 } else {
3974 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3975 return WINED3DERR_NOTAVAILABLE;
3979 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3980 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3982 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3983 } else {
3984 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
3985 return WINED3DERR_NOTAVAILABLE;
3988 } else {
3989 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3990 return WINED3DERR_NOTAVAILABLE;
3992 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
3993 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
3994 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
3996 * Volumetexture allows:
3997 * - D3DUSAGE_DYNAMIC
3998 * - D3DUSAGE_NONSECURE (d3d9ex)
3999 * - D3DUSAGE_SOFTWAREPROCESSING
4000 * - D3DUSAGE_QUERY_WRAPANDMIP
4003 if(SurfaceType != SURFACE_OPENGL) {
4004 TRACE("[FAILED]\n");
4005 return WINED3DERR_NOTAVAILABLE;
4008 /* Check volume texture and volume usage caps */
4009 if (gl_info->supported[EXT_TEXTURE3D])
4011 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
4013 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
4014 return WINED3DERR_NOTAVAILABLE;
4017 /* Always report dynamic locking */
4018 if(Usage & WINED3DUSAGE_DYNAMIC)
4019 UsageCaps |= WINED3DUSAGE_DYNAMIC;
4021 /* Always report software processing */
4022 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
4023 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
4025 /* Check QUERY_FILTER support */
4026 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
4027 if (CheckFilterCapability(adapter, format_desc))
4029 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
4030 } else {
4031 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
4032 return WINED3DERR_NOTAVAILABLE;
4036 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
4037 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
4038 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
4040 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
4041 } else {
4042 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
4043 return WINED3DERR_NOTAVAILABLE;
4047 /* Check QUERY_SRGBREAD support */
4048 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
4049 if (CheckSrgbReadCapability(adapter, format_desc))
4051 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
4052 } else {
4053 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
4054 return WINED3DERR_NOTAVAILABLE;
4058 /* Check QUERY_SRGBWRITE support */
4059 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
4060 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
4062 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
4063 } else {
4064 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
4065 return WINED3DERR_NOTAVAILABLE;
4069 /* Check QUERY_VERTEXTEXTURE support */
4070 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
4071 if (CheckVertexTextureCapability(adapter, format_desc))
4073 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
4074 } else {
4075 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
4076 return WINED3DERR_NOTAVAILABLE;
4080 /* Check QUERY_WRAPANDMIP support */
4081 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
4082 if (CheckWrapAndMipCapability(adapter, format_desc))
4084 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
4085 } else {
4086 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
4087 return WINED3DERR_NOTAVAILABLE;
4090 } else {
4091 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
4092 return WINED3DERR_NOTAVAILABLE;
4095 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
4096 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
4097 * app needing one of those formats, don't advertize them to avoid leading apps into
4098 * temptation. The windows drivers don't support most of those formats on volumes anyway,
4099 * except of R32F.
4101 switch(CheckFormat) {
4102 case WINED3DFMT_P8_UINT:
4103 case WINED3DFMT_L4A4_UNORM:
4104 case WINED3DFMT_R32_FLOAT:
4105 case WINED3DFMT_R16_FLOAT:
4106 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
4107 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
4108 case WINED3DFMT_R16G16_UNORM:
4109 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4110 return WINED3DERR_NOTAVAILABLE;
4112 case WINED3DFMT_R8G8B8A8_SNORM:
4113 case WINED3DFMT_R16G16_SNORM:
4114 if (!gl_info->supported[NV_TEXTURE_SHADER])
4116 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4117 return WINED3DERR_NOTAVAILABLE;
4119 break;
4121 case WINED3DFMT_R8G8_SNORM:
4122 if (!gl_info->supported[NV_TEXTURE_SHADER])
4124 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4125 return WINED3DERR_NOTAVAILABLE;
4127 break;
4129 case WINED3DFMT_DXT1:
4130 case WINED3DFMT_DXT2:
4131 case WINED3DFMT_DXT3:
4132 case WINED3DFMT_DXT4:
4133 case WINED3DFMT_DXT5:
4134 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
4135 * compressed texture results in an error. While the D3D refrast does
4136 * support s3tc volumes, at least the nvidia windows driver does not, so
4137 * we're free not to support this format.
4139 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
4140 return WINED3DERR_NOTAVAILABLE;
4142 default:
4143 /* Do nothing, continue with checking the format below */
4144 break;
4146 } else if(RType == WINED3DRTYPE_BUFFER){
4147 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
4148 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
4149 return WINED3DERR_NOTAVAILABLE;
4152 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
4153 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
4154 * usage flags match. */
4155 if(UsageCaps == Usage) {
4156 return WINED3D_OK;
4157 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
4158 return WINED3DOK_NOAUTOGEN;
4159 } else {
4160 TRACE_(d3d_caps)("[FAILED] - Usage=%#08x requested for CheckFormat=%s and RType=%d but only %#08x is available\n", Usage, debug_d3dformat(CheckFormat), RType, UsageCaps);
4161 return WINED3DERR_NOTAVAILABLE;
4165 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT adapter_idx,
4166 WINED3DDEVTYPE device_type, WINED3DFORMAT src_format, WINED3DFORMAT dst_format)
4168 FIXME("iface %p, adapter_idx %u, device_type %s, src_format %s, dst_format %s stub!\n",
4169 iface, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(src_format),
4170 debug_d3dformat(dst_format));
4172 return WINED3D_OK;
4175 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
4176 subset of a D3DCAPS9 structure. However, it has to come via a void *
4177 as the d3d8 interface cannot import the d3d9 header */
4178 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
4180 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4181 struct wined3d_adapter *adapter = &This->adapters[Adapter];
4182 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4183 int vs_selected_mode;
4184 int ps_selected_mode;
4185 struct shader_caps shader_caps;
4186 struct fragment_caps fragment_caps;
4187 DWORD ckey_caps, blit_caps, fx_caps;
4189 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
4191 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
4192 return WINED3DERR_INVALIDCALL;
4195 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
4197 /* ------------------------------------------------
4198 The following fields apply to both d3d8 and d3d9
4199 ------------------------------------------------ */
4200 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
4201 pCaps->AdapterOrdinal = Adapter;
4203 pCaps->Caps = 0;
4204 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
4205 WINED3DCAPS2_FULLSCREENGAMMA |
4206 WINED3DCAPS2_DYNAMICTEXTURES;
4207 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
4209 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
4212 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
4213 WINED3DCAPS3_COPY_TO_VIDMEM |
4214 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
4216 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
4217 WINED3DPRESENT_INTERVAL_ONE;
4219 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
4220 WINED3DCURSORCAPS_LOWRES;
4222 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
4223 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
4224 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
4225 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4226 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
4227 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
4228 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
4229 WINED3DDEVCAPS_PUREDEVICE |
4230 WINED3DDEVCAPS_HWRASTERIZATION |
4231 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
4232 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
4233 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
4234 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
4235 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
4236 WINED3DDEVCAPS_RTPATCHES;
4238 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
4239 WINED3DPMISCCAPS_CULLCCW |
4240 WINED3DPMISCCAPS_CULLCW |
4241 WINED3DPMISCCAPS_COLORWRITEENABLE |
4242 WINED3DPMISCCAPS_CLIPTLVERTS |
4243 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
4244 WINED3DPMISCCAPS_MASKZ |
4245 WINED3DPMISCCAPS_BLENDOP |
4246 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
4247 /* TODO:
4248 WINED3DPMISCCAPS_NULLREFERENCE
4249 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
4250 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
4251 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
4252 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
4254 if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
4255 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
4257 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
4258 WINED3DPRASTERCAPS_PAT |
4259 WINED3DPRASTERCAPS_WFOG |
4260 WINED3DPRASTERCAPS_ZFOG |
4261 WINED3DPRASTERCAPS_FOGVERTEX |
4262 WINED3DPRASTERCAPS_FOGTABLE |
4263 WINED3DPRASTERCAPS_STIPPLE |
4264 WINED3DPRASTERCAPS_SUBPIXEL |
4265 WINED3DPRASTERCAPS_ZTEST |
4266 WINED3DPRASTERCAPS_SCISSORTEST |
4267 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
4268 WINED3DPRASTERCAPS_DEPTHBIAS;
4270 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4272 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
4273 WINED3DPRASTERCAPS_ZBIAS |
4274 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
4276 if (gl_info->supported[NV_FOG_DISTANCE])
4278 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
4280 /* FIXME Add:
4281 WINED3DPRASTERCAPS_COLORPERSPECTIVE
4282 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
4283 WINED3DPRASTERCAPS_ANTIALIASEDGES
4284 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
4285 WINED3DPRASTERCAPS_WBUFFER */
4287 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
4288 WINED3DPCMPCAPS_EQUAL |
4289 WINED3DPCMPCAPS_GREATER |
4290 WINED3DPCMPCAPS_GREATEREQUAL |
4291 WINED3DPCMPCAPS_LESS |
4292 WINED3DPCMPCAPS_LESSEQUAL |
4293 WINED3DPCMPCAPS_NEVER |
4294 WINED3DPCMPCAPS_NOTEQUAL;
4296 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
4297 WINED3DPBLENDCAPS_BOTHSRCALPHA |
4298 WINED3DPBLENDCAPS_DESTALPHA |
4299 WINED3DPBLENDCAPS_DESTCOLOR |
4300 WINED3DPBLENDCAPS_INVDESTALPHA |
4301 WINED3DPBLENDCAPS_INVDESTCOLOR |
4302 WINED3DPBLENDCAPS_INVSRCALPHA |
4303 WINED3DPBLENDCAPS_INVSRCCOLOR |
4304 WINED3DPBLENDCAPS_ONE |
4305 WINED3DPBLENDCAPS_SRCALPHA |
4306 WINED3DPBLENDCAPS_SRCALPHASAT |
4307 WINED3DPBLENDCAPS_SRCCOLOR |
4308 WINED3DPBLENDCAPS_ZERO;
4310 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
4311 WINED3DPBLENDCAPS_DESTCOLOR |
4312 WINED3DPBLENDCAPS_INVDESTALPHA |
4313 WINED3DPBLENDCAPS_INVDESTCOLOR |
4314 WINED3DPBLENDCAPS_INVSRCALPHA |
4315 WINED3DPBLENDCAPS_INVSRCCOLOR |
4316 WINED3DPBLENDCAPS_ONE |
4317 WINED3DPBLENDCAPS_SRCALPHA |
4318 WINED3DPBLENDCAPS_SRCCOLOR |
4319 WINED3DPBLENDCAPS_ZERO;
4320 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
4321 * according to the glBlendFunc manpage
4323 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
4324 * legacy settings for srcblend only
4327 if (gl_info->supported[EXT_BLEND_COLOR])
4329 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
4330 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
4334 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
4335 WINED3DPCMPCAPS_EQUAL |
4336 WINED3DPCMPCAPS_GREATER |
4337 WINED3DPCMPCAPS_GREATEREQUAL |
4338 WINED3DPCMPCAPS_LESS |
4339 WINED3DPCMPCAPS_LESSEQUAL |
4340 WINED3DPCMPCAPS_NEVER |
4341 WINED3DPCMPCAPS_NOTEQUAL;
4343 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
4344 WINED3DPSHADECAPS_COLORGOURAUDRGB |
4345 WINED3DPSHADECAPS_ALPHAFLATBLEND |
4346 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
4347 WINED3DPSHADECAPS_COLORFLATRGB |
4348 WINED3DPSHADECAPS_FOGFLAT |
4349 WINED3DPSHADECAPS_FOGGOURAUD |
4350 WINED3DPSHADECAPS_SPECULARFLATRGB;
4352 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
4353 WINED3DPTEXTURECAPS_ALPHAPALETTE |
4354 WINED3DPTEXTURECAPS_TRANSPARENCY |
4355 WINED3DPTEXTURECAPS_BORDER |
4356 WINED3DPTEXTURECAPS_MIPMAP |
4357 WINED3DPTEXTURECAPS_PROJECTED |
4358 WINED3DPTEXTURECAPS_PERSPECTIVE;
4360 if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
4362 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
4363 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
4366 if (gl_info->supported[EXT_TEXTURE3D])
4368 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
4369 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
4370 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
4373 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4375 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
4376 WINED3DPTEXTURECAPS_MIPCUBEMAP |
4377 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
4381 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4382 WINED3DPTFILTERCAPS_MAGFPOINT |
4383 WINED3DPTFILTERCAPS_MINFLINEAR |
4384 WINED3DPTFILTERCAPS_MINFPOINT |
4385 WINED3DPTFILTERCAPS_MIPFLINEAR |
4386 WINED3DPTFILTERCAPS_MIPFPOINT |
4387 WINED3DPTFILTERCAPS_LINEAR |
4388 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4389 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4390 WINED3DPTFILTERCAPS_MIPLINEAR |
4391 WINED3DPTFILTERCAPS_MIPNEAREST |
4392 WINED3DPTFILTERCAPS_NEAREST;
4394 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4396 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4397 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4400 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4402 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4403 WINED3DPTFILTERCAPS_MAGFPOINT |
4404 WINED3DPTFILTERCAPS_MINFLINEAR |
4405 WINED3DPTFILTERCAPS_MINFPOINT |
4406 WINED3DPTFILTERCAPS_MIPFLINEAR |
4407 WINED3DPTFILTERCAPS_MIPFPOINT |
4408 WINED3DPTFILTERCAPS_LINEAR |
4409 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4410 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4411 WINED3DPTFILTERCAPS_MIPLINEAR |
4412 WINED3DPTFILTERCAPS_MIPNEAREST |
4413 WINED3DPTFILTERCAPS_NEAREST;
4415 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4417 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4418 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4420 } else
4421 pCaps->CubeTextureFilterCaps = 0;
4423 if (gl_info->supported[EXT_TEXTURE3D])
4425 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4426 WINED3DPTFILTERCAPS_MAGFPOINT |
4427 WINED3DPTFILTERCAPS_MINFLINEAR |
4428 WINED3DPTFILTERCAPS_MINFPOINT |
4429 WINED3DPTFILTERCAPS_MIPFLINEAR |
4430 WINED3DPTFILTERCAPS_MIPFPOINT |
4431 WINED3DPTFILTERCAPS_LINEAR |
4432 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4433 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4434 WINED3DPTFILTERCAPS_MIPLINEAR |
4435 WINED3DPTFILTERCAPS_MIPNEAREST |
4436 WINED3DPTFILTERCAPS_NEAREST;
4437 } else
4438 pCaps->VolumeTextureFilterCaps = 0;
4440 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4441 WINED3DPTADDRESSCAPS_CLAMP |
4442 WINED3DPTADDRESSCAPS_WRAP;
4444 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4446 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4448 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4450 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4452 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4454 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4457 if (gl_info->supported[EXT_TEXTURE3D])
4459 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4460 WINED3DPTADDRESSCAPS_CLAMP |
4461 WINED3DPTADDRESSCAPS_WRAP;
4462 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4464 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4466 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4468 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4470 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4472 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4474 } else
4475 pCaps->VolumeTextureAddressCaps = 0;
4477 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4478 WINED3DLINECAPS_ZTEST |
4479 WINED3DLINECAPS_BLEND |
4480 WINED3DLINECAPS_ALPHACMP |
4481 WINED3DLINECAPS_FOG;
4482 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4483 * idea how generating the smoothing alpha values works; the result is different
4486 pCaps->MaxTextureWidth = gl_info->limits.texture_size;
4487 pCaps->MaxTextureHeight = gl_info->limits.texture_size;
4489 if (gl_info->supported[EXT_TEXTURE3D])
4490 pCaps->MaxVolumeExtent = gl_info->limits.texture3d_size;
4491 else
4492 pCaps->MaxVolumeExtent = 0;
4494 pCaps->MaxTextureRepeat = 32768;
4495 pCaps->MaxTextureAspectRatio = gl_info->limits.texture_size;
4496 pCaps->MaxVertexW = 1.0f;
4498 pCaps->GuardBandLeft = 0.0f;
4499 pCaps->GuardBandTop = 0.0f;
4500 pCaps->GuardBandRight = 0.0f;
4501 pCaps->GuardBandBottom = 0.0f;
4503 pCaps->ExtentsAdjust = 0.0f;
4505 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4506 WINED3DSTENCILCAPS_INCRSAT |
4507 WINED3DSTENCILCAPS_INVERT |
4508 WINED3DSTENCILCAPS_KEEP |
4509 WINED3DSTENCILCAPS_REPLACE |
4510 WINED3DSTENCILCAPS_ZERO;
4511 if (gl_info->supported[EXT_STENCIL_WRAP])
4513 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4514 WINED3DSTENCILCAPS_INCR;
4516 if (gl_info->supported[EXT_STENCIL_TWO_SIDE] || gl_info->supported[ATI_SEPARATE_STENCIL])
4518 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4521 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4523 pCaps->MaxUserClipPlanes = gl_info->limits.clipplanes;
4524 pCaps->MaxActiveLights = gl_info->limits.lights;
4526 pCaps->MaxVertexBlendMatrices = gl_info->limits.blends;
4527 pCaps->MaxVertexBlendMatrixIndex = 0;
4529 pCaps->MaxAnisotropy = gl_info->limits.anisotropy;
4530 pCaps->MaxPointSize = gl_info->limits.pointsize_max;
4533 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4534 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4535 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4536 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4537 WINED3DVTXPCAPS_LOCALVIEWER |
4538 WINED3DVTXPCAPS_VERTEXFOG |
4539 WINED3DVTXPCAPS_TEXGEN;
4541 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4542 pCaps->MaxVertexIndex = 0xFFFFF;
4543 pCaps->MaxStreams = MAX_STREAMS;
4544 pCaps->MaxStreamStride = 1024;
4546 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4547 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4548 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4549 pCaps->MaxNpatchTessellationLevel = 0;
4550 pCaps->MasterAdapterOrdinal = 0;
4551 pCaps->AdapterOrdinalInGroup = 0;
4552 pCaps->NumberOfAdaptersInGroup = 1;
4554 pCaps->NumSimultaneousRTs = gl_info->limits.buffers;
4556 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4557 WINED3DPTFILTERCAPS_MAGFPOINT |
4558 WINED3DPTFILTERCAPS_MINFLINEAR |
4559 WINED3DPTFILTERCAPS_MAGFLINEAR;
4560 pCaps->VertexTextureFilterCaps = 0;
4562 memset(&shader_caps, 0, sizeof(shader_caps));
4563 adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
4565 memset(&fragment_caps, 0, sizeof(fragment_caps));
4566 adapter->fragment_pipe->get_caps(&adapter->gl_info, &fragment_caps);
4568 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4569 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4571 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4572 * Ignore shader model capabilities if disabled in config
4574 if(vs_selected_mode == SHADER_NONE) {
4575 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4576 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4577 pCaps->MaxVertexShaderConst = 0;
4578 } else {
4579 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4580 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4583 if(ps_selected_mode == SHADER_NONE) {
4584 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4585 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4586 pCaps->PixelShader1xMaxValue = 0.0f;
4587 } else {
4588 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4589 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4592 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4593 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4594 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4596 pCaps->VS20Caps = shader_caps.VS20Caps;
4597 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4598 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4599 pCaps->PS20Caps = shader_caps.PS20Caps;
4600 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4601 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4603 /* The following caps are shader specific, but they are things we cannot detect, or which
4604 * are the same among all shader models. So to avoid code duplication set the shader version
4605 * specific, but otherwise constant caps here
4607 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4608 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4609 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4610 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4611 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4612 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_vs_temps);
4613 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4615 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4616 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
4618 else if (pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0))
4620 pCaps->VS20Caps.Caps = 0;
4621 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4622 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_vs_temps);
4623 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4625 pCaps->MaxVShaderInstructionsExecuted = 65535;
4626 pCaps->MaxVertexShader30InstructionSlots = 0;
4627 } else { /* VS 1.x */
4628 pCaps->VS20Caps.Caps = 0;
4629 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4630 pCaps->VS20Caps.NumTemps = 0;
4631 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4633 pCaps->MaxVShaderInstructionsExecuted = 0;
4634 pCaps->MaxVertexShader30InstructionSlots = 0;
4637 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4638 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4639 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4641 /* 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 */
4642 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4643 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4644 WINED3DPS20CAPS_PREDICATION |
4645 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4646 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4647 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4648 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_ps_temps);
4649 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4650 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4652 pCaps->MaxPShaderInstructionsExecuted = 65535;
4653 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS,
4654 adapter->gl_info.limits.arb_ps_instructions);
4656 else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0))
4658 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4659 pCaps->PS20Caps.Caps = 0;
4660 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4661 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_ps_temps);
4662 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4663 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4665 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4666 pCaps->MaxPixelShader30InstructionSlots = 0;
4667 } else { /* PS 1.x */
4668 pCaps->PS20Caps.Caps = 0;
4669 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4670 pCaps->PS20Caps.NumTemps = 0;
4671 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4672 pCaps->PS20Caps.NumInstructionSlots = 0;
4674 pCaps->MaxPShaderInstructionsExecuted = 0;
4675 pCaps->MaxPixelShader30InstructionSlots = 0;
4678 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4679 /* OpenGL supports all the formats below, perhaps not always
4680 * without conversion, but it supports them.
4681 * Further GLSL doesn't seem to have an official unsigned type so
4682 * don't advertise it yet as I'm not sure how we handle it.
4683 * We might need to add some clamping in the shader engine to
4684 * support it.
4685 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4686 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4687 WINED3DDTCAPS_UBYTE4N |
4688 WINED3DDTCAPS_SHORT2N |
4689 WINED3DDTCAPS_SHORT4N;
4690 if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
4692 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4693 WINED3DDTCAPS_FLOAT16_4;
4695 } else
4696 pCaps->DeclTypes = 0;
4698 /* Set DirectDraw helper Caps */
4699 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4700 WINEDDCKEYCAPS_SRCBLT;
4701 fx_caps = WINEDDFXCAPS_BLTALPHA |
4702 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4703 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4704 WINEDDFXCAPS_BLTROTATION90 |
4705 WINEDDFXCAPS_BLTSHRINKX |
4706 WINEDDFXCAPS_BLTSHRINKXN |
4707 WINEDDFXCAPS_BLTSHRINKY |
4708 WINEDDFXCAPS_BLTSHRINKXN |
4709 WINEDDFXCAPS_BLTSTRETCHX |
4710 WINEDDFXCAPS_BLTSTRETCHXN |
4711 WINEDDFXCAPS_BLTSTRETCHY |
4712 WINEDDFXCAPS_BLTSTRETCHYN;
4713 blit_caps = WINEDDCAPS_BLT |
4714 WINEDDCAPS_BLTCOLORFILL |
4715 WINEDDCAPS_BLTDEPTHFILL |
4716 WINEDDCAPS_BLTSTRETCH |
4717 WINEDDCAPS_CANBLTSYSMEM |
4718 WINEDDCAPS_CANCLIP |
4719 WINEDDCAPS_CANCLIPSTRETCHED |
4720 WINEDDCAPS_COLORKEY |
4721 WINEDDCAPS_COLORKEYHWASSIST |
4722 WINEDDCAPS_ALIGNBOUNDARYSRC;
4724 /* Fill the ddraw caps structure */
4725 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4726 WINEDDCAPS_PALETTE |
4727 blit_caps;
4728 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4729 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4730 WINEDDCAPS2_PRIMARYGAMMA |
4731 WINEDDCAPS2_WIDESURFACES |
4732 WINEDDCAPS2_CANRENDERWINDOWED;
4733 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4734 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4735 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4736 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4737 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4738 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4739 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4740 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4741 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4743 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4744 WINEDDSCAPS_BACKBUFFER |
4745 WINEDDSCAPS_FLIP |
4746 WINEDDSCAPS_FRONTBUFFER |
4747 WINEDDSCAPS_OFFSCREENPLAIN |
4748 WINEDDSCAPS_PALETTE |
4749 WINEDDSCAPS_PRIMARYSURFACE |
4750 WINEDDSCAPS_SYSTEMMEMORY |
4751 WINEDDSCAPS_VIDEOMEMORY |
4752 WINEDDSCAPS_VISIBLE;
4753 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4755 /* Set D3D caps if OpenGL is available. */
4756 if (adapter->opengl)
4758 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4759 WINEDDSCAPS_MIPMAP |
4760 WINEDDSCAPS_TEXTURE |
4761 WINEDDSCAPS_ZBUFFER;
4762 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4765 return WINED3D_OK;
4768 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT adapter_idx,
4769 WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, IUnknown *parent,
4770 IWineD3DDeviceParent *device_parent, IWineD3DDevice **device)
4772 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4773 IWineD3DDeviceImpl *object;
4774 HRESULT hr;
4776 TRACE("iface %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x.\n"
4777 "parent %p, device_parent %p, device %p.\n",
4778 iface, adapter_idx, device_type, focus_window, flags,
4779 parent, device_parent, device);
4781 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4782 * number and create a device without a 3D adapter for 2D only operation. */
4783 if (IWineD3D_GetAdapterCount(iface) && adapter_idx >= IWineD3D_GetAdapterCount(iface))
4785 return WINED3DERR_INVALIDCALL;
4788 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4789 if (!object)
4791 ERR("Failed to allocate device memory.\n");
4792 return E_OUTOFMEMORY;
4795 hr = device_init(object, This, adapter_idx, device_type, focus_window, flags, parent, device_parent);
4796 if (FAILED(hr))
4798 WARN("Failed to initialize device, hr %#x.\n", hr);
4799 HeapFree(GetProcessHeap(), 0, object);
4800 return hr;
4803 TRACE("Created device %p.\n", object);
4804 *device = (IWineD3DDevice *)object;
4806 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *device);
4808 return WINED3D_OK;
4811 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4812 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4813 IUnknown_AddRef(This->parent);
4814 *pParent = This->parent;
4815 return WINED3D_OK;
4818 static void WINE_GLAPI invalid_func(const void *data)
4820 ERR("Invalid vertex attribute function called\n");
4821 DebugBreak();
4824 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4826 ERR("Invalid texcoord function called\n");
4827 DebugBreak();
4830 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4831 * the extension detection and are used in drawStridedSlow
4833 static void WINE_GLAPI position_d3dcolor(const void *data)
4835 DWORD pos = *((const DWORD *)data);
4837 FIXME("Add a test for fixed function position from d3dcolor type\n");
4838 glVertex4s(D3DCOLOR_B_R(pos),
4839 D3DCOLOR_B_G(pos),
4840 D3DCOLOR_B_B(pos),
4841 D3DCOLOR_B_A(pos));
4844 static void WINE_GLAPI position_float4(const void *data)
4846 const GLfloat *pos = data;
4848 if (pos[3] != 0.0f && pos[3] != 1.0f)
4850 float w = 1.0f / pos[3];
4852 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4854 else
4856 glVertex3fv(pos);
4860 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4862 DWORD diffuseColor = *((const DWORD *)data);
4864 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4865 D3DCOLOR_B_G(diffuseColor),
4866 D3DCOLOR_B_B(diffuseColor),
4867 D3DCOLOR_B_A(diffuseColor));
4870 static void WINE_GLAPI specular_d3dcolor(const void *data)
4872 DWORD specularColor = *((const DWORD *)data);
4873 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4874 D3DCOLOR_B_G(specularColor),
4875 D3DCOLOR_B_B(specularColor)};
4877 specular_func_3ubv(d);
4880 static void WINE_GLAPI warn_no_specular_func(const void *data)
4882 WARN("GL_EXT_secondary_color not supported\n");
4885 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4887 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4888 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4889 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4890 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4891 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4892 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4893 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4894 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4895 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4896 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4897 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4898 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4899 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4900 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4901 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4902 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4903 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4905 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4906 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4907 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4908 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4909 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4910 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4911 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4912 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4913 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4914 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4915 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4916 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4917 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4918 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4919 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4920 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4921 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4923 /* No 4 component entry points here */
4924 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4925 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4926 if (gl_info->supported[EXT_SECONDARY_COLOR])
4928 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4930 else
4932 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4934 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4935 if (gl_info->supported[EXT_SECONDARY_COLOR])
4937 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4938 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4940 else
4942 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4944 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4945 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4946 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4947 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4948 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4949 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4950 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4951 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4952 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4953 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4954 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4955 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4957 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4958 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4960 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4961 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4962 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4963 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4964 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4965 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4966 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4967 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4968 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4969 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4970 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4971 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4972 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4973 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4974 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4975 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4976 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4978 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4979 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4980 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4981 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4982 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4983 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4984 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4985 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4986 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4987 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4988 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4989 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4990 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4991 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4992 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4993 if (gl_info->supported[NV_HALF_FLOAT])
4995 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4996 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4997 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4998 } else {
4999 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
5000 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
5004 BOOL InitAdapters(IWineD3DImpl *This)
5006 static HMODULE mod_gl;
5007 BOOL ret;
5008 int ps_selected_mode, vs_selected_mode;
5010 /* No need to hold any lock. The calling library makes sure only one thread calls
5011 * wined3d simultaneously
5014 TRACE("Initializing adapters\n");
5016 if(!mod_gl) {
5017 #ifdef USE_WIN32_OPENGL
5018 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
5019 mod_gl = LoadLibraryA("opengl32.dll");
5020 if(!mod_gl) {
5021 ERR("Can't load opengl32.dll!\n");
5022 goto nogl_adapter;
5024 #else
5025 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
5026 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
5027 mod_gl = GetModuleHandleA("gdi32.dll");
5028 #endif
5031 /* Load WGL core functions from opengl32.dll */
5032 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
5033 WGL_FUNCS_GEN;
5034 #undef USE_WGL_FUNC
5036 if(!pwglGetProcAddress) {
5037 ERR("Unable to load wglGetProcAddress!\n");
5038 goto nogl_adapter;
5041 /* Dynamically load all GL core functions */
5042 GL_FUNCS_GEN;
5043 #undef USE_GL_FUNC
5045 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
5046 * otherwise because we have to use winex11.drv's override
5048 #ifdef USE_WIN32_OPENGL
5049 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
5050 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
5051 #else
5052 wglFinish = (void*)pwglGetProcAddress("wglFinish");
5053 wglFlush = (void*)pwglGetProcAddress("wglFlush");
5054 #endif
5056 glEnableWINE = glEnable;
5057 glDisableWINE = glDisable;
5059 /* For now only one default adapter */
5061 struct wined3d_adapter *adapter = &This->adapters[0];
5062 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
5063 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
5064 int iPixelFormat;
5065 int res;
5066 int i;
5067 WineD3D_PixelFormat *cfgs;
5068 DISPLAY_DEVICEW DisplayDevice;
5069 HDC hdc;
5071 TRACE("Initializing default adapter\n");
5072 adapter->ordinal = 0;
5073 adapter->monitorPoint.x = -1;
5074 adapter->monitorPoint.y = -1;
5076 if (!AllocateLocallyUniqueId(&adapter->luid))
5078 DWORD err = GetLastError();
5079 ERR("Failed to set adapter LUID (%#x).\n", err);
5080 goto nogl_adapter;
5082 TRACE("Allocated LUID %08x:%08x for adapter.\n",
5083 adapter->luid.HighPart, adapter->luid.LowPart);
5085 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
5087 ERR("Failed to get a gl context for default adapter\n");
5088 goto nogl_adapter;
5091 ret = IWineD3DImpl_FillGLCaps(adapter);
5092 if(!ret) {
5093 ERR("Failed to initialize gl caps for default adapter\n");
5094 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5095 goto nogl_adapter;
5097 ret = initPixelFormats(&adapter->gl_info, adapter->driver_info.vendor);
5098 if(!ret) {
5099 ERR("Failed to init gl formats\n");
5100 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5101 goto nogl_adapter;
5104 hdc = fake_gl_ctx.dc;
5106 /* Use the VideoRamSize registry setting when set */
5107 if(wined3d_settings.emulated_textureram)
5108 adapter->TextureRam = wined3d_settings.emulated_textureram;
5109 else
5110 adapter->TextureRam = adapter->gl_info.vidmem;
5111 adapter->UsedTextureRam = 0;
5112 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
5114 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
5115 DisplayDevice.cb = sizeof(DisplayDevice);
5116 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
5117 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
5118 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
5120 if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
5122 int attribute;
5123 int attribs[11];
5124 int values[11];
5125 int nAttribs = 0;
5127 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
5128 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
5130 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
5131 cfgs = adapter->cfgs;
5132 attribs[nAttribs++] = WGL_RED_BITS_ARB;
5133 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
5134 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
5135 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
5136 attribs[nAttribs++] = WGL_COLOR_BITS_ARB;
5137 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
5138 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
5139 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
5140 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
5141 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
5142 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
5144 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
5146 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
5148 if(!res)
5149 continue;
5151 /* Cache the pixel format */
5152 cfgs->iPixelFormat = iPixelFormat;
5153 cfgs->redSize = values[0];
5154 cfgs->greenSize = values[1];
5155 cfgs->blueSize = values[2];
5156 cfgs->alphaSize = values[3];
5157 cfgs->colorSize = values[4];
5158 cfgs->depthSize = values[5];
5159 cfgs->stencilSize = values[6];
5160 cfgs->windowDrawable = values[7];
5161 cfgs->iPixelType = values[8];
5162 cfgs->doubleBuffer = values[9];
5163 cfgs->auxBuffers = values[10];
5165 cfgs->numSamples = 0;
5166 /* Check multisample support */
5167 if (gl_info->supported[ARB_MULTISAMPLE])
5169 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
5170 int value[2];
5171 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
5172 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
5173 * value[1] = number of multi sample buffers*/
5174 if(value[0])
5175 cfgs->numSamples = value[1];
5179 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
5180 "depth=%d, stencil=%d, samples=%d, windowDrawable=%d\n",
5181 cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer,
5182 cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize,
5183 cfgs->depthSize, cfgs->stencilSize, cfgs->numSamples, cfgs->windowDrawable);
5184 cfgs++;
5187 else
5189 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
5190 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
5191 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
5193 cfgs = adapter->cfgs;
5194 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
5196 PIXELFORMATDESCRIPTOR ppfd;
5198 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
5199 if(!res)
5200 continue;
5202 /* We only want HW acceleration using an OpenGL ICD driver.
5203 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
5204 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
5206 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
5208 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
5209 continue;
5212 cfgs->iPixelFormat = iPixelFormat;
5213 cfgs->redSize = ppfd.cRedBits;
5214 cfgs->greenSize = ppfd.cGreenBits;
5215 cfgs->blueSize = ppfd.cBlueBits;
5216 cfgs->alphaSize = ppfd.cAlphaBits;
5217 cfgs->colorSize = ppfd.cColorBits;
5218 cfgs->depthSize = ppfd.cDepthBits;
5219 cfgs->stencilSize = ppfd.cStencilBits;
5220 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
5221 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
5222 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
5223 cfgs->auxBuffers = ppfd.cAuxBuffers;
5224 cfgs->numSamples = 0;
5226 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
5227 "depth=%d, stencil=%d, windowDrawable=%d\n",
5228 cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer,
5229 cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize,
5230 cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable);
5231 cfgs++;
5232 adapter->nCfgs++;
5235 /* 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 */
5236 if(!adapter->nCfgs)
5238 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
5240 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5241 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
5242 goto nogl_adapter;
5246 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
5247 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
5248 * but just fake it using D24(X8?) which is fine. D3D also allows that.
5249 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
5250 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
5251 * driver is allowed to consume more bits EXCEPT for stencil bits.
5253 * Mark an adapter with this broken stencil behavior.
5255 adapter->brokenStencil = TRUE;
5256 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
5258 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
5259 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
5260 adapter->brokenStencil = FALSE;
5261 break;
5265 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5267 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
5268 fillGLAttribFuncs(&adapter->gl_info);
5269 adapter->opengl = TRUE;
5271 This->adapter_count = 1;
5272 TRACE("%u adapters successfully initialized\n", This->adapter_count);
5274 return TRUE;
5276 nogl_adapter:
5277 /* Initialize an adapter for ddraw-only memory counting */
5278 memset(This->adapters, 0, sizeof(This->adapters));
5279 This->adapters[0].ordinal = 0;
5280 This->adapters[0].opengl = FALSE;
5281 This->adapters[0].monitorPoint.x = -1;
5282 This->adapters[0].monitorPoint.y = -1;
5284 This->adapters[0].driver_info.name = "Display";
5285 This->adapters[0].driver_info.description = "WineD3D DirectDraw Emulation";
5286 if(wined3d_settings.emulated_textureram) {
5287 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
5288 } else {
5289 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
5292 initPixelFormatsNoGL(&This->adapters[0].gl_info);
5294 This->adapter_count = 1;
5295 return FALSE;
5298 /**********************************************************
5299 * IWineD3D VTbl follows
5300 **********************************************************/
5302 const IWineD3DVtbl IWineD3D_Vtbl =
5304 /* IUnknown */
5305 IWineD3DImpl_QueryInterface,
5306 IWineD3DImpl_AddRef,
5307 IWineD3DImpl_Release,
5308 /* IWineD3D */
5309 IWineD3DImpl_GetParent,
5310 IWineD3DImpl_GetAdapterCount,
5311 IWineD3DImpl_RegisterSoftwareDevice,
5312 IWineD3DImpl_GetAdapterMonitor,
5313 IWineD3DImpl_GetAdapterModeCount,
5314 IWineD3DImpl_EnumAdapterModes,
5315 IWineD3DImpl_GetAdapterDisplayMode,
5316 IWineD3DImpl_GetAdapterIdentifier,
5317 IWineD3DImpl_CheckDeviceMultiSampleType,
5318 IWineD3DImpl_CheckDepthStencilMatch,
5319 IWineD3DImpl_CheckDeviceType,
5320 IWineD3DImpl_CheckDeviceFormat,
5321 IWineD3DImpl_CheckDeviceFormatConversion,
5322 IWineD3DImpl_GetDeviceCaps,
5323 IWineD3DImpl_CreateDevice
5326 static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
5328 const struct wined3d_parent_ops wined3d_null_parent_ops =
5330 wined3d_null_wined3d_object_destroyed,