Release 1.1.37.
[wine/gsoc-2012-control.git] / dlls / wined3d / directx.c
blobb8684c27fce581ce5f182979b25b17742a4c990d
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)
34 /* The d3d device ID */
35 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
37 /* Extension detection */
38 static const struct {
39 const char *extension_string;
40 GL_SupportedExt extension;
41 DWORD version;
42 } EXTENSION_MAP[] = {
43 /* APPLE */
44 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
45 {"GL_APPLE_fence", APPLE_FENCE, 0 },
46 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
47 {"GL_APPLE_flush_buffer_range", APPLE_FLUSH_BUFFER_RANGE, 0 },
48 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
49 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
51 /* ARB */
52 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
53 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
54 {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP, 0 },
55 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
56 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
57 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
58 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
59 {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT, 0 },
60 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
61 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
62 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
63 {"GL_ARB_imaging", ARB_IMAGING, 0 },
64 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
65 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
66 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
67 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
68 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
69 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
70 {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX, 0 },
71 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
72 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
73 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
74 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
75 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
76 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
77 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
78 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
79 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
80 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
81 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
82 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
83 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
84 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
85 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
86 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
87 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
89 /* ATI */
90 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
91 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
92 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
93 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
94 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
96 /* EXT */
97 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
98 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
99 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
100 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
101 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
102 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
103 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
104 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
105 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
106 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
107 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
108 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
109 {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 },
110 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
111 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
112 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
113 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
114 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
115 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
116 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
117 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
118 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
119 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
120 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
121 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
122 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
123 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
124 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
125 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
127 /* NV */
128 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
129 {"GL_NV_fence", NV_FENCE, 0 },
130 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
131 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
132 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
133 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
134 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
135 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
136 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
137 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
138 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
139 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
140 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
141 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
142 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
143 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
144 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
145 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
146 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
147 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
149 /* SGI */
150 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
153 /**********************************************************
154 * Utility functions follow
155 **********************************************************/
157 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
159 const struct min_lookup minMipLookup[] =
161 /* NONE POINT LINEAR */
162 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
163 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
164 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
167 const struct min_lookup minMipLookup_noFilter[] =
169 /* NONE POINT LINEAR */
170 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
171 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
172 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
175 const struct min_lookup minMipLookup_noMip[] =
177 /* NONE POINT LINEAR */
178 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
179 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
180 {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */
183 const GLenum magLookup[] =
185 /* NONE POINT LINEAR */
186 GL_NEAREST, GL_NEAREST, GL_LINEAR,
189 const GLenum magLookup_noFilter[] =
191 /* NONE POINT LINEAR */
192 GL_NEAREST, GL_NEAREST, GL_NEAREST,
195 /* drawStridedSlow attributes */
196 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
197 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
198 glAttribFunc specular_func_3ubv;
199 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
200 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
201 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
204 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
205 * i.e., there is no GL Context - Get a default rendering context to enable the
206 * function query some info from GL.
209 struct wined3d_fake_gl_ctx
211 HDC dc;
212 HWND wnd;
213 HGLRC gl_ctx;
214 HDC restore_dc;
215 HGLRC restore_gl_ctx;
218 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
220 TRACE_(d3d_caps)("Destroying fake GL context.\n");
222 if (!pwglMakeCurrent(NULL, NULL))
224 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
227 if (!pwglDeleteContext(ctx->gl_ctx))
229 DWORD err = GetLastError();
230 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
233 ReleaseDC(ctx->wnd, ctx->dc);
234 DestroyWindow(ctx->wnd);
236 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
238 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
242 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
244 PIXELFORMATDESCRIPTOR pfd;
245 int iPixelFormat;
247 TRACE("getting context...\n");
249 ctx->restore_dc = pwglGetCurrentDC();
250 ctx->restore_gl_ctx = pwglGetCurrentContext();
252 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
253 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
254 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
255 if (!ctx->wnd)
257 ERR_(d3d_caps)("Failed to create a window.\n");
258 goto fail;
261 ctx->dc = GetDC(ctx->wnd);
262 if (!ctx->dc)
264 ERR_(d3d_caps)("Failed to get a DC.\n");
265 goto fail;
268 /* PixelFormat selection */
269 ZeroMemory(&pfd, sizeof(pfd));
270 pfd.nSize = sizeof(pfd);
271 pfd.nVersion = 1;
272 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
273 pfd.iPixelType = PFD_TYPE_RGBA;
274 pfd.cColorBits = 32;
275 pfd.iLayerType = PFD_MAIN_PLANE;
277 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
278 if (!iPixelFormat)
280 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
281 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
282 goto fail;
284 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
285 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
287 /* Create a GL context. */
288 ctx->gl_ctx = pwglCreateContext(ctx->dc);
289 if (!ctx->gl_ctx)
291 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
292 goto fail;
295 /* Make it the current GL context. */
296 if (!context_set_current(NULL))
298 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
301 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
303 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
304 goto fail;
307 return TRUE;
309 fail:
310 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
311 ctx->gl_ctx = NULL;
312 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
313 ctx->dc = NULL;
314 if (ctx->wnd) DestroyWindow(ctx->wnd);
315 ctx->wnd = NULL;
316 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
318 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
321 return FALSE;
324 /* Adjust the amount of used texture memory */
325 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram)
327 struct wined3d_adapter *adapter = D3DDevice->adapter;
329 adapter->UsedTextureRam += glram;
330 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
331 return adapter->UsedTextureRam;
334 static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
336 HeapFree(GetProcessHeap(), 0, adapter->gl_info.gl_formats);
337 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
340 /**********************************************************
341 * IUnknown parts follows
342 **********************************************************/
344 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
348 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
349 if (IsEqualGUID(riid, &IID_IUnknown)
350 || IsEqualGUID(riid, &IID_IWineD3DBase)
351 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
352 IUnknown_AddRef(iface);
353 *ppobj = This;
354 return S_OK;
356 *ppobj = NULL;
357 return E_NOINTERFACE;
360 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
361 IWineD3DImpl *This = (IWineD3DImpl *)iface;
362 ULONG refCount = InterlockedIncrement(&This->ref);
364 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
365 return refCount;
368 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
369 IWineD3DImpl *This = (IWineD3DImpl *)iface;
370 ULONG ref;
371 TRACE("(%p) : Releasing from %d\n", This, This->ref);
372 ref = InterlockedDecrement(&This->ref);
373 if (ref == 0) {
374 unsigned int i;
376 for (i = 0; i < This->adapter_count; ++i)
378 wined3d_adapter_cleanup(&This->adapters[i]);
380 HeapFree(GetProcessHeap(), 0, This);
383 return ref;
386 /**********************************************************
387 * IWineD3D parts follows
388 **********************************************************/
390 /* GL locking is done by the caller */
391 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
393 GLuint prog;
394 BOOL ret = FALSE;
395 const char *testcode =
396 "!!ARBvp1.0\n"
397 "PARAM C[66] = { program.env[0..65] };\n"
398 "ADDRESS A0;"
399 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
400 "ARL A0.x, zero.x;\n"
401 "MOV result.position, C[A0.x + 65];\n"
402 "END\n";
404 while(glGetError());
405 GL_EXTCALL(glGenProgramsARB(1, &prog));
406 if(!prog) {
407 ERR("Failed to create an ARB offset limit test program\n");
409 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
410 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
411 strlen(testcode), testcode));
412 if(glGetError() != 0) {
413 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
414 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
415 ret = TRUE;
416 } else TRACE("OpenGL implementation allows offsets > 63\n");
418 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
419 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
420 checkGLcall("ARB vp offset limit test cleanup");
422 return ret;
425 static DWORD ver_for_ext(GL_SupportedExt ext)
427 unsigned int i;
428 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
429 if(EXTENSION_MAP[i].extension == ext) {
430 return EXTENSION_MAP[i].version;
433 return 0;
436 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
437 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
439 if (vendor != VENDOR_ATI) return FALSE;
440 if (device == CARD_ATI_RADEON_9500) return TRUE;
441 if (device == CARD_ATI_RADEON_X700) return TRUE;
442 if (device == CARD_ATI_RADEON_X1600) return TRUE;
443 return FALSE;
446 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
447 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
449 if (vendor == VENDOR_NVIDIA)
451 if (device == CARD_NVIDIA_GEFORCEFX_5800 || device == CARD_NVIDIA_GEFORCEFX_5600)
453 return TRUE;
456 return FALSE;
459 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
460 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
462 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
463 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
464 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
466 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
467 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
468 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
469 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
470 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
471 * the chance that other implementations support them is rather small since Win32 QuickTime uses
472 * DirectDraw, not OpenGL. */
473 if (gl_info->supported[APPLE_FENCE]
474 && gl_info->supported[APPLE_CLIENT_STORAGE]
475 && gl_info->supported[APPLE_FLUSH_RENDER]
476 && gl_info->supported[APPLE_YCBCR_422])
478 return TRUE;
480 else
482 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_pci_vendor vendor, enum wined3d_pci_device device)
558 return vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer, vendor, device);
561 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
562 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
564 if (!match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
565 if (vendor != 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_pci_vendor vendor, enum wined3d_pci_device device)
573 if (vendor != VENDOR_ATI) return FALSE;
574 if (match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
575 if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */
576 return TRUE;
579 static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
580 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
582 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
583 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
584 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
585 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
586 * hardcoded
588 * dx10 cards usually have 64 varyings */
589 return gl_info->limits.glsl_varyings > 44;
592 /* A GL context is provided by the caller */
593 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
594 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
596 GLenum error;
597 DWORD data[16];
599 if (!gl_info->supported[EXT_SECONDARY_COLOR]) return FALSE;
601 ENTER_GL();
602 while(glGetError());
603 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
604 error = glGetError();
605 LEAVE_GL();
607 if(error == GL_NO_ERROR)
609 TRACE("GL Implementation accepts 4 component specular color pointers\n");
610 return TRUE;
612 else
614 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
615 debug_glerror(error));
616 return FALSE;
620 static BOOL match_apple_nvts(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
621 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
623 if (!match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
624 return gl_info->supported[NV_TEXTURE_SHADER];
627 /* A GL context is provided by the caller */
628 static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
629 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
631 GLuint prog;
632 BOOL ret = FALSE;
633 GLint pos;
634 const char *testcode =
635 "!!ARBvp1.0\n"
636 "OPTION NV_vertex_program2;\n"
637 "MOV result.clip[0], 0.0;\n"
638 "MOV result.position, 0.0;\n"
639 "END\n";
641 if (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]) return FALSE;
643 ENTER_GL();
644 while(glGetError());
646 GL_EXTCALL(glGenProgramsARB(1, &prog));
647 if(!prog)
649 ERR("Failed to create the NVvp clip test program\n");
650 LEAVE_GL();
651 return FALSE;
653 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
654 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
655 strlen(testcode), testcode));
656 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
657 if(pos != -1)
659 WARN("GL_NV_vertex_program2_option result.clip[] test failed\n");
660 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
661 ret = TRUE;
662 while(glGetError());
664 else TRACE("GL_NV_vertex_program2_option result.clip[] test passed\n");
666 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
667 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
668 checkGLcall("GL_NV_vertex_program2_option result.clip[] test cleanup");
670 LEAVE_GL();
671 return ret;
674 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
676 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->limits.arb_vs_native_constants);
677 gl_info->limits.glsl_vs_float_constants = gl_info->limits.arb_vs_native_constants;
678 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->limits.arb_ps_native_constants);
679 gl_info->limits.glsl_ps_float_constants = gl_info->limits.arb_ps_native_constants;
682 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
684 quirk_arb_constants(gl_info);
685 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
686 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
687 * allow 48 different offsets or other helper immediate values. */
688 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
689 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
692 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
693 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
694 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
695 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
696 * most games, but avoids the crash
698 * A more sophisticated way would be to find all units that need texture coordinates and enable
699 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
700 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
702 * Note that disabling the extension entirely does not gain predictability because there is no point
703 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
704 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
706 if (gl_info->supported[ARB_POINT_SPRITE])
708 TRACE("Limiting point sprites to one texture unit.\n");
709 gl_info->limits.point_sprite_units = 1;
713 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
715 quirk_arb_constants(gl_info);
717 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
718 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
719 * If real NP2 textures are used, the driver falls back to software. We could just remove the
720 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
721 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
722 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
723 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
725 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
726 * has this extension promoted to core. The extension loading code sets this extension supported
727 * due to that, so this code works on fglrx as well. */
728 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
730 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
731 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
732 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
735 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
736 * it is generally more efficient. Reserve just 8 constants. */
737 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
738 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
741 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
743 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
744 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
745 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
746 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
747 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
748 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
750 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
751 * triggering the software fallback. There is not much we can do here apart from disabling the
752 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
753 * in IWineD3DImpl_FillGLCaps).
754 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
755 * post-processing effects in the game "Max Payne 2").
756 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
757 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
758 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
759 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
762 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
764 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
765 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
766 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
767 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
768 * according to the spec.
770 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
771 * makes the shader slower and eats instruction slots which should be available to the d3d app.
773 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
774 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
775 * this workaround is activated on cards that do not need it, it won't break things, just affect
776 * performance negatively. */
777 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
778 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
781 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
783 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
786 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
788 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
791 static void quirk_apple_nvts(struct wined3d_gl_info *gl_info)
793 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
794 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
795 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
798 static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info)
800 gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN;
803 struct driver_quirk
805 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
806 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device);
807 void (*apply)(struct wined3d_gl_info *gl_info);
808 const char *description;
811 static const struct driver_quirk quirk_table[] =
814 match_ati_r300_to_500,
815 quirk_ati_dx9,
816 "ATI GLSL constant and normalized texrect quirk"
818 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
819 * used it falls back to software. While the compiler can detect if the shader uses all declared
820 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
821 * using relative addressing falls back to software.
823 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
825 match_apple,
826 quirk_apple_glsl_constants,
827 "Apple GLSL uniform override"
830 match_geforce5,
831 quirk_no_np2,
832 "Geforce 5 NP2 disable"
835 match_apple_intel,
836 quirk_texcoord_w,
837 "Init texcoord .w for Apple Intel GPU driver"
840 match_apple_nonr500ati,
841 quirk_texcoord_w,
842 "Init texcoord .w for Apple ATI >= r600 GPU driver"
845 match_fglrx,
846 quirk_one_point_sprite,
847 "Fglrx point sprite crash workaround"
850 match_dx10_capable,
851 quirk_clip_varying,
852 "Reserved varying for gl_ClipPos"
855 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
856 * GL implementations accept it. The Mac GL is the only implementation known to
857 * reject it.
859 * If we can pass 4 component specular colors, do it, because (a) we don't have
860 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
861 * passes specular alpha to the pixel shader if any is used. Otherwise the
862 * specular alpha is used to pass the fog coordinate, which we pass to opengl
863 * via GL_EXT_fog_coord.
865 match_allows_spec_alpha,
866 quirk_allows_specular_alpha,
867 "Allow specular alpha quirk"
870 /* The pixel formats provided by GL_NV_texture_shader are broken on OSX
871 * (rdar://5682521).
873 match_apple_nvts,
874 quirk_apple_nvts,
875 "Apple NV_texture_shader disable"
878 match_broken_nv_clip,
879 quirk_disable_nvvp_clip,
880 "Apple NV_vertex_program clip bug quirk"
884 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
885 * reporting a driver version is moot because we are not the Windows driver, and we have different
886 * bugs, features, etc.
888 * The driver version has the form "x.y.z.w".
890 * "x" is the Windows version the driver is meant for:
891 * 4 -> 95/98/NT4
892 * 5 -> 2000
893 * 6 -> 2000/XP
894 * 7 -> Vista
895 * 8 -> Win 7
897 * "y" is the Direct3D level the driver supports:
898 * 11 -> d3d6
899 * 12 -> d3d7
900 * 13 -> d3d8
901 * 14 -> d3d9
902 * 15 -> d3d10
904 * "z" is unknown, possibly vendor specific.
906 * "w" is the vendor specific driver version.
908 struct driver_version_information
910 WORD vendor; /* reported PCI card vendor ID */
911 WORD card; /* reported PCI card device ID */
912 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
913 WORD d3d_level; /* driver hiword to report */
914 WORD lopart_hi, lopart_lo; /* driver loword to report */
917 static const struct driver_version_information driver_version_table[] =
919 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
920 * 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
921 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
922 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
924 * All version numbers used below are from the Linux nvidia drivers. */
925 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 1, 8, 6 },
926 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 1, 8, 6 },
927 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 1, 8, 6 },
928 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 6, 4, 3 },
929 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 1, 8, 6 },
930 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 6, 10, 9371 },
931 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 6, 10, 9371 },
932 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 6, 10, 9371 },
933 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 15, 11, 7516 },
934 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 15, 11, 7516 },
935 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 15, 11, 7516 },
936 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 15, 11, 8618 },
937 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 15, 11, 8618 },
938 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 15, 11, 8618 },
939 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 15, 11, 8585 },
940 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 15, 11, 8585 },
941 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 15, 11, 8618 },
942 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 15, 11, 8618 },
943 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 15, 11, 8618 },
944 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 15, 11, 8618 },
945 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 15, 11, 8585 },
946 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 15, 11, 8618 },
947 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 15, 11, 8618 },
948 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 15, 11, 8618 },
949 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 15, 11, 8618 },
950 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 15, 11, 8618 },
951 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 15, 11, 8618 },
952 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 15, 11, 8618 },
953 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 15, 11, 8618 },
954 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 15, 11, 8618 },
955 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GT240, "NVIDIA GeForce GT 240", 15, 11, 8618 },
957 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
958 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 14, 10, 6764 },
959 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 14, 10, 6764 },
960 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 14, 10, 6764 },
961 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 14, 10, 6764 },
962 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 14, 10, 6764 },
963 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 14, 10, 6764 },
964 {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 14, 10, 6764 },
965 {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 14, 10, 6764 },
966 {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 14, 10, 6764 },
967 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 14, 10, 6764 },
968 {VENDOR_ATI, CARD_ATI_RADEON_HD5700, "ATI Radeon HD 5700 Series", 14, 10, 8681 },
969 {VENDOR_ATI, CARD_ATI_RADEON_HD5800, "ATI Radeon HD 5800 Series", 14, 10, 8681 },
971 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
974 static void init_driver_info(struct wined3d_driver_info *driver_info,
975 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
977 OSVERSIONINFOW os_version;
978 WORD driver_os_version;
979 unsigned int i;
981 if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
983 TRACE_(d3d_caps)("Overriding PCI vendor ID with: %04x\n", wined3d_settings.pci_vendor_id);
984 vendor = wined3d_settings.pci_vendor_id;
986 driver_info->vendor = vendor;
988 if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
990 TRACE_(d3d_caps)("Overriding PCI device ID with: %04x\n", wined3d_settings.pci_device_id);
991 device = wined3d_settings.pci_device_id;
993 driver_info->device = device;
995 switch (vendor)
997 case VENDOR_ATI:
998 driver_info->name = "ati2dvag.dll";
999 break;
1001 case VENDOR_NVIDIA:
1002 driver_info->name = "nv4_disp.dll";
1003 break;
1005 default:
1006 FIXME_(d3d_caps)("Unhandled vendor %04x.\n", vendor);
1007 driver_info->name = "Display";
1008 break;
1011 memset(&os_version, 0, sizeof(os_version));
1012 os_version.dwOSVersionInfoSize = sizeof(os_version);
1013 if (!GetVersionExW(&os_version))
1015 ERR("Failed to get OS version, reporting 2000/XP.\n");
1016 driver_os_version = 6;
1018 else
1020 TRACE("OS version %u.%u.\n", os_version.dwMajorVersion, os_version.dwMinorVersion);
1021 switch (os_version.dwMajorVersion)
1023 case 4:
1024 driver_os_version = 4;
1025 break;
1027 case 5:
1028 driver_os_version = 6;
1029 break;
1031 case 6:
1032 if (os_version.dwMinorVersion == 0)
1034 driver_os_version = 7;
1036 else
1038 if (os_version.dwMinorVersion > 1)
1040 FIXME("Unhandled OS version %u.%u, reporting Win 7.\n",
1041 os_version.dwMajorVersion, os_version.dwMinorVersion);
1043 driver_os_version = 8;
1045 break;
1047 default:
1048 FIXME("Unhandled OS version %u.%u, reporting 2000/XP.\n",
1049 os_version.dwMajorVersion, os_version.dwMinorVersion);
1050 driver_os_version = 6;
1051 break;
1055 driver_info->description = "Direct3D HAL";
1056 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
1057 driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
1059 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
1061 if (vendor == driver_version_table[i].vendor && device == driver_version_table[i].card)
1063 TRACE_(d3d_caps)("Found card %04x:%04x in driver DB.\n", vendor, device);
1065 driver_info->description = driver_version_table[i].description;
1066 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, driver_version_table[i].d3d_level);
1067 driver_info->version_low = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
1068 driver_version_table[i].lopart_lo);
1069 break;
1073 TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08x-0x%08x.\n",
1074 driver_info->version_high, driver_info->version_low);
1077 /* Context activation is done by the caller. */
1078 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer,
1079 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
1081 unsigned int i;
1083 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
1085 if (!quirk_table[i].match(gl_info, gl_renderer, vendor, device)) continue;
1086 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
1087 quirk_table[i].apply(gl_info);
1090 /* Find out if PBOs work as they are supposed to. */
1091 test_pbo_functionality(gl_info);
1094 static DWORD wined3d_parse_gl_version(const char *gl_version)
1096 const char *ptr = gl_version;
1097 int major, minor;
1099 major = atoi(ptr);
1100 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
1102 while (isdigit(*ptr)) ++ptr;
1103 if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version));
1105 minor = atoi(ptr);
1107 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
1109 return MAKEDWORD_VERSION(major, minor);
1112 static enum wined3d_pci_vendor wined3d_guess_vendor(const char *gl_vendor, const char *gl_renderer)
1114 if (strstr(gl_vendor, "NVIDIA"))
1115 return VENDOR_NVIDIA;
1117 if (strstr(gl_vendor, "ATI"))
1118 return VENDOR_ATI;
1120 if (strstr(gl_vendor, "Intel(R)")
1121 || strstr(gl_renderer, "Intel(R)")
1122 || strstr(gl_vendor, "Intel Inc."))
1123 return VENDOR_INTEL;
1125 if (strstr(gl_vendor, "Mesa")
1126 || strstr(gl_vendor, "DRI R300 Project")
1127 || strstr(gl_vendor, "Tungsten Graphics, Inc")
1128 || strstr(gl_vendor, "VMware, Inc."))
1129 return VENDOR_MESA;
1131 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning VENDOR_WINE.\n", debugstr_a(gl_vendor));
1133 return VENDOR_WINE;
1136 static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1137 enum wined3d_pci_vendor *vendor, unsigned int *vidmem)
1139 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of
1140 * different GPUs with roughly the same features. In most cases GPUs from a
1141 * certain family differ in clockspeeds, the amount of video memory and the
1142 * number of shader pipelines.
1144 * A Direct3D device object contains the PCI id (vendor + device) of the
1145 * videocard which is used for rendering. Various applications use this
1146 * information to get a rough estimation of the features of the card and
1147 * some might use it for enabling 3d effects only on certain types of
1148 * videocards. In some cases games might even use it to work around bugs
1149 * which happen on certain videocards/driver combinations. The problem is
1150 * that OpenGL only exposes a rendering string containing the name of the
1151 * videocard and not the PCI id.
1153 * Various games depend on the PCI id, so somehow we need to provide one.
1154 * A simple option is to parse the renderer string and translate this to
1155 * the right PCI id. This is a lot of work because there are more than 200
1156 * GPUs just for Nvidia. Various cards share the same renderer string, so
1157 * the amount of code might be 'small' but there are quite a number of
1158 * exceptions which would make this a pain to maintain. Another way would
1159 * be to query the PCI id from the operating system (assuming this is the
1160 * videocard which is used for rendering which is not always the case).
1161 * This would work but it is not very portable. Second it would not work
1162 * well in, let's say, a remote X situation in which the amount of 3d
1163 * features which can be used is limited.
1165 * As said most games only use the PCI id to get an indication of the
1166 * capabilities of the card. It doesn't really matter if the given id is
1167 * the correct one if we return the id of a card with similar 3d features.
1169 * The code below checks the OpenGL capabilities of a videocard and matches
1170 * that to a certain level of Direct3D functionality. Once a card passes
1171 * the Direct3D9 check, we know that the card (in case of Nvidia) is at
1172 * least a GeforceFX. To give a better estimate we do a basic check on the
1173 * renderer string but if that won't pass we return a default card. This
1174 * way is better than maintaining a full card database as even without a
1175 * full database we can return a card with similar features. Second the
1176 * size of the database can be made quite small because when you know what
1177 * type of 3d functionality a card has, you know to which GPU family the
1178 * GPU must belong. Because of this you only have to check a small part of
1179 * the renderer string to distinguishes between different models from that
1180 * family.
1182 * The code also selects a default amount of video memory which we will
1183 * use for an estimation of the amount of free texture memory. In case of
1184 * real D3D the amount of texture memory includes video memory and system
1185 * memory (to be specific AGP memory or in case of PCIE TurboCache /
1186 * HyperMemory). We don't know how much system memory can be addressed by
1187 * the system but we can make a reasonable estimation about the amount of
1188 * video memory. If the value is slightly wrong it doesn't matter as we
1189 * didn't include AGP-like memory which makes the amount of addressable
1190 * memory higher and second OpenGL isn't that critical it moves to system
1191 * memory behind our backs if really needed. Note that the amount of video
1192 * memory can be overruled using a registry setting. */
1194 switch (*vendor)
1196 case VENDOR_NVIDIA:
1197 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1198 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1200 if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3])
1202 /* Geforce 200 - highend */
1203 if (strstr(gl_renderer, "GTX 280")
1204 || strstr(gl_renderer, "GTX 285")
1205 || strstr(gl_renderer, "GTX 295"))
1207 *vidmem = 1024;
1208 return CARD_NVIDIA_GEFORCE_GTX280;
1211 /* Geforce 200 - midend high */
1212 if (strstr(gl_renderer, "GTX 275"))
1214 *vidmem = 896;
1215 return CARD_NVIDIA_GEFORCE_GTX275;
1218 /* Geforce 200 - midend */
1219 if (strstr(gl_renderer, "GTX 260"))
1221 *vidmem = 1024;
1222 return CARD_NVIDIA_GEFORCE_GTX260;
1224 /* Geforce 200 - midend */
1225 if (strstr(gl_renderer, "GT 240"))
1227 *vidmem = 512;
1228 return CARD_NVIDIA_GEFORCE_GT240;
1231 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1232 if (strstr(gl_renderer, "9800")
1233 || strstr(gl_renderer, "GTS 150")
1234 || strstr(gl_renderer, "GTS 250"))
1236 *vidmem = 512;
1237 return CARD_NVIDIA_GEFORCE_9800GT;
1240 /* Geforce9 - midend */
1241 if (strstr(gl_renderer, "9600"))
1243 *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1244 return CARD_NVIDIA_GEFORCE_9600GT;
1247 /* Geforce9 - midend low / Geforce 200 - low */
1248 if (strstr(gl_renderer, "9500")
1249 || strstr(gl_renderer, "GT 120")
1250 || strstr(gl_renderer, "GT 130"))
1252 *vidmem = 256; /* The 9500GT has 256-1024MB */
1253 return CARD_NVIDIA_GEFORCE_9500GT;
1256 /* Geforce9 - lowend */
1257 if (strstr(gl_renderer, "9400"))
1259 *vidmem = 256; /* The 9400GT has 256-1024MB */
1260 return CARD_NVIDIA_GEFORCE_9400GT;
1263 /* Geforce9 - lowend low */
1264 if (strstr(gl_renderer, "9100")
1265 || strstr(gl_renderer, "9200")
1266 || strstr(gl_renderer, "9300")
1267 || strstr(gl_renderer, "G 100"))
1269 *vidmem = 256; /* The 9100-9300 cards have 256MB */
1270 return CARD_NVIDIA_GEFORCE_9200;
1273 /* Geforce8 - highend */
1274 if (strstr(gl_renderer, "8800"))
1276 *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1277 return CARD_NVIDIA_GEFORCE_8800GTS;
1280 /* Geforce8 - midend mobile */
1281 if (strstr(gl_renderer, "8600 M"))
1283 *vidmem = 512;
1284 return CARD_NVIDIA_GEFORCE_8600MGT;
1287 /* Geforce8 - midend */
1288 if (strstr(gl_renderer, "8600")
1289 || strstr(gl_renderer, "8700"))
1291 *vidmem = 256;
1292 return CARD_NVIDIA_GEFORCE_8600GT;
1295 /* Geforce8 - lowend */
1296 if (strstr(gl_renderer, "8100")
1297 || strstr(gl_renderer, "8200")
1298 || strstr(gl_renderer, "8300")
1299 || strstr(gl_renderer, "8400")
1300 || strstr(gl_renderer, "8500"))
1302 *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1303 return CARD_NVIDIA_GEFORCE_8300GS;
1306 /* Geforce7 - highend */
1307 if (strstr(gl_renderer, "7800")
1308 || strstr(gl_renderer, "7900")
1309 || strstr(gl_renderer, "7950")
1310 || strstr(gl_renderer, "Quadro FX 4")
1311 || strstr(gl_renderer, "Quadro FX 5"))
1313 *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1314 return CARD_NVIDIA_GEFORCE_7800GT;
1317 /* Geforce7 midend */
1318 if (strstr(gl_renderer, "7600")
1319 || strstr(gl_renderer, "7700"))
1321 *vidmem = 256; /* The 7600 uses 256-512MB */
1322 return CARD_NVIDIA_GEFORCE_7600;
1325 /* Geforce7 lower medium */
1326 if (strstr(gl_renderer, "7400"))
1328 *vidmem = 256; /* The 7400 uses 256-512MB */
1329 return CARD_NVIDIA_GEFORCE_7400;
1332 /* Geforce7 lowend */
1333 if (strstr(gl_renderer, "7300"))
1335 *vidmem = 256; /* Mac Pros with this card have 256 MB */
1336 return CARD_NVIDIA_GEFORCE_7300;
1339 /* Geforce6 highend */
1340 if (strstr(gl_renderer, "6800"))
1342 *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1343 return CARD_NVIDIA_GEFORCE_6800;
1346 /* Geforce6 - midend */
1347 if (strstr(gl_renderer, "6600")
1348 || strstr(gl_renderer, "6610")
1349 || strstr(gl_renderer, "6700"))
1351 *vidmem = 128; /* A 6600GT has 128-256MB */
1352 return CARD_NVIDIA_GEFORCE_6600GT;
1355 /* Geforce6/7 lowend */
1356 *vidmem = 64; /* */
1357 return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1360 if (WINE_D3D9_CAPABLE(gl_info))
1362 /* GeforceFX - highend */
1363 if (strstr(gl_renderer, "5800")
1364 || strstr(gl_renderer, "5900")
1365 || strstr(gl_renderer, "5950")
1366 || strstr(gl_renderer, "Quadro FX"))
1368 *vidmem = 256; /* 5800-5900 cards use 256MB */
1369 return CARD_NVIDIA_GEFORCEFX_5800;
1372 /* GeforceFX - midend */
1373 if (strstr(gl_renderer, "5600")
1374 || strstr(gl_renderer, "5650")
1375 || strstr(gl_renderer, "5700")
1376 || strstr(gl_renderer, "5750"))
1378 *vidmem = 128; /* A 5600 uses 128-256MB */
1379 return CARD_NVIDIA_GEFORCEFX_5600;
1382 /* GeforceFX - lowend */
1383 *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1384 return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1387 if (WINE_D3D8_CAPABLE(gl_info))
1389 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1391 *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1392 return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1395 *vidmem = 64; /* Geforce3 cards have 64-128MB */
1396 return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1399 if (WINE_D3D7_CAPABLE(gl_info))
1401 if (strstr(gl_renderer, "GeForce4 MX"))
1403 /* Most Geforce4MX GPUs have at least 64MB of memory, some
1404 * early models had 32MB but most have 64MB or even 128MB. */
1405 *vidmem = 64;
1406 return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1409 if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1411 *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1412 return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1415 if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1417 *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1418 return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1421 /* Most Geforce1 cards have 32MB, there are also some rare 16
1422 * and 64MB (Dell) models. */
1423 *vidmem = 32;
1424 return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1427 if (strstr(gl_renderer, "TNT2"))
1429 *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1430 return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1433 *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1434 return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1436 case VENDOR_ATI:
1437 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1439 * Beware: renderer string do not match exact card model,
1440 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1441 if (WINE_D3D9_CAPABLE(gl_info))
1443 /* Radeon EG CYPRESS XT / PRO HD5800 - highend */
1444 if (strstr(gl_renderer, "HD 5800") /* Radeon EG CYPRESS HD58xx generic renderer string */
1445 || strstr(gl_renderer, "HD 5850") /* Radeon EG CYPRESS XT */
1446 || strstr(gl_renderer, "HD 5870")) /* Radeon EG CYPRESS PRO */
1448 *vidmem = 1024; /* note: HD58xx cards use 1024MB */
1449 return CARD_ATI_RADEON_HD5800;
1452 /* Radeon EG JUNIPER XT / LE HD5700 - midend */
1453 if (strstr(gl_renderer, "HD 5700") /* Radeon EG JUNIPER HD57xx generic renderer string */
1454 || strstr(gl_renderer, "HD 5750") /* Radeon EG JUNIPER LE */
1455 || strstr(gl_renderer, "HD 5770")) /* Radeon EG JUNIPER XT */
1457 *vidmem = 512; /* note: HD5770 cards use 1024MB and HD5750 cards use 512MB or 1024MB */
1458 return CARD_ATI_RADEON_HD5700;
1461 /* Radeon R7xx HD4800 - highend */
1462 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1463 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1464 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1465 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1466 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1468 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1469 return CARD_ATI_RADEON_HD4800;
1472 /* Radeon R740 HD4700 - midend */
1473 if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1474 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1476 *vidmem = 512;
1477 return CARD_ATI_RADEON_HD4700;
1480 /* Radeon R730 HD4600 - midend */
1481 if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1482 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1483 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1485 *vidmem = 512;
1486 return CARD_ATI_RADEON_HD4600;
1489 /* Radeon R710 HD4500/HD4350 - lowend */
1490 if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1491 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1493 *vidmem = 256;
1494 return CARD_ATI_RADEON_HD4350;
1497 /* Radeon R6xx HD2900/HD3800 - highend */
1498 if (strstr(gl_renderer, "HD 2900")
1499 || strstr(gl_renderer, "HD 3870")
1500 || strstr(gl_renderer, "HD 3850"))
1502 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1503 return CARD_ATI_RADEON_HD2900;
1506 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1507 if (strstr(gl_renderer, "HD 2600")
1508 || strstr(gl_renderer, "HD 3830")
1509 || strstr(gl_renderer, "HD 3690")
1510 || strstr(gl_renderer, "HD 3650"))
1512 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1513 return CARD_ATI_RADEON_HD2600;
1516 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1517 if (strstr(gl_renderer, "HD 2300")
1518 || strstr(gl_renderer, "HD 2400")
1519 || strstr(gl_renderer, "HD 3470")
1520 || strstr(gl_renderer, "HD 3450")
1521 || strstr(gl_renderer, "HD 3430")
1522 || strstr(gl_renderer, "HD 3400"))
1524 *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1525 return CARD_ATI_RADEON_HD2300;
1528 /* Radeon R6xx/R7xx integrated */
1529 if (strstr(gl_renderer, "HD 3100")
1530 || strstr(gl_renderer, "HD 3200")
1531 || strstr(gl_renderer, "HD 3300"))
1533 *vidmem = 128; /* 128MB */
1534 return CARD_ATI_RADEON_HD3200;
1537 /* Radeon R5xx */
1538 if (strstr(gl_renderer, "X1600")
1539 || strstr(gl_renderer, "X1650")
1540 || strstr(gl_renderer, "X1800")
1541 || strstr(gl_renderer, "X1900")
1542 || strstr(gl_renderer, "X1950"))
1544 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1545 return CARD_ATI_RADEON_X1600;
1548 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1549 if (strstr(gl_renderer, "X700")
1550 || strstr(gl_renderer, "X800")
1551 || strstr(gl_renderer, "X850")
1552 || strstr(gl_renderer, "X1300")
1553 || strstr(gl_renderer, "X1400")
1554 || strstr(gl_renderer, "X1450")
1555 || strstr(gl_renderer, "X1550"))
1557 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1558 return CARD_ATI_RADEON_X700;
1561 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1562 if (strstr(gl_renderer, "Radeon Xpress"))
1564 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1565 return CARD_ATI_RADEON_XPRESS_200M;
1568 /* Radeon R3xx */
1569 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1570 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1573 if (WINE_D3D8_CAPABLE(gl_info))
1575 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1576 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1579 if (WINE_D3D7_CAPABLE(gl_info))
1581 *vidmem = 32; /* There are models with up to 64MB */
1582 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1585 *vidmem = 16; /* There are 16-32MB models */
1586 return CARD_ATI_RAGE_128PRO;
1588 case VENDOR_INTEL:
1589 if (strstr(gl_renderer, "X3100"))
1591 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1592 *vidmem = 128;
1593 return CARD_INTEL_X3100;
1596 if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1598 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1599 *vidmem = 64;
1600 return CARD_INTEL_I945GM;
1603 if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM;
1604 if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G;
1605 if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G;
1606 if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G;
1607 if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G;
1608 return CARD_INTEL_I915G;
1610 case VENDOR_MESA:
1611 case VENDOR_WINE:
1612 default:
1613 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1614 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1615 * them a good generic choice. */
1616 *vendor = VENDOR_NVIDIA;
1617 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1618 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1619 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1620 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
1621 return CARD_NVIDIA_RIVA_128;
1625 /* Context activation is done by the caller. */
1626 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_driver_info *driver_info, struct wined3d_gl_info *gl_info)
1628 const char *GL_Extensions = NULL;
1629 const char *WGL_Extensions = NULL;
1630 const char *gl_string = NULL;
1631 enum wined3d_pci_vendor vendor;
1632 enum wined3d_pci_device device;
1633 GLint gl_max;
1634 GLfloat gl_floatv[2];
1635 unsigned i;
1636 HDC hdc;
1637 unsigned int vidmem=0;
1638 char *gl_renderer;
1639 DWORD gl_version;
1640 size_t len;
1642 TRACE_(d3d_caps)("(%p)\n", gl_info);
1644 ENTER_GL();
1646 gl_string = (const char *)glGetString(GL_RENDERER);
1647 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_string));
1648 if (!gl_string)
1650 LEAVE_GL();
1651 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
1652 return FALSE;
1655 len = strlen(gl_string) + 1;
1656 gl_renderer = HeapAlloc(GetProcessHeap(), 0, len);
1657 if (!gl_renderer)
1659 LEAVE_GL();
1660 ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n");
1661 return FALSE;
1663 memcpy(gl_renderer, gl_string, len);
1665 gl_string = (const char *)glGetString(GL_VENDOR);
1666 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_string));
1667 if (!gl_string)
1669 LEAVE_GL();
1670 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
1671 HeapFree(GetProcessHeap(), 0, gl_renderer);
1672 return FALSE;
1674 vendor = wined3d_guess_vendor(gl_string, gl_renderer);
1675 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), vendor);
1677 /* Parse the GL_VERSION field into major and minor information */
1678 gl_string = (const char *)glGetString(GL_VERSION);
1679 TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_string));
1680 if (!gl_string)
1682 LEAVE_GL();
1683 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
1684 HeapFree(GetProcessHeap(), 0, gl_renderer);
1685 return FALSE;
1687 gl_version = wined3d_parse_gl_version(gl_string);
1690 * Initialize openGL extension related variables
1691 * with Default values
1693 memset(gl_info->supported, 0, sizeof(gl_info->supported));
1694 gl_info->limits.buffers = 1;
1695 gl_info->limits.textures = 1;
1696 gl_info->limits.texture_stages = 1;
1697 gl_info->limits.fragment_samplers = 1;
1698 gl_info->limits.vertex_samplers = 0;
1699 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
1700 gl_info->limits.sampler_stages = 1;
1701 gl_info->limits.glsl_vs_float_constants = 0;
1702 gl_info->limits.glsl_ps_float_constants = 0;
1703 gl_info->limits.arb_vs_float_constants = 0;
1704 gl_info->limits.arb_vs_native_constants = 0;
1705 gl_info->limits.arb_vs_instructions = 0;
1706 gl_info->limits.arb_vs_temps = 0;
1707 gl_info->limits.arb_ps_float_constants = 0;
1708 gl_info->limits.arb_ps_local_constants = 0;
1709 gl_info->limits.arb_ps_instructions = 0;
1710 gl_info->limits.arb_ps_temps = 0;
1712 /* Retrieve opengl defaults */
1713 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1714 gl_info->limits.clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
1715 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
1717 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1718 gl_info->limits.lights = gl_max;
1719 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
1721 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
1722 gl_info->limits.texture_size = gl_max;
1723 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
1725 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
1726 gl_info->limits.pointsize_min = gl_floatv[0];
1727 gl_info->limits.pointsize_max = gl_floatv[1];
1728 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
1730 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
1731 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
1732 if (!GL_Extensions)
1734 LEAVE_GL();
1735 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
1736 HeapFree(GetProcessHeap(), 0, gl_renderer);
1737 return FALSE;
1740 LEAVE_GL();
1742 TRACE_(d3d_caps)("GL_Extensions reported:\n");
1744 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
1746 while (*GL_Extensions)
1748 const char *start;
1749 char current_ext[256];
1751 while (isspace(*GL_Extensions)) ++GL_Extensions;
1752 start = GL_Extensions;
1753 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
1755 len = GL_Extensions - start;
1756 if (!len || len >= sizeof(current_ext)) continue;
1758 memcpy(current_ext, start, len);
1759 current_ext[len] = '\0';
1760 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
1762 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1764 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
1766 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
1767 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1768 break;
1773 /* Now work out what GL support this card really has */
1774 #define USE_GL_FUNC(type, pfn, ext, replace) \
1776 DWORD ver = ver_for_ext(ext); \
1777 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
1778 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
1779 else gl_info->pfn = NULL; \
1781 GL_EXT_FUNCS_GEN;
1782 #undef USE_GL_FUNC
1784 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
1785 WGL_EXT_FUNCS_GEN;
1786 #undef USE_GL_FUNC
1788 ENTER_GL();
1790 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
1791 * loading the functions, otherwise the code above will load the extension entry points instead of the
1792 * core functions, which may not work. */
1793 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1795 if (!gl_info->supported[EXTENSION_MAP[i].extension]
1796 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
1798 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
1799 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1803 if (gl_info->supported[APPLE_FENCE])
1805 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
1806 * The apple extension interacts with some other apple exts. Disable the NV
1807 * extension if the apple one is support to prevent confusion in other parts
1808 * of the code. */
1809 gl_info->supported[NV_FENCE] = FALSE;
1811 if (gl_info->supported[APPLE_FLOAT_PIXELS])
1813 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
1815 * The enums are the same:
1816 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
1817 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
1818 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
1819 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
1820 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
1822 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
1824 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
1825 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
1827 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
1829 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
1830 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
1833 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1835 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
1836 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
1838 if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
1840 TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
1841 gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
1843 if (gl_info->supported[NV_TEXTURE_SHADER2])
1845 if (gl_info->supported[NV_REGISTER_COMBINERS])
1847 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
1848 * are supported. The nv extensions provide the same functionality as the
1849 * ATI one, and a bit more(signed pixelformats). */
1850 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
1853 if (gl_info->supported[ARB_DRAW_BUFFERS])
1855 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
1856 gl_info->limits.buffers = gl_max;
1857 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
1859 if (gl_info->supported[ARB_MULTITEXTURE])
1861 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1862 gl_info->limits.textures = min(MAX_TEXTURES, gl_max);
1863 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->limits.textures);
1865 if (gl_info->supported[NV_REGISTER_COMBINERS])
1867 GLint tmp;
1868 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
1869 gl_info->limits.texture_stages = min(MAX_TEXTURES, tmp);
1871 else
1873 gl_info->limits.texture_stages = min(MAX_TEXTURES, gl_max);
1875 TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->limits.texture_stages);
1877 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1879 GLint tmp;
1880 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1881 gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
1883 else
1885 gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, gl_max);
1887 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers);
1889 if (gl_info->supported[ARB_VERTEX_SHADER])
1891 GLint tmp;
1892 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1893 gl_info->limits.vertex_samplers = tmp;
1894 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1895 gl_info->limits.combined_samplers = tmp;
1897 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
1898 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
1899 * an issue because then the sampler setup only depends on the two shaders. If a pixel
1900 * shader is used with fixed function vertex processing we're fine too because fixed function
1901 * vertex processing doesn't use any samplers. If fixed function fragment processing is
1902 * used we have to make sure that all vertex sampler setups are valid together with all
1903 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
1904 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
1905 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
1906 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
1907 * a fixed function pipeline anymore.
1909 * So this is just a check to check that our assumption holds true. If not, write a warning
1910 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
1911 if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12
1912 && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers)
1914 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
1915 gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers);
1916 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
1917 if (gl_info->limits.combined_samplers > MAX_TEXTURES)
1918 gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES;
1919 else
1920 gl_info->limits.vertex_samplers = 0;
1923 else
1925 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers;
1927 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers);
1928 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->limits.combined_samplers);
1930 if (gl_info->supported[ARB_VERTEX_BLEND])
1932 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1933 gl_info->limits.blends = gl_max;
1934 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->limits.blends);
1936 if (gl_info->supported[EXT_TEXTURE3D])
1938 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
1939 gl_info->limits.texture3d_size = gl_max;
1940 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->limits.texture3d_size);
1942 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
1944 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1945 gl_info->limits.anisotropy = gl_max;
1946 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->limits.anisotropy);
1948 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1950 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1951 gl_info->limits.arb_ps_float_constants = gl_max;
1952 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants);
1953 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
1954 gl_info->limits.arb_ps_native_constants = gl_max;
1955 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n",
1956 gl_info->limits.arb_ps_native_constants);
1957 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1958 gl_info->limits.arb_ps_temps = gl_max;
1959 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps);
1960 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1961 gl_info->limits.arb_ps_instructions = gl_max;
1962 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions);
1963 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
1964 gl_info->limits.arb_ps_local_constants = gl_max;
1965 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions);
1967 if (gl_info->supported[ARB_VERTEX_PROGRAM])
1969 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1970 gl_info->limits.arb_vs_float_constants = gl_max;
1971 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants);
1972 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
1973 gl_info->limits.arb_vs_native_constants = gl_max;
1974 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native float constants: %d.\n",
1975 gl_info->limits.arb_vs_native_constants);
1976 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1977 gl_info->limits.arb_vs_temps = gl_max;
1978 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps);
1979 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1980 gl_info->limits.arb_vs_instructions = gl_max;
1981 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions);
1983 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
1985 if (gl_info->supported[ARB_VERTEX_SHADER])
1987 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
1988 gl_info->limits.glsl_vs_float_constants = gl_max / 4;
1989 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
1991 if (gl_info->supported[ARB_FRAGMENT_SHADER])
1993 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
1994 gl_info->limits.glsl_ps_float_constants = gl_max / 4;
1995 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants);
1996 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
1997 gl_info->limits.glsl_varyings = gl_max;
1998 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
2000 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
2002 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess);
2004 else
2006 gl_info->limits.shininess = 128.0f;
2008 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
2010 /* If we have full NP2 texture support, disable
2011 * GL_ARB_texture_rectangle because we will never use it.
2012 * This saves a few redundant glDisable calls. */
2013 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
2015 if (gl_info->supported[ATI_FRAGMENT_SHADER])
2017 /* Disable NV_register_combiners and fragment shader if this is supported.
2018 * generally the NV extensions are preferred over the ATI ones, and this
2019 * extension is disabled if register_combiners and texture_shader2 are both
2020 * supported. So we reach this place only if we have incomplete NV dxlevel 8
2021 * fragment processing support. */
2022 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
2023 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
2024 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
2025 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
2026 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
2028 if (gl_info->supported[NV_HALF_FLOAT])
2030 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
2031 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
2033 if (gl_info->supported[ARB_POINT_SPRITE])
2035 gl_info->limits.point_sprite_units = gl_info->limits.textures;
2037 else
2039 gl_info->limits.point_sprite_units = 0;
2041 checkGLcall("extension detection");
2043 LEAVE_GL();
2045 /* In some cases the number of texture stages can be larger than the number
2046 * of samplers. The GF4 for example can use only 2 samplers (no fragment
2047 * shaders), but 8 texture stages (register combiners). */
2048 gl_info->limits.sampler_stages = max(gl_info->limits.fragment_samplers, gl_info->limits.texture_stages);
2050 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
2052 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbuffer;
2053 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbuffer;
2054 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffers;
2055 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffers;
2056 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorage;
2057 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisample;
2058 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameteriv;
2059 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebuffer;
2060 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebuffer;
2061 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffers;
2062 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffers;
2063 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatus;
2064 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1D;
2065 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2D;
2066 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3D;
2067 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbuffer;
2068 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameteriv;
2069 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebuffer;
2070 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmap;
2072 else
2074 if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT])
2076 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbufferEXT;
2077 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbufferEXT;
2078 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffersEXT;
2079 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffersEXT;
2080 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorageEXT;
2081 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameterivEXT;
2082 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebufferEXT;
2083 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebufferEXT;
2084 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffersEXT;
2085 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffersEXT;
2086 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatusEXT;
2087 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1DEXT;
2088 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2DEXT;
2089 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3DEXT;
2090 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbufferEXT;
2091 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameterivEXT;
2092 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmapEXT;
2094 else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2096 WARN_(d3d_caps)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
2097 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
2099 if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
2101 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebufferEXT;
2103 if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
2105 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisampleEXT;
2109 /* MRTs are currently only supported when FBOs are used. */
2110 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
2112 gl_info->limits.buffers = 1;
2115 device = wined3d_guess_card(gl_info, gl_renderer, &vendor, &vidmem);
2116 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", vendor, device);
2118 /* If we have an estimate use it, else default to 64MB; */
2119 if(vidmem)
2120 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
2121 else
2122 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
2124 gl_info->wrap_lookup[WINED3DTADDRESS_WRAP - WINED3DTADDRESS_WRAP] = GL_REPEAT;
2125 gl_info->wrap_lookup[WINED3DTADDRESS_MIRROR - WINED3DTADDRESS_WRAP] =
2126 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
2127 gl_info->wrap_lookup[WINED3DTADDRESS_CLAMP - WINED3DTADDRESS_WRAP] = GL_CLAMP_TO_EDGE;
2128 gl_info->wrap_lookup[WINED3DTADDRESS_BORDER - WINED3DTADDRESS_WRAP] =
2129 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2130 gl_info->wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP] =
2131 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
2133 /* Make sure there's an active HDC else the WGL extensions will fail */
2134 hdc = pwglGetCurrentDC();
2135 if (hdc) {
2136 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2137 if(GL_EXTCALL(wglGetExtensionsStringARB))
2138 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2140 if (NULL == WGL_Extensions) {
2141 ERR(" WGL_Extensions returns NULL\n");
2142 } else {
2143 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2144 while (*WGL_Extensions != 0x00) {
2145 const char *Start;
2146 char ThisExtn[256];
2148 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2149 Start = WGL_Extensions;
2150 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2151 WGL_Extensions++;
2154 len = WGL_Extensions - Start;
2155 if (len == 0 || len >= sizeof(ThisExtn))
2156 continue;
2158 memcpy(ThisExtn, Start, len);
2159 ThisExtn[len] = '\0';
2160 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
2162 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
2163 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
2164 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
2166 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2167 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2168 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2170 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2171 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2172 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2178 fixup_extensions(gl_info, gl_renderer, vendor, device);
2179 init_driver_info(driver_info, vendor, device);
2180 add_gl_compat_wrappers(gl_info);
2182 HeapFree(GetProcessHeap(), 0, gl_renderer);
2183 return TRUE;
2186 /**********************************************************
2187 * IWineD3D implementation follows
2188 **********************************************************/
2190 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2191 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2193 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2195 return This->adapter_count;
2198 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void *init_function)
2200 FIXME("iface %p, init_function %p stub!\n", iface, init_function);
2202 return WINED3D_OK;
2205 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2206 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2208 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2210 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2211 return NULL;
2214 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2217 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2218 of the same bpp but different resolutions */
2220 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2221 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2222 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2223 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2225 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2226 return 0;
2229 /* TODO: Store modes per adapter and read it from the adapter structure */
2230 if (Adapter == 0) { /* Display */
2231 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2232 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2233 unsigned int i = 0;
2234 unsigned int j = 0;
2235 DEVMODEW mode;
2237 memset(&mode, 0, sizeof(mode));
2238 mode.dmSize = sizeof(mode);
2240 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2242 ++j;
2244 if (Format == WINED3DFMT_UNKNOWN)
2246 /* This is for D3D8, do not enumerate P8 here */
2247 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2249 else if (mode.dmBitsPerPel == format_bits)
2251 ++i;
2255 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2256 return i;
2257 } else {
2258 FIXME_(d3d_caps)("Adapter not primary display\n");
2260 return 0;
2263 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2264 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2265 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2266 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2268 /* Validate the parameters as much as possible */
2269 if (NULL == pMode ||
2270 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2271 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2272 return WINED3DERR_INVALIDCALL;
2275 /* TODO: Store modes per adapter and read it from the adapter structure */
2276 if (Adapter == 0)
2278 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2279 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2280 DEVMODEW DevModeW;
2281 int ModeIdx = 0;
2282 UINT i = 0;
2283 int j = 0;
2285 ZeroMemory(&DevModeW, sizeof(DevModeW));
2286 DevModeW.dmSize = sizeof(DevModeW);
2288 /* If we are filtering to a specific format (D3D9), then need to skip
2289 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2290 just count through the ones with valid bit depths */
2291 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0))
2293 if (Format == WINED3DFMT_UNKNOWN)
2295 /* This is for D3D8, do not enumerate P8 here */
2296 if (DevModeW.dmBitsPerPel == 32 || DevModeW.dmBitsPerPel == 16) ++i;
2298 else if (DevModeW.dmBitsPerPel == format_bits)
2300 ++i;
2304 if (i == 0) {
2305 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2306 return WINED3DERR_INVALIDCALL;
2308 ModeIdx = j - 1;
2310 /* Now get the display mode via the calculated index */
2311 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2312 pMode->Width = DevModeW.dmPelsWidth;
2313 pMode->Height = DevModeW.dmPelsHeight;
2314 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2315 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2316 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2318 if (Format == WINED3DFMT_UNKNOWN) {
2319 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2320 } else {
2321 pMode->Format = Format;
2323 } else {
2324 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2325 return WINED3DERR_INVALIDCALL;
2328 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2329 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2330 DevModeW.dmBitsPerPel);
2333 else
2335 FIXME_(d3d_caps)("Adapter not primary display\n");
2338 return WINED3D_OK;
2341 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE *pMode)
2343 TRACE("iface %p, adapter_idx %u, display_mode %p.\n", iface, Adapter, pMode);
2345 if (NULL == pMode ||
2346 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2347 return WINED3DERR_INVALIDCALL;
2350 if (Adapter == 0) { /* Display */
2351 int bpp = 0;
2352 DEVMODEW DevModeW;
2354 ZeroMemory(&DevModeW, sizeof(DevModeW));
2355 DevModeW.dmSize = sizeof(DevModeW);
2357 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2358 pMode->Width = DevModeW.dmPelsWidth;
2359 pMode->Height = DevModeW.dmPelsHeight;
2360 bpp = DevModeW.dmBitsPerPel;
2361 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2362 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2364 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2367 pMode->Format = pixelformat_for_depth(bpp);
2368 } else {
2369 FIXME_(d3d_caps)("Adapter not primary display\n");
2372 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2373 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2374 return WINED3D_OK;
2377 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2378 and fields being inserted in the middle, a new structure is used in place */
2379 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2380 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2381 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2382 struct wined3d_adapter *adapter;
2383 size_t len;
2385 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2387 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2388 return WINED3DERR_INVALIDCALL;
2391 adapter = &This->adapters[Adapter];
2393 /* Return the information requested */
2394 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2396 if (pIdentifier->driver_size)
2398 const char *name = adapter->driver_info.name;
2399 len = min(strlen(name), pIdentifier->driver_size - 1);
2400 memcpy(pIdentifier->driver, name, len);
2401 pIdentifier->driver[len] = '\0';
2404 if (pIdentifier->description_size)
2406 const char *description = adapter->driver_info.description;
2407 len = min(strlen(description), pIdentifier->description_size - 1);
2408 memcpy(pIdentifier->description, description, len);
2409 pIdentifier->description[len] = '\0';
2412 /* Note that d3d8 doesn't supply a device name. */
2413 if (pIdentifier->device_name_size)
2415 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2417 len = strlen(device_name);
2418 if (len >= pIdentifier->device_name_size)
2420 ERR("Device name size too small.\n");
2421 return WINED3DERR_INVALIDCALL;
2424 memcpy(pIdentifier->device_name, device_name, len);
2425 pIdentifier->device_name[len] = '\0';
2428 pIdentifier->driver_version.u.HighPart = adapter->driver_info.version_high;
2429 pIdentifier->driver_version.u.LowPart = adapter->driver_info.version_low;
2430 pIdentifier->vendor_id = adapter->driver_info.vendor;
2431 pIdentifier->device_id = adapter->driver_info.device;
2432 pIdentifier->subsystem_id = 0;
2433 pIdentifier->revision = 0;
2434 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2435 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2436 memcpy(&pIdentifier->adapter_luid, &adapter->luid, sizeof(pIdentifier->adapter_luid));
2437 pIdentifier->video_memory = adapter->TextureRam;
2439 return WINED3D_OK;
2442 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2443 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2445 short redSize, greenSize, blueSize, alphaSize, colorBits;
2447 if(!cfg)
2448 return FALSE;
2450 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2451 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2453 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2454 return FALSE;
2457 if(cfg->redSize < redSize)
2458 return FALSE;
2460 if(cfg->greenSize < greenSize)
2461 return FALSE;
2463 if(cfg->blueSize < blueSize)
2464 return FALSE;
2466 if(cfg->alphaSize < alphaSize)
2467 return FALSE;
2469 return TRUE;
2470 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2471 if (format_desc->format == WINED3DFMT_R16_FLOAT)
2472 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2473 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2474 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2475 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2476 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2477 if (format_desc->format == WINED3DFMT_R32_FLOAT)
2478 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2479 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2480 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2481 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2482 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
2483 } else {
2484 /* Probably a color index mode */
2485 return FALSE;
2488 return FALSE;
2491 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2492 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2494 short depthSize, stencilSize;
2495 BOOL lockable = FALSE;
2497 if(!cfg)
2498 return FALSE;
2500 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2502 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2503 return FALSE;
2506 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32_FLOAT))
2507 lockable = TRUE;
2509 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2510 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2511 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2512 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2513 return FALSE;
2515 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2516 * allow more stencil bits than requested. */
2517 if(cfg->stencilSize < stencilSize)
2518 return FALSE;
2520 return TRUE;
2523 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2524 WINED3DFORMAT AdapterFormat,
2525 WINED3DFORMAT RenderTargetFormat,
2526 WINED3DFORMAT DepthStencilFormat) {
2527 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2528 int nCfgs;
2529 const WineD3D_PixelFormat *cfgs;
2530 const struct wined3d_adapter *adapter;
2531 const struct GlPixelFormatDesc *rt_format_desc;
2532 const struct GlPixelFormatDesc *ds_format_desc;
2533 int it;
2535 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2536 This, Adapter,
2537 DeviceType, debug_d3ddevicetype(DeviceType),
2538 AdapterFormat, debug_d3dformat(AdapterFormat),
2539 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2540 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2542 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2543 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2544 return WINED3DERR_INVALIDCALL;
2547 adapter = &This->adapters[Adapter];
2548 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
2549 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2550 cfgs = adapter->cfgs;
2551 nCfgs = adapter->nCfgs;
2552 for (it = 0; it < nCfgs; ++it) {
2553 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2555 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2557 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
2558 return WINED3D_OK;
2562 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2564 return WINED3DERR_NOTAVAILABLE;
2567 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2568 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
2570 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2571 const struct GlPixelFormatDesc *glDesc;
2572 const struct wined3d_adapter *adapter;
2574 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2575 This,
2576 Adapter,
2577 DeviceType, debug_d3ddevicetype(DeviceType),
2578 SurfaceFormat, debug_d3dformat(SurfaceFormat),
2579 Windowed,
2580 MultiSampleType,
2581 pQualityLevels);
2583 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2584 return WINED3DERR_INVALIDCALL;
2587 /* TODO: handle Windowed, add more quality levels */
2589 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
2590 if(pQualityLevels) *pQualityLevels = 1;
2591 return WINED3D_OK;
2594 /* By default multisampling is disabled right now as it causes issues
2595 * on some Nvidia driver versions and it doesn't work well in combination
2596 * with FBOs yet. */
2597 if(!wined3d_settings.allow_multisampling)
2598 return WINED3DERR_NOTAVAILABLE;
2600 adapter = &This->adapters[Adapter];
2601 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
2602 if (!glDesc) return WINED3DERR_INVALIDCALL;
2604 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
2605 int i, nCfgs;
2606 const WineD3D_PixelFormat *cfgs;
2608 cfgs = adapter->cfgs;
2609 nCfgs = adapter->nCfgs;
2610 for(i=0; i<nCfgs; i++) {
2611 if(cfgs[i].numSamples != MultiSampleType)
2612 continue;
2614 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
2615 continue;
2617 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2619 if(pQualityLevels)
2620 *pQualityLevels = 1; /* Guess at a value! */
2621 return WINED3D_OK;
2624 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
2625 short redSize, greenSize, blueSize, alphaSize, colorBits;
2626 int i, nCfgs;
2627 const WineD3D_PixelFormat *cfgs;
2629 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2631 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
2632 return WINED3DERR_NOTAVAILABLE;
2635 cfgs = adapter->cfgs;
2636 nCfgs = adapter->nCfgs;
2637 for(i=0; i<nCfgs; i++) {
2638 if(cfgs[i].numSamples != MultiSampleType)
2639 continue;
2640 if(cfgs[i].redSize != redSize)
2641 continue;
2642 if(cfgs[i].greenSize != greenSize)
2643 continue;
2644 if(cfgs[i].blueSize != blueSize)
2645 continue;
2646 if(cfgs[i].alphaSize != alphaSize)
2647 continue;
2649 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2651 if(pQualityLevels)
2652 *pQualityLevels = 1; /* Guess at a value! */
2653 return WINED3D_OK;
2656 return WINED3DERR_NOTAVAILABLE;
2659 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2660 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed)
2662 HRESULT hr = WINED3DERR_NOTAVAILABLE;
2663 UINT nmodes;
2665 TRACE("iface %p, adapter_idx %u, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
2666 iface, Adapter, debug_d3ddevicetype(DeviceType), debug_d3dformat(DisplayFormat),
2667 debug_d3dformat(BackBufferFormat), Windowed);
2669 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2670 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2671 return WINED3DERR_INVALIDCALL;
2674 /* The task of this function is to check whether a certain display / backbuffer format
2675 * combination is available on the given adapter. In fullscreen mode microsoft specified
2676 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2677 * and display format should match exactly.
2678 * In windowed mode format conversion can occur and this depends on the driver. When format
2679 * conversion is done, this function should nevertheless fail and applications need to use
2680 * CheckDeviceFormatConversion.
2681 * At the moment we assume that fullscreen and windowed have the same capabilities */
2683 /* There are only 4 display formats */
2684 if (!(DisplayFormat == WINED3DFMT_B5G6R5_UNORM
2685 || DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
2686 || DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
2687 || DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM))
2689 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2690 return WINED3DERR_NOTAVAILABLE;
2693 /* If the requested DisplayFormat is not available, don't continue */
2694 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2695 if(!nmodes) {
2696 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2697 return WINED3DERR_NOTAVAILABLE;
2700 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2701 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2702 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2703 return WINED3DERR_NOTAVAILABLE;
2706 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2707 if (DisplayFormat == WINED3DFMT_B5G6R5_UNORM && BackBufferFormat != WINED3DFMT_B5G6R5_UNORM)
2709 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2710 return WINED3DERR_NOTAVAILABLE;
2713 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2714 if (DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
2715 && !(BackBufferFormat == WINED3DFMT_B5G5R5X1_UNORM || BackBufferFormat == WINED3DFMT_B5G5R5A1_UNORM))
2717 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2718 return WINED3DERR_NOTAVAILABLE;
2721 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2722 if (DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
2723 && !(BackBufferFormat == WINED3DFMT_B8G8R8X8_UNORM || BackBufferFormat == WINED3DFMT_B8G8R8A8_UNORM))
2725 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2726 return WINED3DERR_NOTAVAILABLE;
2729 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2730 if (DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM
2731 && (BackBufferFormat != WINED3DFMT_B10G10R10A2_UNORM || Windowed))
2733 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2734 return WINED3DERR_NOTAVAILABLE;
2737 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2738 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2739 if(FAILED(hr))
2740 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2742 return hr;
2746 /* Check if we support bumpmapping for a format */
2747 static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter,
2748 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2750 const struct fragment_pipeline *fp;
2752 switch(format_desc->format)
2754 case WINED3DFMT_R8G8_SNORM:
2755 case WINED3DFMT_R16G16_SNORM:
2756 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
2757 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
2758 case WINED3DFMT_R8G8B8A8_SNORM:
2759 /* Ask the fixed function pipeline implementation if it can deal
2760 * with the conversion. If we've got a GL extension giving native
2761 * support this will be an identity conversion. */
2762 fp = select_fragment_implementation(adapter, DeviceType);
2763 if (fp->color_fixup_supported(format_desc->color_fixup))
2765 TRACE_(d3d_caps)("[OK]\n");
2766 return TRUE;
2768 TRACE_(d3d_caps)("[FAILED]\n");
2769 return FALSE;
2771 default:
2772 TRACE_(d3d_caps)("[FAILED]\n");
2773 return FALSE;
2777 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2778 static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter,
2779 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2781 int it=0;
2783 /* Only allow depth/stencil formats */
2784 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
2786 /* Walk through all WGL pixel formats to find a match */
2787 for (it = 0; it < adapter->nCfgs; ++it)
2789 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2790 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2792 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2794 return TRUE;
2799 return FALSE;
2802 static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2804 /* The flags entry of a format contains the filtering capability */
2805 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2807 return FALSE;
2810 /* Check the render target capabilities of a format */
2811 static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter,
2812 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2814 /* Filter out non-RT formats */
2815 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2817 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2818 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2819 int it;
2820 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2821 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2823 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2824 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2826 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2827 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2828 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2829 TRACE_(d3d_caps)("[FAILED]\n");
2830 return FALSE;
2833 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2834 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2835 for (it = 0; it < adapter->nCfgs; ++it)
2837 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2838 &cfgs[it], check_format_desc))
2840 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2841 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2842 return TRUE;
2845 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2846 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2847 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2848 int it;
2850 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2851 for (it = 0; it < adapter->nCfgs; ++it)
2853 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2854 &cfgs[it], check_format_desc))
2856 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2857 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2858 return TRUE;
2861 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2862 /* For now return TRUE for FBOs until we have some proper checks.
2863 * Note that this function will only be called when the format is around for texturing. */
2864 return TRUE;
2866 return FALSE;
2869 static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2871 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2873 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2874 if (!gl_info->supported[EXT_TEXTURE_SRGB])
2876 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2877 return FALSE;
2880 switch (format_desc->format)
2882 case WINED3DFMT_B8G8R8A8_UNORM:
2883 case WINED3DFMT_B8G8R8X8_UNORM:
2884 case WINED3DFMT_B4G4R4A4_UNORM:
2885 case WINED3DFMT_L8_UNORM:
2886 case WINED3DFMT_L8A8_UNORM:
2887 case WINED3DFMT_DXT1:
2888 case WINED3DFMT_DXT2:
2889 case WINED3DFMT_DXT3:
2890 case WINED3DFMT_DXT4:
2891 case WINED3DFMT_DXT5:
2892 TRACE_(d3d_caps)("[OK]\n");
2893 return TRUE;
2895 default:
2896 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2897 return FALSE;
2899 return FALSE;
2902 static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter,
2903 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2905 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2906 * doing the color fixup in shaders.
2907 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2908 if ((format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) || (format_desc->format == WINED3DFMT_B8G8R8A8_UNORM))
2910 int vs_selected_mode;
2911 int ps_selected_mode;
2912 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
2914 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2915 TRACE_(d3d_caps)("[OK]\n");
2916 return TRUE;
2920 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2921 return FALSE;
2924 /* Check if a format support blending in combination with pixel shaders */
2925 static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapter,
2926 const struct GlPixelFormatDesc *format_desc)
2928 /* The flags entry of a format contains the post pixel shader blending capability */
2929 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2931 return FALSE;
2934 static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2936 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2937 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2938 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2939 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2940 * capability anyway.
2942 * For now lets report this on all formats, but in the future we may want to
2943 * restrict it to some should games need that
2945 return TRUE;
2948 /* Check if a texture format is supported on the given adapter */
2949 static BOOL CheckTextureCapability(struct wined3d_adapter *adapter,
2950 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2952 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2953 const shader_backend_t *shader_backend;
2954 const struct fragment_pipeline *fp;
2956 switch (format_desc->format)
2958 /*****
2959 * supported: RGB(A) formats
2961 case WINED3DFMT_B8G8R8_UNORM: /* Enable for dx7, blacklisted for 8 and 9 above */
2962 case WINED3DFMT_B8G8R8A8_UNORM:
2963 case WINED3DFMT_B8G8R8X8_UNORM:
2964 case WINED3DFMT_B5G6R5_UNORM:
2965 case WINED3DFMT_B5G5R5X1_UNORM:
2966 case WINED3DFMT_B5G5R5A1_UNORM:
2967 case WINED3DFMT_B4G4R4A4_UNORM:
2968 case WINED3DFMT_A8_UNORM:
2969 case WINED3DFMT_B4G4R4X4_UNORM:
2970 case WINED3DFMT_R8G8B8A8_UNORM:
2971 case WINED3DFMT_R8G8B8X8_UNORM:
2972 case WINED3DFMT_B10G10R10A2_UNORM:
2973 case WINED3DFMT_R10G10B10A2_UNORM:
2974 case WINED3DFMT_R16G16_UNORM:
2975 TRACE_(d3d_caps)("[OK]\n");
2976 return TRUE;
2978 case WINED3DFMT_B2G3R3_UNORM:
2979 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2980 return FALSE;
2982 /*****
2983 * supported: Palettized
2985 case WINED3DFMT_P8_UINT:
2986 TRACE_(d3d_caps)("[OK]\n");
2987 return TRUE;
2988 /* No Windows driver offers WINED3DFMT_P8_UINT_A8_UNORM, so don't offer it either */
2989 case WINED3DFMT_P8_UINT_A8_UNORM:
2990 return FALSE;
2992 /*****
2993 * Supported: (Alpha)-Luminance
2995 case WINED3DFMT_L8_UNORM:
2996 case WINED3DFMT_L8A8_UNORM:
2997 case WINED3DFMT_L16_UNORM:
2998 TRACE_(d3d_caps)("[OK]\n");
2999 return TRUE;
3001 /* Not supported on Windows, thus disabled */
3002 case WINED3DFMT_L4A4_UNORM:
3003 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
3004 return FALSE;
3006 /*****
3007 * Supported: Depth/Stencil formats
3009 case WINED3DFMT_D16_LOCKABLE:
3010 case WINED3DFMT_D16_UNORM:
3011 case WINED3DFMT_S1_UINT_D15_UNORM:
3012 case WINED3DFMT_X8D24_UNORM:
3013 case WINED3DFMT_S4X4_UINT_D24_UNORM:
3014 case WINED3DFMT_D24_UNORM_S8_UINT:
3015 case WINED3DFMT_S8_UINT_D24_FLOAT:
3016 case WINED3DFMT_D32_UNORM:
3017 case WINED3DFMT_D32_FLOAT:
3018 return TRUE;
3020 /*****
3021 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
3022 * GL_NV_texture_shader). Emulated by shaders
3024 case WINED3DFMT_R8G8_SNORM:
3025 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3026 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3027 case WINED3DFMT_R8G8B8A8_SNORM:
3028 case WINED3DFMT_R16G16_SNORM:
3029 /* Ask the shader backend if it can deal with the conversion. If
3030 * we've got a GL extension giving native support this will be an
3031 * identity conversion. */
3032 shader_backend = select_shader_backend(adapter, DeviceType);
3033 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
3035 TRACE_(d3d_caps)("[OK]\n");
3036 return TRUE;
3038 TRACE_(d3d_caps)("[FAILED]\n");
3039 return FALSE;
3041 case WINED3DFMT_DXT1:
3042 case WINED3DFMT_DXT2:
3043 case WINED3DFMT_DXT3:
3044 case WINED3DFMT_DXT4:
3045 case WINED3DFMT_DXT5:
3046 if (gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC])
3048 TRACE_(d3d_caps)("[OK]\n");
3049 return TRUE;
3051 TRACE_(d3d_caps)("[FAILED]\n");
3052 return FALSE;
3055 /*****
3056 * Odd formats - not supported
3058 case WINED3DFMT_VERTEXDATA:
3059 case WINED3DFMT_R16_UINT:
3060 case WINED3DFMT_R32_UINT:
3061 case WINED3DFMT_R16G16B16A16_SNORM:
3062 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM:
3063 case WINED3DFMT_R10G11B11_SNORM:
3064 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3065 return FALSE;
3067 /*****
3068 * WINED3DFMT_R8G8_SNORM_Cx: Not supported right now
3070 case WINED3DFMT_R8G8_SNORM_Cx:
3071 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3072 return FALSE;
3074 /* YUV formats */
3075 case WINED3DFMT_UYVY:
3076 case WINED3DFMT_YUY2:
3077 if (gl_info->supported[APPLE_YCBCR_422])
3079 TRACE_(d3d_caps)("[OK]\n");
3080 return TRUE;
3082 TRACE_(d3d_caps)("[FAILED]\n");
3083 return FALSE;
3084 case WINED3DFMT_YV12:
3085 TRACE_(d3d_caps)("[FAILED]\n");
3086 return FALSE;
3088 /* Not supported */
3089 case WINED3DFMT_R16G16B16A16_UNORM:
3090 case WINED3DFMT_B2G3R3A8_UNORM:
3091 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3092 return FALSE;
3094 /* Floating point formats */
3095 case WINED3DFMT_R16_FLOAT:
3096 case WINED3DFMT_R16G16_FLOAT:
3097 case WINED3DFMT_R16G16B16A16_FLOAT:
3098 if (gl_info->supported[ARB_TEXTURE_FLOAT] && gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3100 TRACE_(d3d_caps)("[OK]\n");
3101 return TRUE;
3103 TRACE_(d3d_caps)("[FAILED]\n");
3104 return FALSE;
3106 case WINED3DFMT_R32_FLOAT:
3107 case WINED3DFMT_R32G32_FLOAT:
3108 case WINED3DFMT_R32G32B32A32_FLOAT:
3109 if (gl_info->supported[ARB_TEXTURE_FLOAT])
3111 TRACE_(d3d_caps)("[OK]\n");
3112 return TRUE;
3114 TRACE_(d3d_caps)("[FAILED]\n");
3115 return FALSE;
3117 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3118 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3119 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3120 * We can do instancing with all shader versions, but we need vertex shaders.
3122 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3123 * to enable instancing. WineD3D doesn't need that and just ignores it.
3125 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3127 case WINED3DFMT_INST:
3128 TRACE("ATI Instancing check hack\n");
3129 if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
3131 TRACE_(d3d_caps)("[OK]\n");
3132 return TRUE;
3134 TRACE_(d3d_caps)("[FAILED]\n");
3135 return FALSE;
3137 /* Some weird FOURCC formats */
3138 case WINED3DFMT_R8G8_B8G8:
3139 case WINED3DFMT_G8R8_G8B8:
3140 case WINED3DFMT_MULTI2_ARGB8:
3141 TRACE_(d3d_caps)("[FAILED]\n");
3142 return FALSE;
3144 /* Vendor specific formats */
3145 case WINED3DFMT_ATI2N:
3146 if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC]
3147 || gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
3149 shader_backend = select_shader_backend(adapter, DeviceType);
3150 fp = select_fragment_implementation(adapter, DeviceType);
3151 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3152 && fp->color_fixup_supported(format_desc->color_fixup))
3154 TRACE_(d3d_caps)("[OK]\n");
3155 return TRUE;
3158 TRACE_(d3d_caps)("[OK]\n");
3159 return TRUE;
3161 TRACE_(d3d_caps)("[FAILED]\n");
3162 return FALSE;
3164 case WINED3DFMT_NVHU:
3165 case WINED3DFMT_NVHS:
3166 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3167 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3168 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3169 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3170 * Applications have to deal with not having NVHS and NVHU.
3172 TRACE_(d3d_caps)("[FAILED]\n");
3173 return FALSE;
3175 case WINED3DFMT_UNKNOWN:
3176 return FALSE;
3178 default:
3179 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3180 break;
3182 return FALSE;
3185 static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
3186 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
3188 const struct blit_shader *blitter;
3190 if(SurfaceType == SURFACE_GDI) {
3191 switch(check_format_desc->format)
3193 case WINED3DFMT_B8G8R8_UNORM:
3194 case WINED3DFMT_B8G8R8A8_UNORM:
3195 case WINED3DFMT_B8G8R8X8_UNORM:
3196 case WINED3DFMT_B5G6R5_UNORM:
3197 case WINED3DFMT_B5G5R5X1_UNORM:
3198 case WINED3DFMT_B5G5R5A1_UNORM:
3199 case WINED3DFMT_B4G4R4A4_UNORM:
3200 case WINED3DFMT_B2G3R3_UNORM:
3201 case WINED3DFMT_A8_UNORM:
3202 case WINED3DFMT_B2G3R3A8_UNORM:
3203 case WINED3DFMT_B4G4R4X4_UNORM:
3204 case WINED3DFMT_R10G10B10A2_UNORM:
3205 case WINED3DFMT_R8G8B8A8_UNORM:
3206 case WINED3DFMT_R8G8B8X8_UNORM:
3207 case WINED3DFMT_R16G16_UNORM:
3208 case WINED3DFMT_B10G10R10A2_UNORM:
3209 case WINED3DFMT_R16G16B16A16_UNORM:
3210 case WINED3DFMT_P8_UINT:
3211 TRACE_(d3d_caps)("[OK]\n");
3212 return TRUE;
3213 default:
3214 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3215 return FALSE;
3219 /* All format that are supported for textures are supported for surfaces as well */
3220 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3221 /* All depth stencil formats are supported on surfaces */
3222 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3224 /* If opengl can't process the format natively, the blitter may be able to convert it */
3225 blitter = select_blit_implementation(adapter, DeviceType);
3226 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
3228 TRACE_(d3d_caps)("[OK]\n");
3229 return TRUE;
3232 /* Reject other formats */
3233 TRACE_(d3d_caps)("[FAILED]\n");
3234 return FALSE;
3237 static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
3239 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3241 if (!gl_info->limits.vertex_samplers)
3243 TRACE_(d3d_caps)("[FAILED]\n");
3244 return FALSE;
3247 switch (format_desc->format)
3249 case WINED3DFMT_R32G32B32A32_FLOAT:
3250 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
3252 TRACE_(d3d_caps)("[FAILED]\n");
3253 return FALSE;
3255 TRACE_(d3d_caps)("[OK]\n");
3256 return TRUE;
3258 default:
3259 TRACE_(d3d_caps)("[FAILED]\n");
3260 return FALSE;
3262 return FALSE;
3265 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3266 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3267 WINED3DSURFTYPE SurfaceType)
3269 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3270 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3271 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3272 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3273 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3274 DWORD UsageCaps = 0;
3276 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3277 This,
3278 Adapter,
3279 DeviceType, debug_d3ddevicetype(DeviceType),
3280 AdapterFormat, debug_d3dformat(AdapterFormat),
3281 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3282 RType, debug_d3dresourcetype(RType),
3283 CheckFormat, debug_d3dformat(CheckFormat));
3285 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3286 return WINED3DERR_INVALIDCALL;
3289 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3291 if(SurfaceType != SURFACE_OPENGL) {
3292 TRACE("[FAILED]\n");
3293 return WINED3DERR_NOTAVAILABLE;
3296 /* Cubetexture allows:
3297 * - D3DUSAGE_AUTOGENMIPMAP
3298 * - D3DUSAGE_DEPTHSTENCIL
3299 * - D3DUSAGE_DYNAMIC
3300 * - D3DUSAGE_NONSECURE (d3d9ex)
3301 * - D3DUSAGE_RENDERTARGET
3302 * - D3DUSAGE_SOFTWAREPROCESSING
3303 * - D3DUSAGE_QUERY_WRAPANDMIP
3305 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3307 /* Check if the texture format is around */
3308 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3310 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3311 /* Check for automatic mipmap generation support */
3312 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3314 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3315 } else {
3316 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3317 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3321 /* Always report dynamic locking */
3322 if(Usage & WINED3DUSAGE_DYNAMIC)
3323 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3325 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3326 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3328 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3329 } else {
3330 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3331 return WINED3DERR_NOTAVAILABLE;
3335 /* Always report software processing */
3336 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3337 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3339 /* Check QUERY_FILTER support */
3340 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3341 if (CheckFilterCapability(adapter, format_desc))
3343 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3344 } else {
3345 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3346 return WINED3DERR_NOTAVAILABLE;
3350 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3351 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3352 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3354 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3355 } else {
3356 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3357 return WINED3DERR_NOTAVAILABLE;
3361 /* Check QUERY_SRGBREAD support */
3362 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3363 if (CheckSrgbReadCapability(adapter, format_desc))
3365 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3366 } else {
3367 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3368 return WINED3DERR_NOTAVAILABLE;
3372 /* Check QUERY_SRGBWRITE support */
3373 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3374 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3376 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3377 } else {
3378 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3379 return WINED3DERR_NOTAVAILABLE;
3383 /* Check QUERY_VERTEXTEXTURE support */
3384 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3385 if (CheckVertexTextureCapability(adapter, format_desc))
3387 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3388 } else {
3389 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3390 return WINED3DERR_NOTAVAILABLE;
3394 /* Check QUERY_WRAPANDMIP support */
3395 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3396 if (CheckWrapAndMipCapability(adapter, format_desc))
3398 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3399 } else {
3400 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3401 return WINED3DERR_NOTAVAILABLE;
3404 } else {
3405 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3406 return WINED3DERR_NOTAVAILABLE;
3408 } else {
3409 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3410 return WINED3DERR_NOTAVAILABLE;
3412 } else if(RType == WINED3DRTYPE_SURFACE) {
3413 /* Surface allows:
3414 * - D3DUSAGE_DEPTHSTENCIL
3415 * - D3DUSAGE_NONSECURE (d3d9ex)
3416 * - D3DUSAGE_RENDERTARGET
3419 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3421 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3422 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3424 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3425 } else {
3426 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3427 return WINED3DERR_NOTAVAILABLE;
3431 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3432 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3434 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3435 } else {
3436 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3437 return WINED3DERR_NOTAVAILABLE;
3441 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3442 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3443 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3445 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3446 } else {
3447 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3448 return WINED3DERR_NOTAVAILABLE;
3451 } else {
3452 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3453 return WINED3DERR_NOTAVAILABLE;
3456 } else if(RType == WINED3DRTYPE_TEXTURE) {
3457 /* Texture allows:
3458 * - D3DUSAGE_AUTOGENMIPMAP
3459 * - D3DUSAGE_DEPTHSTENCIL
3460 * - D3DUSAGE_DMAP
3461 * - D3DUSAGE_DYNAMIC
3462 * - D3DUSAGE_NONSECURE (d3d9ex)
3463 * - D3DUSAGE_RENDERTARGET
3464 * - D3DUSAGE_SOFTWAREPROCESSING
3465 * - D3DUSAGE_TEXTAPI (d3d9ex)
3466 * - D3DUSAGE_QUERY_WRAPANDMIP
3469 if(SurfaceType != SURFACE_OPENGL) {
3470 TRACE("[FAILED]\n");
3471 return WINED3DERR_NOTAVAILABLE;
3474 /* Check if the texture format is around */
3475 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3477 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3478 /* Check for automatic mipmap generation support */
3479 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3481 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3482 } else {
3483 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3484 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3488 /* Always report dynamic locking */
3489 if(Usage & WINED3DUSAGE_DYNAMIC)
3490 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3492 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3493 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3495 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3496 } else {
3497 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3498 return WINED3DERR_NOTAVAILABLE;
3502 /* Always report software processing */
3503 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3504 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3506 /* Check QUERY_FILTER support */
3507 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3508 if (CheckFilterCapability(adapter, format_desc))
3510 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3511 } else {
3512 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3513 return WINED3DERR_NOTAVAILABLE;
3517 /* Check QUERY_LEGACYBUMPMAP support */
3518 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3519 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3521 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3522 } else {
3523 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3524 return WINED3DERR_NOTAVAILABLE;
3528 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3529 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3530 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3532 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3533 } else {
3534 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3535 return WINED3DERR_NOTAVAILABLE;
3539 /* Check QUERY_SRGBREAD support */
3540 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3541 if (CheckSrgbReadCapability(adapter, format_desc))
3543 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3544 } else {
3545 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3546 return WINED3DERR_NOTAVAILABLE;
3550 /* Check QUERY_SRGBWRITE support */
3551 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3552 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3554 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3555 } else {
3556 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3557 return WINED3DERR_NOTAVAILABLE;
3561 /* Check QUERY_VERTEXTEXTURE support */
3562 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3563 if (CheckVertexTextureCapability(adapter, format_desc))
3565 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3566 } else {
3567 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3568 return WINED3DERR_NOTAVAILABLE;
3572 /* Check QUERY_WRAPANDMIP support */
3573 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3574 if (CheckWrapAndMipCapability(adapter, format_desc))
3576 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3577 } else {
3578 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3579 return WINED3DERR_NOTAVAILABLE;
3583 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3584 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3586 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3587 } else {
3588 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
3589 return WINED3DERR_NOTAVAILABLE;
3592 } else {
3593 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3594 return WINED3DERR_NOTAVAILABLE;
3596 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
3597 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
3598 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
3600 * Volumetexture allows:
3601 * - D3DUSAGE_DYNAMIC
3602 * - D3DUSAGE_NONSECURE (d3d9ex)
3603 * - D3DUSAGE_SOFTWAREPROCESSING
3604 * - D3DUSAGE_QUERY_WRAPANDMIP
3607 if(SurfaceType != SURFACE_OPENGL) {
3608 TRACE("[FAILED]\n");
3609 return WINED3DERR_NOTAVAILABLE;
3612 /* Check volume texture and volume usage caps */
3613 if (gl_info->supported[EXT_TEXTURE3D])
3615 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
3617 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
3618 return WINED3DERR_NOTAVAILABLE;
3621 /* Always report dynamic locking */
3622 if(Usage & WINED3DUSAGE_DYNAMIC)
3623 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3625 /* Always report software processing */
3626 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3627 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3629 /* Check QUERY_FILTER support */
3630 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3631 if (CheckFilterCapability(adapter, format_desc))
3633 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3634 } else {
3635 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3636 return WINED3DERR_NOTAVAILABLE;
3640 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3641 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3642 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3644 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3645 } else {
3646 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3647 return WINED3DERR_NOTAVAILABLE;
3651 /* Check QUERY_SRGBREAD support */
3652 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3653 if (CheckSrgbReadCapability(adapter, format_desc))
3655 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3656 } else {
3657 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3658 return WINED3DERR_NOTAVAILABLE;
3662 /* Check QUERY_SRGBWRITE support */
3663 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3664 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3666 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3667 } else {
3668 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3669 return WINED3DERR_NOTAVAILABLE;
3673 /* Check QUERY_VERTEXTEXTURE support */
3674 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3675 if (CheckVertexTextureCapability(adapter, format_desc))
3677 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3678 } else {
3679 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3680 return WINED3DERR_NOTAVAILABLE;
3684 /* Check QUERY_WRAPANDMIP support */
3685 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3686 if (CheckWrapAndMipCapability(adapter, format_desc))
3688 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3689 } else {
3690 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3691 return WINED3DERR_NOTAVAILABLE;
3694 } else {
3695 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3696 return WINED3DERR_NOTAVAILABLE;
3699 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3700 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3701 * app needing one of those formats, don't advertize them to avoid leading apps into
3702 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3703 * except of R32F.
3705 switch(CheckFormat) {
3706 case WINED3DFMT_P8_UINT:
3707 case WINED3DFMT_L4A4_UNORM:
3708 case WINED3DFMT_R32_FLOAT:
3709 case WINED3DFMT_R16_FLOAT:
3710 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3711 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3712 case WINED3DFMT_R16G16_UNORM:
3713 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3714 return WINED3DERR_NOTAVAILABLE;
3716 case WINED3DFMT_R8G8B8A8_SNORM:
3717 case WINED3DFMT_R16G16_SNORM:
3718 if (!gl_info->supported[NV_TEXTURE_SHADER])
3720 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3721 return WINED3DERR_NOTAVAILABLE;
3723 break;
3725 case WINED3DFMT_R8G8_SNORM:
3726 if (!gl_info->supported[NV_TEXTURE_SHADER])
3728 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3729 return WINED3DERR_NOTAVAILABLE;
3731 break;
3733 case WINED3DFMT_DXT1:
3734 case WINED3DFMT_DXT2:
3735 case WINED3DFMT_DXT3:
3736 case WINED3DFMT_DXT4:
3737 case WINED3DFMT_DXT5:
3738 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3739 * compressed texture results in an error. While the D3D refrast does
3740 * support s3tc volumes, at least the nvidia windows driver does not, so
3741 * we're free not to support this format.
3743 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3744 return WINED3DERR_NOTAVAILABLE;
3746 default:
3747 /* Do nothing, continue with checking the format below */
3748 break;
3750 } else if(RType == WINED3DRTYPE_BUFFER){
3751 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3752 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3753 return WINED3DERR_NOTAVAILABLE;
3756 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3757 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3758 * usage flags match. */
3759 if(UsageCaps == Usage) {
3760 return WINED3D_OK;
3761 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3762 return WINED3DOK_NOAUTOGEN;
3763 } else {
3764 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);
3765 return WINED3DERR_NOTAVAILABLE;
3769 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT adapter_idx,
3770 WINED3DDEVTYPE device_type, WINED3DFORMAT src_format, WINED3DFORMAT dst_format)
3772 FIXME("iface %p, adapter_idx %u, device_type %s, src_format %s, dst_format %s stub!\n",
3773 iface, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(src_format),
3774 debug_d3dformat(dst_format));
3776 return WINED3D_OK;
3779 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3780 subset of a D3DCAPS9 structure. However, it has to come via a void *
3781 as the d3d8 interface cannot import the d3d9 header */
3782 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3784 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3785 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3786 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3787 int vs_selected_mode;
3788 int ps_selected_mode;
3789 struct shader_caps shader_caps;
3790 struct fragment_caps fragment_caps;
3791 const shader_backend_t *shader_backend;
3792 const struct fragment_pipeline *frag_pipeline = NULL;
3793 DWORD ckey_caps, blit_caps, fx_caps;
3795 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3797 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3798 return WINED3DERR_INVALIDCALL;
3801 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3803 /* ------------------------------------------------
3804 The following fields apply to both d3d8 and d3d9
3805 ------------------------------------------------ */
3806 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3807 pCaps->AdapterOrdinal = Adapter;
3809 pCaps->Caps = 0;
3810 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3811 WINED3DCAPS2_FULLSCREENGAMMA |
3812 WINED3DCAPS2_DYNAMICTEXTURES;
3813 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3815 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3818 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3819 WINED3DCAPS3_COPY_TO_VIDMEM |
3820 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3822 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3823 WINED3DPRESENT_INTERVAL_ONE;
3825 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3826 WINED3DCURSORCAPS_LOWRES;
3828 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3829 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3830 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3831 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3832 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3833 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3834 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3835 WINED3DDEVCAPS_PUREDEVICE |
3836 WINED3DDEVCAPS_HWRASTERIZATION |
3837 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3838 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3839 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3840 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3841 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3842 WINED3DDEVCAPS_RTPATCHES;
3844 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3845 WINED3DPMISCCAPS_CULLCCW |
3846 WINED3DPMISCCAPS_CULLCW |
3847 WINED3DPMISCCAPS_COLORWRITEENABLE |
3848 WINED3DPMISCCAPS_CLIPTLVERTS |
3849 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3850 WINED3DPMISCCAPS_MASKZ |
3851 WINED3DPMISCCAPS_BLENDOP |
3852 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3853 /* TODO:
3854 WINED3DPMISCCAPS_NULLREFERENCE
3855 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3856 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3857 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3858 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3860 if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
3861 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3863 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3864 WINED3DPRASTERCAPS_PAT |
3865 WINED3DPRASTERCAPS_WFOG |
3866 WINED3DPRASTERCAPS_ZFOG |
3867 WINED3DPRASTERCAPS_FOGVERTEX |
3868 WINED3DPRASTERCAPS_FOGTABLE |
3869 WINED3DPRASTERCAPS_STIPPLE |
3870 WINED3DPRASTERCAPS_SUBPIXEL |
3871 WINED3DPRASTERCAPS_ZTEST |
3872 WINED3DPRASTERCAPS_SCISSORTEST |
3873 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3874 WINED3DPRASTERCAPS_DEPTHBIAS;
3876 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
3878 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3879 WINED3DPRASTERCAPS_ZBIAS |
3880 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3882 if (gl_info->supported[NV_FOG_DISTANCE])
3884 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3886 /* FIXME Add:
3887 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3888 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3889 WINED3DPRASTERCAPS_ANTIALIASEDGES
3890 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3891 WINED3DPRASTERCAPS_WBUFFER */
3893 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3894 WINED3DPCMPCAPS_EQUAL |
3895 WINED3DPCMPCAPS_GREATER |
3896 WINED3DPCMPCAPS_GREATEREQUAL |
3897 WINED3DPCMPCAPS_LESS |
3898 WINED3DPCMPCAPS_LESSEQUAL |
3899 WINED3DPCMPCAPS_NEVER |
3900 WINED3DPCMPCAPS_NOTEQUAL;
3902 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3903 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3904 WINED3DPBLENDCAPS_DESTALPHA |
3905 WINED3DPBLENDCAPS_DESTCOLOR |
3906 WINED3DPBLENDCAPS_INVDESTALPHA |
3907 WINED3DPBLENDCAPS_INVDESTCOLOR |
3908 WINED3DPBLENDCAPS_INVSRCALPHA |
3909 WINED3DPBLENDCAPS_INVSRCCOLOR |
3910 WINED3DPBLENDCAPS_ONE |
3911 WINED3DPBLENDCAPS_SRCALPHA |
3912 WINED3DPBLENDCAPS_SRCALPHASAT |
3913 WINED3DPBLENDCAPS_SRCCOLOR |
3914 WINED3DPBLENDCAPS_ZERO;
3916 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3917 WINED3DPBLENDCAPS_DESTCOLOR |
3918 WINED3DPBLENDCAPS_INVDESTALPHA |
3919 WINED3DPBLENDCAPS_INVDESTCOLOR |
3920 WINED3DPBLENDCAPS_INVSRCALPHA |
3921 WINED3DPBLENDCAPS_INVSRCCOLOR |
3922 WINED3DPBLENDCAPS_ONE |
3923 WINED3DPBLENDCAPS_SRCALPHA |
3924 WINED3DPBLENDCAPS_SRCCOLOR |
3925 WINED3DPBLENDCAPS_ZERO;
3926 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3927 * according to the glBlendFunc manpage
3929 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3930 * legacy settings for srcblend only
3933 if (gl_info->supported[EXT_BLEND_COLOR])
3935 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3936 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3940 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3941 WINED3DPCMPCAPS_EQUAL |
3942 WINED3DPCMPCAPS_GREATER |
3943 WINED3DPCMPCAPS_GREATEREQUAL |
3944 WINED3DPCMPCAPS_LESS |
3945 WINED3DPCMPCAPS_LESSEQUAL |
3946 WINED3DPCMPCAPS_NEVER |
3947 WINED3DPCMPCAPS_NOTEQUAL;
3949 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3950 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3951 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3952 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3953 WINED3DPSHADECAPS_COLORFLATRGB |
3954 WINED3DPSHADECAPS_FOGFLAT |
3955 WINED3DPSHADECAPS_FOGGOURAUD |
3956 WINED3DPSHADECAPS_SPECULARFLATRGB;
3958 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3959 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3960 WINED3DPTEXTURECAPS_TRANSPARENCY |
3961 WINED3DPTEXTURECAPS_BORDER |
3962 WINED3DPTEXTURECAPS_MIPMAP |
3963 WINED3DPTEXTURECAPS_PROJECTED |
3964 WINED3DPTEXTURECAPS_PERSPECTIVE;
3966 if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
3968 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3969 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3972 if (gl_info->supported[EXT_TEXTURE3D])
3974 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3975 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3976 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3979 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3981 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3982 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3983 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3987 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3988 WINED3DPTFILTERCAPS_MAGFPOINT |
3989 WINED3DPTFILTERCAPS_MINFLINEAR |
3990 WINED3DPTFILTERCAPS_MINFPOINT |
3991 WINED3DPTFILTERCAPS_MIPFLINEAR |
3992 WINED3DPTFILTERCAPS_MIPFPOINT |
3993 WINED3DPTFILTERCAPS_LINEAR |
3994 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3995 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3996 WINED3DPTFILTERCAPS_MIPLINEAR |
3997 WINED3DPTFILTERCAPS_MIPNEAREST |
3998 WINED3DPTFILTERCAPS_NEAREST;
4000 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4002 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4003 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4006 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4008 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4009 WINED3DPTFILTERCAPS_MAGFPOINT |
4010 WINED3DPTFILTERCAPS_MINFLINEAR |
4011 WINED3DPTFILTERCAPS_MINFPOINT |
4012 WINED3DPTFILTERCAPS_MIPFLINEAR |
4013 WINED3DPTFILTERCAPS_MIPFPOINT |
4014 WINED3DPTFILTERCAPS_LINEAR |
4015 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4016 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4017 WINED3DPTFILTERCAPS_MIPLINEAR |
4018 WINED3DPTFILTERCAPS_MIPNEAREST |
4019 WINED3DPTFILTERCAPS_NEAREST;
4021 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4023 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4024 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4026 } else
4027 pCaps->CubeTextureFilterCaps = 0;
4029 if (gl_info->supported[EXT_TEXTURE3D])
4031 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4032 WINED3DPTFILTERCAPS_MAGFPOINT |
4033 WINED3DPTFILTERCAPS_MINFLINEAR |
4034 WINED3DPTFILTERCAPS_MINFPOINT |
4035 WINED3DPTFILTERCAPS_MIPFLINEAR |
4036 WINED3DPTFILTERCAPS_MIPFPOINT |
4037 WINED3DPTFILTERCAPS_LINEAR |
4038 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4039 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4040 WINED3DPTFILTERCAPS_MIPLINEAR |
4041 WINED3DPTFILTERCAPS_MIPNEAREST |
4042 WINED3DPTFILTERCAPS_NEAREST;
4043 } else
4044 pCaps->VolumeTextureFilterCaps = 0;
4046 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4047 WINED3DPTADDRESSCAPS_CLAMP |
4048 WINED3DPTADDRESSCAPS_WRAP;
4050 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4052 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4054 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4056 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4058 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4060 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4063 if (gl_info->supported[EXT_TEXTURE3D])
4065 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4066 WINED3DPTADDRESSCAPS_CLAMP |
4067 WINED3DPTADDRESSCAPS_WRAP;
4068 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4070 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4072 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4074 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4076 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4078 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4080 } else
4081 pCaps->VolumeTextureAddressCaps = 0;
4083 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4084 WINED3DLINECAPS_ZTEST |
4085 WINED3DLINECAPS_BLEND |
4086 WINED3DLINECAPS_ALPHACMP |
4087 WINED3DLINECAPS_FOG;
4088 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4089 * idea how generating the smoothing alpha values works; the result is different
4092 pCaps->MaxTextureWidth = gl_info->limits.texture_size;
4093 pCaps->MaxTextureHeight = gl_info->limits.texture_size;
4095 if (gl_info->supported[EXT_TEXTURE3D])
4096 pCaps->MaxVolumeExtent = gl_info->limits.texture3d_size;
4097 else
4098 pCaps->MaxVolumeExtent = 0;
4100 pCaps->MaxTextureRepeat = 32768;
4101 pCaps->MaxTextureAspectRatio = gl_info->limits.texture_size;
4102 pCaps->MaxVertexW = 1.0f;
4104 pCaps->GuardBandLeft = 0.0f;
4105 pCaps->GuardBandTop = 0.0f;
4106 pCaps->GuardBandRight = 0.0f;
4107 pCaps->GuardBandBottom = 0.0f;
4109 pCaps->ExtentsAdjust = 0.0f;
4111 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4112 WINED3DSTENCILCAPS_INCRSAT |
4113 WINED3DSTENCILCAPS_INVERT |
4114 WINED3DSTENCILCAPS_KEEP |
4115 WINED3DSTENCILCAPS_REPLACE |
4116 WINED3DSTENCILCAPS_ZERO;
4117 if (gl_info->supported[EXT_STENCIL_WRAP])
4119 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4120 WINED3DSTENCILCAPS_INCR;
4122 if (gl_info->supported[EXT_STENCIL_TWO_SIDE] || gl_info->supported[ATI_SEPARATE_STENCIL])
4124 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4127 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4129 pCaps->MaxUserClipPlanes = gl_info->limits.clipplanes;
4130 pCaps->MaxActiveLights = gl_info->limits.lights;
4132 pCaps->MaxVertexBlendMatrices = gl_info->limits.blends;
4133 pCaps->MaxVertexBlendMatrixIndex = 0;
4135 pCaps->MaxAnisotropy = gl_info->limits.anisotropy;
4136 pCaps->MaxPointSize = gl_info->limits.pointsize_max;
4139 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4140 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4141 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4142 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4143 WINED3DVTXPCAPS_LOCALVIEWER |
4144 WINED3DVTXPCAPS_VERTEXFOG |
4145 WINED3DVTXPCAPS_TEXGEN;
4147 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4148 pCaps->MaxVertexIndex = 0xFFFFF;
4149 pCaps->MaxStreams = MAX_STREAMS;
4150 pCaps->MaxStreamStride = 1024;
4152 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4153 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4154 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4155 pCaps->MaxNpatchTessellationLevel = 0;
4156 pCaps->MasterAdapterOrdinal = 0;
4157 pCaps->AdapterOrdinalInGroup = 0;
4158 pCaps->NumberOfAdaptersInGroup = 1;
4160 pCaps->NumSimultaneousRTs = gl_info->limits.buffers;
4162 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4163 WINED3DPTFILTERCAPS_MAGFPOINT |
4164 WINED3DPTFILTERCAPS_MINFLINEAR |
4165 WINED3DPTFILTERCAPS_MAGFLINEAR;
4166 pCaps->VertexTextureFilterCaps = 0;
4168 memset(&shader_caps, 0, sizeof(shader_caps));
4169 shader_backend = select_shader_backend(adapter, DeviceType);
4170 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4172 memset(&fragment_caps, 0, sizeof(fragment_caps));
4173 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4174 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
4176 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4177 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4179 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4180 * Ignore shader model capabilities if disabled in config
4182 if(vs_selected_mode == SHADER_NONE) {
4183 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4184 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4185 pCaps->MaxVertexShaderConst = 0;
4186 } else {
4187 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4188 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4191 if(ps_selected_mode == SHADER_NONE) {
4192 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4193 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4194 pCaps->PixelShader1xMaxValue = 0.0f;
4195 } else {
4196 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4197 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4200 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4201 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4202 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4204 pCaps->VS20Caps = shader_caps.VS20Caps;
4205 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4206 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4207 pCaps->PS20Caps = shader_caps.PS20Caps;
4208 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4209 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4211 /* The following caps are shader specific, but they are things we cannot detect, or which
4212 * are the same among all shader models. So to avoid code duplication set the shader version
4213 * specific, but otherwise constant caps here
4215 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4216 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4217 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4218 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4219 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4220 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_vs_temps);
4221 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4223 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4224 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
4226 else if (pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0))
4228 pCaps->VS20Caps.Caps = 0;
4229 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4230 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_vs_temps);
4231 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4233 pCaps->MaxVShaderInstructionsExecuted = 65535;
4234 pCaps->MaxVertexShader30InstructionSlots = 0;
4235 } else { /* VS 1.x */
4236 pCaps->VS20Caps.Caps = 0;
4237 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4238 pCaps->VS20Caps.NumTemps = 0;
4239 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4241 pCaps->MaxVShaderInstructionsExecuted = 0;
4242 pCaps->MaxVertexShader30InstructionSlots = 0;
4245 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4246 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4247 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4249 /* 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 */
4250 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4251 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4252 WINED3DPS20CAPS_PREDICATION |
4253 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4254 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4255 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4256 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_ps_temps);
4257 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4258 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4260 pCaps->MaxPShaderInstructionsExecuted = 65535;
4261 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS,
4262 adapter->gl_info.limits.arb_ps_instructions);
4264 else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0))
4266 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4267 pCaps->PS20Caps.Caps = 0;
4268 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4269 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_ps_temps);
4270 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4271 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4273 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4274 pCaps->MaxPixelShader30InstructionSlots = 0;
4275 } else { /* PS 1.x */
4276 pCaps->PS20Caps.Caps = 0;
4277 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4278 pCaps->PS20Caps.NumTemps = 0;
4279 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4280 pCaps->PS20Caps.NumInstructionSlots = 0;
4282 pCaps->MaxPShaderInstructionsExecuted = 0;
4283 pCaps->MaxPixelShader30InstructionSlots = 0;
4286 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4287 /* OpenGL supports all the formats below, perhaps not always
4288 * without conversion, but it supports them.
4289 * Further GLSL doesn't seem to have an official unsigned type so
4290 * don't advertise it yet as I'm not sure how we handle it.
4291 * We might need to add some clamping in the shader engine to
4292 * support it.
4293 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4294 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4295 WINED3DDTCAPS_UBYTE4N |
4296 WINED3DDTCAPS_SHORT2N |
4297 WINED3DDTCAPS_SHORT4N;
4298 if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
4300 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4301 WINED3DDTCAPS_FLOAT16_4;
4303 } else
4304 pCaps->DeclTypes = 0;
4306 /* Set DirectDraw helper Caps */
4307 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4308 WINEDDCKEYCAPS_SRCBLT;
4309 fx_caps = WINEDDFXCAPS_BLTALPHA |
4310 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4311 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4312 WINEDDFXCAPS_BLTROTATION90 |
4313 WINEDDFXCAPS_BLTSHRINKX |
4314 WINEDDFXCAPS_BLTSHRINKXN |
4315 WINEDDFXCAPS_BLTSHRINKY |
4316 WINEDDFXCAPS_BLTSHRINKXN |
4317 WINEDDFXCAPS_BLTSTRETCHX |
4318 WINEDDFXCAPS_BLTSTRETCHXN |
4319 WINEDDFXCAPS_BLTSTRETCHY |
4320 WINEDDFXCAPS_BLTSTRETCHYN;
4321 blit_caps = WINEDDCAPS_BLT |
4322 WINEDDCAPS_BLTCOLORFILL |
4323 WINEDDCAPS_BLTDEPTHFILL |
4324 WINEDDCAPS_BLTSTRETCH |
4325 WINEDDCAPS_CANBLTSYSMEM |
4326 WINEDDCAPS_CANCLIP |
4327 WINEDDCAPS_CANCLIPSTRETCHED |
4328 WINEDDCAPS_COLORKEY |
4329 WINEDDCAPS_COLORKEYHWASSIST |
4330 WINEDDCAPS_ALIGNBOUNDARYSRC;
4332 /* Fill the ddraw caps structure */
4333 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4334 WINEDDCAPS_PALETTE |
4335 blit_caps;
4336 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4337 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4338 WINEDDCAPS2_PRIMARYGAMMA |
4339 WINEDDCAPS2_WIDESURFACES |
4340 WINEDDCAPS2_CANRENDERWINDOWED;
4341 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4342 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4343 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4344 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4345 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4346 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4347 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4348 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4349 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4351 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4352 WINEDDSCAPS_BACKBUFFER |
4353 WINEDDSCAPS_FLIP |
4354 WINEDDSCAPS_FRONTBUFFER |
4355 WINEDDSCAPS_OFFSCREENPLAIN |
4356 WINEDDSCAPS_PALETTE |
4357 WINEDDSCAPS_PRIMARYSURFACE |
4358 WINEDDSCAPS_SYSTEMMEMORY |
4359 WINEDDSCAPS_VIDEOMEMORY |
4360 WINEDDSCAPS_VISIBLE;
4361 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4363 /* Set D3D caps if OpenGL is available. */
4364 if (adapter->opengl)
4366 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4367 WINEDDSCAPS_MIPMAP |
4368 WINEDDSCAPS_TEXTURE |
4369 WINEDDSCAPS_ZBUFFER;
4370 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4373 return WINED3D_OK;
4376 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT adapter_idx,
4377 WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, IUnknown *parent,
4378 IWineD3DDeviceParent *device_parent, IWineD3DDevice **device)
4380 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4381 IWineD3DDeviceImpl *object;
4382 HRESULT hr;
4384 TRACE("iface %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x.\n"
4385 "parent %p, device_parent %p, device %p.\n",
4386 iface, adapter_idx, device_type, focus_window, flags,
4387 parent, device_parent, device);
4389 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4390 * number and create a device without a 3D adapter for 2D only operation. */
4391 if (IWineD3D_GetAdapterCount(iface) && adapter_idx >= IWineD3D_GetAdapterCount(iface))
4393 return WINED3DERR_INVALIDCALL;
4396 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4397 if (!object)
4399 ERR("Failed to allocate device memory.\n");
4400 return E_OUTOFMEMORY;
4403 hr = device_init(object, This, adapter_idx, device_type, focus_window, flags, parent, device_parent);
4404 if (FAILED(hr))
4406 WARN("Failed to initialize device, hr %#x.\n", hr);
4407 HeapFree(GetProcessHeap(), 0, object);
4408 return hr;
4411 TRACE("Created device %p.\n", object);
4412 *device = (IWineD3DDevice *)object;
4414 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *device);
4416 return WINED3D_OK;
4419 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4420 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4421 IUnknown_AddRef(This->parent);
4422 *pParent = This->parent;
4423 return WINED3D_OK;
4426 static void WINE_GLAPI invalid_func(const void *data)
4428 ERR("Invalid vertex attribute function called\n");
4429 DebugBreak();
4432 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4434 ERR("Invalid texcoord function called\n");
4435 DebugBreak();
4438 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4439 * the extension detection and are used in drawStridedSlow
4441 static void WINE_GLAPI position_d3dcolor(const void *data)
4443 DWORD pos = *((const DWORD *)data);
4445 FIXME("Add a test for fixed function position from d3dcolor type\n");
4446 glVertex4s(D3DCOLOR_B_R(pos),
4447 D3DCOLOR_B_G(pos),
4448 D3DCOLOR_B_B(pos),
4449 D3DCOLOR_B_A(pos));
4452 static void WINE_GLAPI position_float4(const void *data)
4454 const GLfloat *pos = data;
4456 if (pos[3] != 0.0f && pos[3] != 1.0f)
4458 float w = 1.0f / pos[3];
4460 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4462 else
4464 glVertex3fv(pos);
4468 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4470 DWORD diffuseColor = *((const DWORD *)data);
4472 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4473 D3DCOLOR_B_G(diffuseColor),
4474 D3DCOLOR_B_B(diffuseColor),
4475 D3DCOLOR_B_A(diffuseColor));
4478 static void WINE_GLAPI specular_d3dcolor(const void *data)
4480 DWORD specularColor = *((const DWORD *)data);
4481 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4482 D3DCOLOR_B_G(specularColor),
4483 D3DCOLOR_B_B(specularColor)};
4485 specular_func_3ubv(d);
4488 static void WINE_GLAPI warn_no_specular_func(const void *data)
4490 WARN("GL_EXT_secondary_color not supported\n");
4493 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4495 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4496 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4497 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4498 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4499 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4500 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4501 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4502 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4503 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4504 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4505 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4506 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4507 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4508 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4509 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4510 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4511 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4513 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4514 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4515 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4516 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4517 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4518 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4519 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4520 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4521 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4522 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4523 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4524 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4525 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4526 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4527 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4528 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4529 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4531 /* No 4 component entry points here */
4532 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4533 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4534 if (gl_info->supported[EXT_SECONDARY_COLOR])
4536 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4538 else
4540 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4542 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4543 if (gl_info->supported[EXT_SECONDARY_COLOR])
4545 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4546 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4548 else
4550 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4552 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4553 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4554 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4555 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4556 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4557 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4558 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4559 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4560 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4561 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4562 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4563 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4565 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4566 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4568 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4569 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4570 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4571 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4572 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4573 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4574 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4575 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4576 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4577 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4578 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4579 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4580 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4581 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4582 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4583 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4584 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4586 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4587 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4588 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4589 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4590 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4591 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4592 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4593 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4594 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4595 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4596 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4597 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4598 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4599 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4600 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4601 if (gl_info->supported[NV_HALF_FLOAT])
4603 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4604 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4605 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4606 } else {
4607 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4608 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4612 BOOL InitAdapters(IWineD3DImpl *This)
4614 static HMODULE mod_gl;
4615 BOOL ret;
4616 int ps_selected_mode, vs_selected_mode;
4618 /* No need to hold any lock. The calling library makes sure only one thread calls
4619 * wined3d simultaneously
4622 TRACE("Initializing adapters\n");
4624 if(!mod_gl) {
4625 #ifdef USE_WIN32_OPENGL
4626 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4627 mod_gl = LoadLibraryA("opengl32.dll");
4628 if(!mod_gl) {
4629 ERR("Can't load opengl32.dll!\n");
4630 goto nogl_adapter;
4632 #else
4633 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4634 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4635 mod_gl = GetModuleHandleA("gdi32.dll");
4636 #endif
4639 /* Load WGL core functions from opengl32.dll */
4640 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4641 WGL_FUNCS_GEN;
4642 #undef USE_WGL_FUNC
4644 if(!pwglGetProcAddress) {
4645 ERR("Unable to load wglGetProcAddress!\n");
4646 goto nogl_adapter;
4649 /* Dynamically load all GL core functions */
4650 GL_FUNCS_GEN;
4651 #undef USE_GL_FUNC
4653 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4654 * otherwise because we have to use winex11.drv's override
4656 #ifdef USE_WIN32_OPENGL
4657 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4658 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4659 #else
4660 wglFinish = (void*)pwglGetProcAddress("wglFinish");
4661 wglFlush = (void*)pwglGetProcAddress("wglFlush");
4662 #endif
4664 glEnableWINE = glEnable;
4665 glDisableWINE = glDisable;
4667 /* For now only one default adapter */
4669 struct wined3d_adapter *adapter = &This->adapters[0];
4670 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4671 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
4672 int iPixelFormat;
4673 int res;
4674 int i;
4675 WineD3D_PixelFormat *cfgs;
4676 DISPLAY_DEVICEW DisplayDevice;
4677 HDC hdc;
4679 TRACE("Initializing default adapter\n");
4680 adapter->ordinal = 0;
4681 adapter->monitorPoint.x = -1;
4682 adapter->monitorPoint.y = -1;
4684 if (!AllocateLocallyUniqueId(&adapter->luid))
4686 DWORD err = GetLastError();
4687 ERR("Failed to set adapter LUID (%#x).\n", err);
4688 goto nogl_adapter;
4690 TRACE("Allocated LUID %08x:%08x for adapter.\n",
4691 adapter->luid.HighPart, adapter->luid.LowPart);
4693 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
4695 ERR("Failed to get a gl context for default adapter\n");
4696 goto nogl_adapter;
4699 ret = IWineD3DImpl_FillGLCaps(&adapter->driver_info, &adapter->gl_info);
4700 if(!ret) {
4701 ERR("Failed to initialize gl caps for default adapter\n");
4702 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4703 goto nogl_adapter;
4705 ret = initPixelFormats(&adapter->gl_info, adapter->driver_info.vendor);
4706 if(!ret) {
4707 ERR("Failed to init gl formats\n");
4708 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4709 goto nogl_adapter;
4712 hdc = fake_gl_ctx.dc;
4714 /* Use the VideoRamSize registry setting when set */
4715 if(wined3d_settings.emulated_textureram)
4716 adapter->TextureRam = wined3d_settings.emulated_textureram;
4717 else
4718 adapter->TextureRam = adapter->gl_info.vidmem;
4719 adapter->UsedTextureRam = 0;
4720 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4722 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4723 DisplayDevice.cb = sizeof(DisplayDevice);
4724 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4725 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4726 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4728 if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
4730 int attribute;
4731 int attribs[10];
4732 int values[10];
4733 int nAttribs = 0;
4735 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4736 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4738 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4739 cfgs = adapter->cfgs;
4740 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4741 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4742 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4743 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4744 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4745 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4746 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4747 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4748 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4749 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4751 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4753 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4755 if(!res)
4756 continue;
4758 /* Cache the pixel format */
4759 cfgs->iPixelFormat = iPixelFormat;
4760 cfgs->redSize = values[0];
4761 cfgs->greenSize = values[1];
4762 cfgs->blueSize = values[2];
4763 cfgs->alphaSize = values[3];
4764 cfgs->depthSize = values[4];
4765 cfgs->stencilSize = values[5];
4766 cfgs->windowDrawable = values[6];
4767 cfgs->iPixelType = values[7];
4768 cfgs->doubleBuffer = values[8];
4769 cfgs->auxBuffers = values[9];
4771 cfgs->pbufferDrawable = FALSE;
4772 /* Check for pbuffer support when it is around as
4773 * wglGetPixelFormatAttribiv fails for unknown attributes. */
4774 if (gl_info->supported[WGL_ARB_PBUFFER])
4776 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4777 int value;
4778 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4779 cfgs->pbufferDrawable = value;
4782 cfgs->numSamples = 0;
4783 /* Check multisample support */
4784 if (gl_info->supported[ARB_MULTISAMPLE])
4786 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4787 int value[2];
4788 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4789 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4790 * value[1] = number of multi sample buffers*/
4791 if(value[0])
4792 cfgs->numSamples = value[1];
4796 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
4797 cfgs++;
4800 else
4802 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4803 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4804 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4806 cfgs = adapter->cfgs;
4807 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4809 PIXELFORMATDESCRIPTOR ppfd;
4811 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4812 if(!res)
4813 continue;
4815 /* We only want HW acceleration using an OpenGL ICD driver.
4816 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4817 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4819 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4821 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4822 continue;
4825 cfgs->iPixelFormat = iPixelFormat;
4826 cfgs->redSize = ppfd.cRedBits;
4827 cfgs->greenSize = ppfd.cGreenBits;
4828 cfgs->blueSize = ppfd.cBlueBits;
4829 cfgs->alphaSize = ppfd.cAlphaBits;
4830 cfgs->depthSize = ppfd.cDepthBits;
4831 cfgs->stencilSize = ppfd.cStencilBits;
4832 cfgs->pbufferDrawable = 0;
4833 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4834 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4835 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4836 cfgs->auxBuffers = ppfd.cAuxBuffers;
4837 cfgs->numSamples = 0;
4839 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
4840 cfgs++;
4841 adapter->nCfgs++;
4844 /* 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 */
4845 if(!adapter->nCfgs)
4847 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4849 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4850 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4851 goto nogl_adapter;
4855 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4856 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4857 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4858 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4859 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4860 * driver is allowed to consume more bits EXCEPT for stencil bits.
4862 * Mark an adapter with this broken stencil behavior.
4864 adapter->brokenStencil = TRUE;
4865 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4867 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4868 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4869 adapter->brokenStencil = FALSE;
4870 break;
4874 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4876 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
4877 fillGLAttribFuncs(&adapter->gl_info);
4878 adapter->opengl = TRUE;
4880 This->adapter_count = 1;
4881 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4883 return TRUE;
4885 nogl_adapter:
4886 /* Initialize an adapter for ddraw-only memory counting */
4887 memset(This->adapters, 0, sizeof(This->adapters));
4888 This->adapters[0].ordinal = 0;
4889 This->adapters[0].opengl = FALSE;
4890 This->adapters[0].monitorPoint.x = -1;
4891 This->adapters[0].monitorPoint.y = -1;
4893 This->adapters[0].driver_info.name = "Display";
4894 This->adapters[0].driver_info.description = "WineD3D DirectDraw Emulation";
4895 if(wined3d_settings.emulated_textureram) {
4896 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4897 } else {
4898 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4901 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4903 This->adapter_count = 1;
4904 return FALSE;
4907 /**********************************************************
4908 * IWineD3D VTbl follows
4909 **********************************************************/
4911 const IWineD3DVtbl IWineD3D_Vtbl =
4913 /* IUnknown */
4914 IWineD3DImpl_QueryInterface,
4915 IWineD3DImpl_AddRef,
4916 IWineD3DImpl_Release,
4917 /* IWineD3D */
4918 IWineD3DImpl_GetParent,
4919 IWineD3DImpl_GetAdapterCount,
4920 IWineD3DImpl_RegisterSoftwareDevice,
4921 IWineD3DImpl_GetAdapterMonitor,
4922 IWineD3DImpl_GetAdapterModeCount,
4923 IWineD3DImpl_EnumAdapterModes,
4924 IWineD3DImpl_GetAdapterDisplayMode,
4925 IWineD3DImpl_GetAdapterIdentifier,
4926 IWineD3DImpl_CheckDeviceMultiSampleType,
4927 IWineD3DImpl_CheckDepthStencilMatch,
4928 IWineD3DImpl_CheckDeviceType,
4929 IWineD3DImpl_CheckDeviceFormat,
4930 IWineD3DImpl_CheckDeviceFormatConversion,
4931 IWineD3DImpl_GetDeviceCaps,
4932 IWineD3DImpl_CreateDevice
4935 static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
4937 const struct wined3d_parent_ops wined3d_null_parent_ops =
4939 wined3d_null_wined3d_object_destroyed,