VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/directx.c@ 33280

Last change on this file since 33280 was 33280, checked in by vboxsync, 14 years ago

crOpenGL/wddm: disable partial blits for hd4800 only

  • Property svn:eol-style set to native
File size: 233.8 KB
Line 
1/*
2 * IWineD3D implementation
3 *
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
10 *
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.
15 *
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.
20 *
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
24 */
25
26/*
27 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
28 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
29 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
30 * a choice of LGPL license versions is made available with the language indicating
31 * that LGPLv2 or any later version may be used, or where a choice of which version
32 * of the LGPL is applied is otherwise unspecified.
33 */
34
35#include "config.h"
36#include <stdio.h>
37#include "wined3d_private.h"
38
39WINE_DEFAULT_DEBUG_CHANNEL(d3d);
40WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
41
42#define GLINFO_LOCATION (*gl_info)
43#define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024)
44
45/* The d3d device ID */
46static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
47
48/* Extension detection */
49static const struct {
50 const char *extension_string;
51 GL_SupportedExt extension;
52 DWORD version;
53} EXTENSION_MAP[] = {
54 /* APPLE */
55 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
56 {"GL_APPLE_fence", APPLE_FENCE, 0 },
57 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
58 {"GL_APPLE_flush_buffer_range", APPLE_FLUSH_BUFFER_RANGE, 0 },
59 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
60 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
61
62 /* ARB */
63 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
64 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
65 {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP, 0 },
66 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
67 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
68 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
69 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
70 {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT, 0 },
71 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
72 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
73 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
74 {"GL_ARB_imaging", ARB_IMAGING, 0 },
75 {"GL_ARB_map_buffer_range", ARB_MAP_BUFFER_RANGE, 0 },
76 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
77 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
78 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
79 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
80 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
81 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
82 {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX, 0 },
83 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
84 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
85 {"GL_ARB_shading_language_100", ARB_SHADING_LANGUAGE_100, 0 },
86 {"GL_ARB_sync", ARB_SYNC, 0 },
87 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
88 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
89 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
90 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
91 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
92 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
93 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
94 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
95 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
96 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
97 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
98 {"GL_ARB_vertex_array_bgra", ARB_VERTEX_ARRAY_BGRA, 0 },
99 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
100 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
101 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
102 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
103
104 /* ATI */
105 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
106 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
107 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
108 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
109 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
110
111 /* EXT */
112 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
113 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
114 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
115 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
116 {"GL_EXT_draw_buffers2", EXT_DRAW_BUFFERS2, 0 },
117 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
118 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
119 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
120 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
121 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
122 {"GL_EXT_gpu_shader4", EXT_GPU_SHADER4, 0 },
123 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
124 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
125 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
126 {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 },
127 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
128 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
129 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
130 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
131 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
132 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
133 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
134 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
135 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
136 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
137 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
138 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
139 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
140
141 /* NV */
142 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
143 {"GL_NV_fence", NV_FENCE, 0 },
144 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
145 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
146 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
147 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
148 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
149 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
150 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
151 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
152 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
153 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
154 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
155 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
156 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
157 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
158 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
159 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
160 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
161
162 /* SGI */
163 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
164};
165
166/**********************************************************
167 * Utility functions follow
168 **********************************************************/
169
170static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
171
172const struct min_lookup minMipLookup[] =
173{
174 /* NONE POINT LINEAR */
175 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
176 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
177 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
178};
179
180const struct min_lookup minMipLookup_noFilter[] =
181{
182 /* NONE POINT LINEAR */
183 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
184 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
185 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
186};
187
188const struct min_lookup minMipLookup_noMip[] =
189{
190 /* NONE POINT LINEAR */
191 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
192 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
193 {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */
194};
195
196const GLenum magLookup[] =
197{
198 /* NONE POINT LINEAR */
199 GL_NEAREST, GL_NEAREST, GL_LINEAR,
200};
201
202const GLenum magLookup_noFilter[] =
203{
204 /* NONE POINT LINEAR */
205 GL_NEAREST, GL_NEAREST, GL_NEAREST,
206};
207
208/* drawStridedSlow attributes */
209glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
210glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
211glAttribFunc specular_func_3ubv;
212glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
213glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
214glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
215
216/**
217 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
218 * i.e., there is no GL Context - Get a default rendering context to enable the
219 * function query some info from GL.
220 */
221
222struct wined3d_fake_gl_ctx
223{
224 HDC dc;
225 HWND wnd;
226 HGLRC gl_ctx;
227 HDC restore_dc;
228 HGLRC restore_gl_ctx;
229};
230
231static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
232{
233 TRACE_(d3d_caps)("Destroying fake GL context.\n");
234
235 if (!pwglMakeCurrent(NULL, NULL))
236 {
237 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
238 }
239
240 if (!pwglDeleteContext(ctx->gl_ctx))
241 {
242 DWORD err = GetLastError();
243 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
244 }
245
246 ReleaseDC(ctx->wnd, ctx->dc);
247 DestroyWindow(ctx->wnd);
248
249 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
250 {
251 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
252 }
253}
254
255static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
256{
257 PIXELFORMATDESCRIPTOR pfd;
258 int iPixelFormat;
259
260 TRACE("getting context...\n");
261
262 ctx->restore_dc = pwglGetCurrentDC();
263 ctx->restore_gl_ctx = pwglGetCurrentContext();
264
265 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
266 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
267 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
268 if (!ctx->wnd)
269 {
270 ERR_(d3d_caps)("Failed to create a window.\n");
271 goto fail;
272 }
273
274 ctx->dc = GetDC(ctx->wnd);
275 if (!ctx->dc)
276 {
277 ERR_(d3d_caps)("Failed to get a DC.\n");
278 goto fail;
279 }
280
281 /* PixelFormat selection */
282 ZeroMemory(&pfd, sizeof(pfd));
283 pfd.nSize = sizeof(pfd);
284 pfd.nVersion = 1;
285 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
286 pfd.iPixelType = PFD_TYPE_RGBA;
287 pfd.cColorBits = 32;
288 pfd.iLayerType = PFD_MAIN_PLANE;
289
290 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
291 if (!iPixelFormat)
292 {
293 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
294 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
295 goto fail;
296 }
297 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
298 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
299
300 /* Create a GL context. */
301 ctx->gl_ctx = pwglCreateContext(ctx->dc);
302 if (!ctx->gl_ctx)
303 {
304 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
305 goto fail;
306 }
307
308 /* Make it the current GL context. */
309 if (!context_set_current(NULL))
310 {
311 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
312 }
313
314 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
315 {
316 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
317 goto fail;
318 }
319
320 return TRUE;
321
322fail:
323 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
324 ctx->gl_ctx = NULL;
325 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
326 ctx->dc = NULL;
327 if (ctx->wnd) DestroyWindow(ctx->wnd);
328 ctx->wnd = NULL;
329 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
330 {
331 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
332 }
333
334 return FALSE;
335}
336
337/* Adjust the amount of used texture memory */
338long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram)
339{
340 struct wined3d_adapter *adapter = D3DDevice->adapter;
341
342 adapter->UsedTextureRam += glram;
343 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
344 return adapter->UsedTextureRam;
345}
346
347static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
348{
349 HeapFree(GetProcessHeap(), 0, adapter->gl_info.gl_formats);
350 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
351}
352
353/**********************************************************
354 * IUnknown parts follows
355 **********************************************************/
356
357static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
358{
359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
360
361 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
362 if (IsEqualGUID(riid, &IID_IUnknown)
363 || IsEqualGUID(riid, &IID_IWineD3DBase)
364 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
365 IUnknown_AddRef(iface);
366 *ppobj = This;
367 return S_OK;
368 }
369 *ppobj = NULL;
370 return E_NOINTERFACE;
371}
372
373static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
374 IWineD3DImpl *This = (IWineD3DImpl *)iface;
375 ULONG refCount = InterlockedIncrement(&This->ref);
376
377 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
378 return refCount;
379}
380
381static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
382 IWineD3DImpl *This = (IWineD3DImpl *)iface;
383 ULONG ref;
384 TRACE("(%p) : Releasing from %d\n", This, This->ref);
385 ref = InterlockedDecrement(&This->ref);
386 if (ref == 0) {
387 unsigned int i;
388
389 for (i = 0; i < This->adapter_count; ++i)
390 {
391 wined3d_adapter_cleanup(&This->adapters[i]);
392 }
393 HeapFree(GetProcessHeap(), 0, This);
394 }
395
396 return ref;
397}
398
399/**********************************************************
400 * IWineD3D parts follows
401 **********************************************************/
402
403/* GL locking is done by the caller */
404static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
405{
406 GLuint prog;
407 BOOL ret = FALSE;
408 const char *testcode =
409 "!!ARBvp1.0\n"
410 "PARAM C[66] = { program.env[0..65] };\n"
411 "ADDRESS A0;"
412 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
413 "ARL A0.x, zero.x;\n"
414 "MOV result.position, C[A0.x + 65];\n"
415 "END\n";
416
417 while(glGetError());
418 GL_EXTCALL(glGenProgramsARB(1, &prog));
419 if(!prog) {
420 ERR("Failed to create an ARB offset limit test program\n");
421 }
422 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
423 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
424 strlen(testcode), testcode));
425 if(glGetError() != 0) {
426 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
427 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
428 ret = TRUE;
429 } else TRACE("OpenGL implementation allows offsets > 63\n");
430
431 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
432 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
433 checkGLcall("ARB vp offset limit test cleanup");
434
435 return ret;
436}
437
438static DWORD ver_for_ext(GL_SupportedExt ext)
439{
440 unsigned int i;
441 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
442 if(EXTENSION_MAP[i].extension == ext) {
443 return EXTENSION_MAP[i].version;
444 }
445 }
446 return 0;
447}
448
449static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
450 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
451{
452 if (card_vendor != HW_VENDOR_ATI) return FALSE;
453 if (device == CARD_ATI_RADEON_9500) return TRUE;
454 if (device == CARD_ATI_RADEON_X700) return TRUE;
455 if (device == CARD_ATI_RADEON_X1600) return TRUE;
456 return FALSE;
457}
458
459static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
460 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
461{
462 if (card_vendor == HW_VENDOR_NVIDIA)
463 {
464 if (device == CARD_NVIDIA_GEFORCEFX_5800 || device == CARD_NVIDIA_GEFORCEFX_5600)
465 {
466 return TRUE;
467 }
468 }
469 return FALSE;
470}
471
472static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
473 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
474{
475 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
476 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
477 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
478 *
479 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
480 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
481 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
482 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
483 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
484 * the chance that other implementations support them is rather small since Win32 QuickTime uses
485 * DirectDraw, not OpenGL.
486 *
487 * This test has been moved into wined3d_guess_gl_vendor()
488 */
489 if (gl_vendor == GL_VENDOR_APPLE)
490 {
491 return TRUE;
492 }
493 return FALSE;
494}
495
496/* Context activation is done by the caller. */
497static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
498{
499 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
500 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
501 * all the texture. This function detects this bug by its symptom and disables PBOs
502 * if the test fails.
503 *
504 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
505 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
506 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
507 * read back is compared to the original. If they are equal PBOs are assumed to work,
508 * otherwise the PBO extension is disabled. */
509 GLuint texture, pbo;
510 static const unsigned int pattern[] =
511 {
512 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
513 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
514 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
515 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
516 };
517 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
518
519 /* No PBO -> No point in testing them. */
520 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
521
522 ENTER_GL();
523
524 while (glGetError());
525 glGenTextures(1, &texture);
526 glBindTexture(GL_TEXTURE_2D, texture);
527
528 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
529 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
530 checkGLcall("Specifying the PBO test texture");
531
532 GL_EXTCALL(glGenBuffersARB(1, &pbo));
533 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
534 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
535 checkGLcall("Specifying the PBO test pbo");
536
537 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
538 checkGLcall("Loading the PBO test texture");
539
540 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
541 wglFinish(); /* just to be sure */
542
543 memset(check, 0, sizeof(check));
544 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
545 checkGLcall("Reading back the PBO test texture");
546
547 glDeleteTextures(1, &texture);
548 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
549 checkGLcall("PBO test cleanup");
550
551 LEAVE_GL();
552
553 if (memcmp(check, pattern, sizeof(check)))
554 {
555 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
556 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
557 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
558 }
559 else
560 {
561 TRACE_(d3d_caps)("PBO test successful.\n");
562 }
563}
564
565static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
566 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
567{
568 return (card_vendor == HW_VENDOR_INTEL) && (gl_vendor == GL_VENDOR_APPLE);
569}
570
571static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
572 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
573{
574 if (gl_vendor != GL_VENDOR_APPLE) return FALSE;
575 if (card_vendor != HW_VENDOR_ATI) return FALSE;
576 if (device == CARD_ATI_RADEON_X1600) return FALSE;
577 return TRUE;
578}
579
580static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
581 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
582{
583 return gl_vendor == GL_VENDOR_FGLRX;
584
585}
586
587static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
588 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
589{
590 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
591 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
592 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
593 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
594 * hardcoded
595 *
596 * dx10 cards usually have 64 varyings */
597 return gl_info->limits.glsl_varyings > 44;
598}
599
600/* A GL context is provided by the caller */
601static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
602 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
603{
604 GLenum error;
605 DWORD data[16];
606
607 if (!gl_info->supported[EXT_SECONDARY_COLOR]) return FALSE;
608
609 ENTER_GL();
610 while(glGetError());
611 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
612 error = glGetError();
613 LEAVE_GL();
614
615 if(error == GL_NO_ERROR)
616 {
617 TRACE("GL Implementation accepts 4 component specular color pointers\n");
618 return TRUE;
619 }
620 else
621 {
622 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
623 debug_glerror(error));
624 return FALSE;
625 }
626}
627
628static BOOL match_apple_nvts(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
629 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
630{
631 if (!match_apple(gl_info, gl_renderer, gl_vendor, card_vendor, device)) return FALSE;
632 return gl_info->supported[NV_TEXTURE_SHADER];
633}
634
635/* A GL context is provided by the caller */
636static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
637 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
638{
639 GLuint prog;
640 BOOL ret = FALSE;
641 GLint pos;
642 const char *testcode =
643 "!!ARBvp1.0\n"
644 "OPTION NV_vertex_program2;\n"
645 "MOV result.clip[0], 0.0;\n"
646 "MOV result.position, 0.0;\n"
647 "END\n";
648
649 if (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]) return FALSE;
650
651 ENTER_GL();
652 while(glGetError());
653
654 GL_EXTCALL(glGenProgramsARB(1, &prog));
655 if(!prog)
656 {
657 ERR("Failed to create the NVvp clip test program\n");
658 LEAVE_GL();
659 return FALSE;
660 }
661 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
662 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
663 strlen(testcode), testcode));
664 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
665 if(pos != -1)
666 {
667 WARN("GL_NV_vertex_program2_option result.clip[] test failed\n");
668 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
669 ret = TRUE;
670 while(glGetError());
671 }
672 else TRACE("GL_NV_vertex_program2_option result.clip[] test passed\n");
673
674 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
675 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
676 checkGLcall("GL_NV_vertex_program2_option result.clip[] test cleanup");
677
678 LEAVE_GL();
679 return ret;
680}
681
682/* Context activation is done by the caller. */
683static BOOL match_fbo_tex_update(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
684 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
685{
686 char data[4 * 4 * 4];
687 GLuint tex, fbo;
688 GLenum status;
689
690 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return FALSE;
691
692 memset(data, 0xcc, sizeof(data));
693
694 ENTER_GL();
695
696 glGenTextures(1, &tex);
697 glBindTexture(GL_TEXTURE_2D, tex);
698 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
699 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
700 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
701 checkGLcall("glTexImage2D");
702
703 gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
704 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
705 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
706 checkGLcall("glFramebufferTexture2D");
707
708 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
709 if (status != GL_FRAMEBUFFER_COMPLETE) ERR("FBO status %#x\n", status);
710 checkGLcall("glCheckFramebufferStatus");
711
712 memset(data, 0x11, sizeof(data));
713 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
714 checkGLcall("glTexSubImage2D");
715
716 glClearColor(0.996, 0.729, 0.745, 0.792);
717 glClear(GL_COLOR_BUFFER_BIT);
718 checkGLcall("glClear");
719
720 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
721 checkGLcall("glGetTexImage");
722
723 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
724 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
725 glBindTexture(GL_TEXTURE_2D, 0);
726 checkGLcall("glBindTexture");
727
728 gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
729 glDeleteTextures(1, &tex);
730 checkGLcall("glDeleteTextures");
731
732 LEAVE_GL();
733
734 return *(DWORD *)data == 0x11111111;
735}
736
737static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
738{
739 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->limits.arb_vs_native_constants);
740 gl_info->limits.glsl_vs_float_constants = gl_info->limits.arb_vs_native_constants;
741 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->limits.arb_ps_native_constants);
742 gl_info->limits.glsl_ps_float_constants = gl_info->limits.arb_ps_native_constants;
743}
744
745static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
746{
747 quirk_arb_constants(gl_info);
748 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
749 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
750 * allow 48 different offsets or other helper immediate values. */
751 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
752 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
753}
754
755/* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
756 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
757 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
758 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
759 * most games, but avoids the crash
760 *
761 * A more sophisticated way would be to find all units that need texture coordinates and enable
762 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
763 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
764 *
765 * Note that disabling the extension entirely does not gain predictability because there is no point
766 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
767static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
768{
769 if (gl_info->supported[ARB_POINT_SPRITE])
770 {
771 TRACE("Limiting point sprites to one texture unit.\n");
772 gl_info->limits.point_sprite_units = 1;
773 }
774}
775
776static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
777{
778 quirk_arb_constants(gl_info);
779
780 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
781 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
782 * If real NP2 textures are used, the driver falls back to software. We could just remove the
783 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
784 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
785 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
786 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
787 *
788 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
789 * has this extension promoted to core. The extension loading code sets this extension supported
790 * due to that, so this code works on fglrx as well. */
791 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
792 {
793 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
794 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
795 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
796 }
797
798 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
799 * it is generally more efficient. Reserve just 8 constants. */
800 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
801 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
802}
803
804static void quirk_no_np2(struct wined3d_gl_info *gl_info)
805{
806 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
807 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
808 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
809 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
810 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
811 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
812 *
813 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
814 * triggering the software fallback. There is not much we can do here apart from disabling the
815 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
816 * in IWineD3DImpl_FillGLCaps).
817 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
818 * post-processing effects in the game "Max Payne 2").
819 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
820 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
821 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
822 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
823}
824
825static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
826{
827 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
828 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
829 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
830 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
831 * according to the spec.
832 *
833 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
834 * makes the shader slower and eats instruction slots which should be available to the d3d app.
835 *
836 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
837 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
838 * this workaround is activated on cards that do not need it, it won't break things, just affect
839 * performance negatively. */
840 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
841 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
842}
843
844static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
845{
846 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
847}
848
849static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
850{
851 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
852}
853
854static void quirk_apple_nvts(struct wined3d_gl_info *gl_info)
855{
856 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
857 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
858}
859
860static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info)
861{
862 gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN;
863}
864
865static void quirk_fbo_tex_update(struct wined3d_gl_info *gl_info)
866{
867 gl_info->quirks |= WINED3D_QUIRK_FBO_TEX_UPDATE;
868}
869
870static BOOL match_ati_hd4800(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
871 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
872{
873 if (card_vendor != HW_VENDOR_ATI) return FALSE;
874 if (device == CARD_ATI_RADEON_HD4800) return TRUE;
875 return FALSE;
876}
877
878static void quirk_fullsize_blit(struct wined3d_gl_info *gl_info)
879{
880 gl_info->quirks |= WINED3D_QUIRK_FULLSIZE_BLIT;
881}
882
883struct driver_quirk
884{
885 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
886 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device);
887 void (*apply)(struct wined3d_gl_info *gl_info);
888 const char *description;
889};
890
891static const struct driver_quirk quirk_table[] =
892{
893 {
894 match_ati_r300_to_500,
895 quirk_ati_dx9,
896 "ATI GLSL constant and normalized texrect quirk"
897 },
898 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
899 * used it falls back to software. While the compiler can detect if the shader uses all declared
900 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
901 * using relative addressing falls back to software.
902 *
903 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
904 {
905 match_apple,
906 quirk_apple_glsl_constants,
907 "Apple GLSL uniform override"
908 },
909 {
910 match_geforce5,
911 quirk_no_np2,
912 "Geforce 5 NP2 disable"
913 },
914 {
915 match_apple_intel,
916 quirk_texcoord_w,
917 "Init texcoord .w for Apple Intel GPU driver"
918 },
919 {
920 match_apple_nonr500ati,
921 quirk_texcoord_w,
922 "Init texcoord .w for Apple ATI >= r600 GPU driver"
923 },
924 {
925 match_fglrx,
926 quirk_one_point_sprite,
927 "Fglrx point sprite crash workaround"
928 },
929 {
930 match_dx10_capable,
931 quirk_clip_varying,
932 "Reserved varying for gl_ClipPos"
933 },
934 {
935 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
936 * GL implementations accept it. The Mac GL is the only implementation known to
937 * reject it.
938 *
939 * If we can pass 4 component specular colors, do it, because (a) we don't have
940 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
941 * passes specular alpha to the pixel shader if any is used. Otherwise the
942 * specular alpha is used to pass the fog coordinate, which we pass to opengl
943 * via GL_EXT_fog_coord.
944 */
945 match_allows_spec_alpha,
946 quirk_allows_specular_alpha,
947 "Allow specular alpha quirk"
948 },
949 {
950 /* The pixel formats provided by GL_NV_texture_shader are broken on OSX
951 * (rdar://5682521).
952 */
953 match_apple_nvts,
954 quirk_apple_nvts,
955 "Apple NV_texture_shader disable"
956 },
957 {
958 match_broken_nv_clip,
959 quirk_disable_nvvp_clip,
960 "Apple NV_vertex_program clip bug quirk"
961 },
962 {
963 match_fbo_tex_update,
964 quirk_fbo_tex_update,
965 "FBO rebind for attachment updates"
966 },
967 {
968 match_ati_hd4800,
969 quirk_fullsize_blit,
970 "Fullsize blit"
971 },
972};
973
974/* Certain applications (Steam) complain if we report an outdated driver version. In general,
975 * reporting a driver version is moot because we are not the Windows driver, and we have different
976 * bugs, features, etc.
977 *
978 * The driver version has the form "x.y.z.w".
979 *
980 * "x" is the Windows version the driver is meant for:
981 * 4 -> 95/98/NT4
982 * 5 -> 2000
983 * 6 -> 2000/XP
984 * 7 -> Vista
985 * 8 -> Win 7
986 *
987 * "y" is the Direct3D level the driver supports:
988 * 11 -> d3d6
989 * 12 -> d3d7
990 * 13 -> d3d8
991 * 14 -> d3d9
992 * 15 -> d3d10
993 *
994 * "z" is unknown, possibly vendor specific.
995 *
996 * "w" is the vendor specific driver version.
997 */
998struct driver_version_information
999{
1000 WORD vendor; /* reported PCI card vendor ID */
1001 WORD card; /* reported PCI card device ID */
1002 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
1003 WORD d3d_level; /* driver hiword to report */
1004 WORD lopart_hi, lopart_lo; /* driver loword to report */
1005};
1006
1007static const struct driver_version_information driver_version_table[] =
1008{
1009 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
1010 * 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
1011 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
1012 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
1013 *
1014 * All version numbers used below are from the Linux nvidia drivers. */
1015 {HW_VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 1, 8, 6 },
1016 {HW_VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 1, 8, 6 },
1017 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 1, 8, 6 },
1018 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 6, 4, 3 },
1019 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 1, 8, 6 },
1020 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 6, 10, 9371 },
1021 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 6, 10, 9371 },
1022 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 6, 10, 9371 },
1023 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 15, 11, 7516 },
1024 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 15, 11, 7516 },
1025 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 15, 11, 7516 },
1026 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 15, 11, 8618 },
1027 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 15, 11, 8618 },
1028 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 15, 11, 8618 },
1029 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 15, 11, 8585 },
1030 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 15, 11, 8585 },
1031 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 15, 11, 8618 },
1032 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 15, 11, 8618 },
1033 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 15, 11, 8618 },
1034 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 15, 11, 8618 },
1035 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 15, 11, 8585 },
1036 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 15, 11, 8618 },
1037 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 15, 11, 8618 },
1038 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 15, 11, 8618 },
1039 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 15, 11, 8618 },
1040 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 15, 11, 8618 },
1041 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 15, 11, 8618 },
1042 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 15, 11, 8618 },
1043 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 15, 11, 8618 },
1044 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 15, 11, 8618 },
1045 {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GT240, "NVIDIA GeForce GT 240", 15, 11, 8618 },
1046
1047 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
1048 {HW_VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 14, 10, 6764 },
1049 {HW_VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 14, 10, 6764 },
1050 {HW_VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 14, 10, 6764 },
1051 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2350, "ATI Mobility Radeon HD 2350", 14, 10, 6764 },
1052 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 14, 10, 6764 },
1053 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 14, 10, 6764 },
1054 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 14, 10, 6764 },
1055 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 14, 10, 6764 },
1056 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 14, 10, 6764 },
1057 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 14, 10, 6764 },
1058 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD5700, "ATI Radeon HD 5700 Series", 14, 10, 8681 },
1059 {HW_VENDOR_ATI, CARD_ATI_RADEON_HD5800, "ATI Radeon HD 5800 Series", 14, 10, 8681 },
1060
1061 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
1062};
1063
1064static void init_driver_info(struct wined3d_driver_info *driver_info,
1065 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
1066{
1067 OSVERSIONINFOW os_version;
1068 WORD driver_os_version;
1069 unsigned int i;
1070
1071 if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1072 {
1073 TRACE_(d3d_caps)("Overriding PCI vendor ID with: %04x\n", wined3d_settings.pci_vendor_id);
1074 vendor = wined3d_settings.pci_vendor_id;
1075 }
1076 driver_info->vendor = vendor;
1077
1078 if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1079 {
1080 TRACE_(d3d_caps)("Overriding PCI device ID with: %04x\n", wined3d_settings.pci_device_id);
1081 device = wined3d_settings.pci_device_id;
1082 }
1083 driver_info->device = device;
1084
1085 switch (vendor)
1086 {
1087 case HW_VENDOR_ATI:
1088 driver_info->name = "ati2dvag.dll";
1089 break;
1090
1091 case HW_VENDOR_NVIDIA:
1092 driver_info->name = "nv4_disp.dll";
1093 break;
1094
1095 case HW_VENDOR_INTEL:
1096 default:
1097 FIXME_(d3d_caps)("Unhandled vendor %04x.\n", vendor);
1098 driver_info->name = "Display";
1099 break;
1100 }
1101
1102 memset(&os_version, 0, sizeof(os_version));
1103 os_version.dwOSVersionInfoSize = sizeof(os_version);
1104 if (!GetVersionExW(&os_version))
1105 {
1106 ERR("Failed to get OS version, reporting 2000/XP.\n");
1107 driver_os_version = 6;
1108 }
1109 else
1110 {
1111 TRACE("OS version %u.%u.\n", os_version.dwMajorVersion, os_version.dwMinorVersion);
1112 switch (os_version.dwMajorVersion)
1113 {
1114 case 4:
1115 driver_os_version = 4;
1116 break;
1117
1118 case 5:
1119 driver_os_version = 6;
1120 break;
1121
1122 case 6:
1123 if (os_version.dwMinorVersion == 0)
1124 {
1125 driver_os_version = 7;
1126 }
1127 else
1128 {
1129 if (os_version.dwMinorVersion > 1)
1130 {
1131 FIXME("Unhandled OS version %u.%u, reporting Win 7.\n",
1132 os_version.dwMajorVersion, os_version.dwMinorVersion);
1133 }
1134 driver_os_version = 8;
1135 }
1136 break;
1137
1138 default:
1139 FIXME("Unhandled OS version %u.%u, reporting 2000/XP.\n",
1140 os_version.dwMajorVersion, os_version.dwMinorVersion);
1141 driver_os_version = 6;
1142 break;
1143 }
1144 }
1145
1146 driver_info->description = "Direct3D HAL";
1147 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
1148 driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
1149
1150 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
1151 {
1152 if (vendor == driver_version_table[i].vendor && device == driver_version_table[i].card)
1153 {
1154 TRACE_(d3d_caps)("Found card %04x:%04x in driver DB.\n", vendor, device);
1155
1156 driver_info->description = driver_version_table[i].description;
1157 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, driver_version_table[i].d3d_level);
1158 driver_info->version_low = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
1159 driver_version_table[i].lopart_lo);
1160 break;
1161 }
1162 }
1163
1164 TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08x-0x%08x.\n",
1165 driver_info->version_high, driver_info->version_low);
1166}
1167
1168/* Context activation is done by the caller. */
1169static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer,
1170 enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
1171{
1172 unsigned int i;
1173
1174 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
1175 {
1176 if (!quirk_table[i].match(gl_info, gl_renderer, gl_vendor, card_vendor, device)) continue;
1177 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
1178 quirk_table[i].apply(gl_info);
1179 }
1180
1181 /* Find out if PBOs work as they are supposed to. */
1182 test_pbo_functionality(gl_info);
1183}
1184
1185static DWORD wined3d_parse_gl_version(const char *gl_version)
1186{
1187 const char *ptr = gl_version;
1188 int major, minor;
1189
1190 major = atoi(ptr);
1191 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
1192
1193 while (isdigit(*ptr)) ++ptr;
1194 if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version));
1195
1196 minor = atoi(ptr);
1197
1198 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
1199
1200 return MAKEDWORD_VERSION(major, minor);
1201}
1202
1203static enum wined3d_gl_vendor wined3d_guess_gl_vendor(struct wined3d_gl_info *gl_info, const char *gl_vendor_string, const char *gl_renderer)
1204{
1205
1206 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
1207 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
1208 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
1209 *
1210 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
1211 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
1212 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
1213 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
1214 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
1215 * the chance that other implementations support them is rather small since Win32 QuickTime uses
1216 * DirectDraw, not OpenGL. */
1217 if (gl_info->supported[APPLE_FENCE]
1218 && gl_info->supported[APPLE_CLIENT_STORAGE]
1219 && gl_info->supported[APPLE_FLUSH_RENDER]
1220 && gl_info->supported[APPLE_YCBCR_422])
1221 return GL_VENDOR_APPLE;
1222
1223 if (strstr(gl_vendor_string, "NVIDIA"))
1224 return GL_VENDOR_NVIDIA;
1225
1226 if (strstr(gl_vendor_string, "ATI"))
1227 return GL_VENDOR_FGLRX;
1228
1229 if (strstr(gl_vendor_string, "Intel(R)")
1230 || strstr(gl_renderer, "Intel(R)")
1231 || strstr(gl_vendor_string, "Intel Inc."))
1232 return GL_VENDOR_INTEL;
1233
1234 if (strstr(gl_vendor_string, "Mesa")
1235 || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
1236 || strstr(gl_vendor_string, "DRI R300 Project")
1237 || strstr(gl_vendor_string, "X.Org R300 Project")
1238 || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
1239 || strstr(gl_vendor_string, "VMware, Inc.")
1240 || strstr(gl_renderer, "Mesa")
1241 || strstr(gl_renderer, "Gallium"))
1242 return GL_VENDOR_MESA;
1243
1244 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning GL_VENDOR_UNKNOWN.\n",
1245 debugstr_a(gl_vendor_string));
1246
1247 return GL_VENDOR_UNKNOWN;
1248}
1249
1250static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_string, const char *gl_renderer)
1251{
1252 if (strstr(gl_vendor_string, "NVIDIA"))
1253 return HW_VENDOR_NVIDIA;
1254
1255 if (strstr(gl_vendor_string, "ATI")
1256 || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
1257 || strstr(gl_vendor_string, "X.Org R300 Project")
1258 || strstr(gl_vendor_string, "DRI R300 Project"))
1259 return HW_VENDOR_ATI;
1260
1261 if (strstr(gl_vendor_string, "Intel(R)")
1262 || strstr(gl_renderer, "Intel(R)")
1263 || strstr(gl_vendor_string, "Intel Inc."))
1264 return HW_VENDOR_INTEL;
1265
1266 if (strstr(gl_vendor_string, "Mesa")
1267 || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
1268 || strstr(gl_vendor_string, "VMware, Inc."))
1269 return HW_VENDOR_SOFTWARE;
1270
1271 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning HW_VENDOR_NVIDIA.\n", debugstr_a(gl_vendor_string));
1272
1273 return HW_VENDOR_NVIDIA;
1274}
1275
1276
1277
1278static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info,
1279 const char *gl_renderer, unsigned int *vidmem)
1280{
1281#ifndef VBOX_WITH_WDDM
1282 if (WINE_D3D10_CAPABLE(gl_info))
1283#endif
1284 {
1285 /* Geforce 200 - highend */
1286 if (strstr(gl_renderer, "GTX 280")
1287 || strstr(gl_renderer, "GTX 285")
1288 || strstr(gl_renderer, "GTX 295"))
1289 {
1290 *vidmem = 1024;
1291 return CARD_NVIDIA_GEFORCE_GTX280;
1292 }
1293
1294 /* Geforce 200 - midend high */
1295 if (strstr(gl_renderer, "GTX 275"))
1296 {
1297 *vidmem = 896;
1298 return CARD_NVIDIA_GEFORCE_GTX275;
1299 }
1300
1301 /* Geforce 200 - midend */
1302 if (strstr(gl_renderer, "GTX 260"))
1303 {
1304 *vidmem = 1024;
1305 return CARD_NVIDIA_GEFORCE_GTX260;
1306 }
1307 /* Geforce 200 - midend */
1308 if (strstr(gl_renderer, "GT 240"))
1309 {
1310 *vidmem = 512;
1311 return CARD_NVIDIA_GEFORCE_GT240;
1312 }
1313
1314 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1315 if (strstr(gl_renderer, "9800")
1316 || strstr(gl_renderer, "GTS 150")
1317 || strstr(gl_renderer, "GTS 250"))
1318 {
1319 *vidmem = 512;
1320 return CARD_NVIDIA_GEFORCE_9800GT;
1321 }
1322
1323 /* Geforce9 - midend */
1324 if (strstr(gl_renderer, "9600"))
1325 {
1326 *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1327 return CARD_NVIDIA_GEFORCE_9600GT;
1328 }
1329
1330 /* Geforce9 - midend low / Geforce 200 - low */
1331 if (strstr(gl_renderer, "9500")
1332 || strstr(gl_renderer, "GT 120")
1333 || strstr(gl_renderer, "GT 130"))
1334 {
1335 *vidmem = 256; /* The 9500GT has 256-1024MB */
1336 return CARD_NVIDIA_GEFORCE_9500GT;
1337 }
1338
1339 /* Geforce9 - lowend */
1340 if (strstr(gl_renderer, "9400"))
1341 {
1342 *vidmem = 256; /* The 9400GT has 256-1024MB */
1343 return CARD_NVIDIA_GEFORCE_9400GT;
1344 }
1345
1346 /* Geforce9 - lowend low */
1347 if (strstr(gl_renderer, "9100")
1348 || strstr(gl_renderer, "9200")
1349 || strstr(gl_renderer, "9300")
1350 || strstr(gl_renderer, "G 100"))
1351 {
1352 *vidmem = 256; /* The 9100-9300 cards have 256MB */
1353 return CARD_NVIDIA_GEFORCE_9200;
1354 }
1355
1356 /* Geforce8 - highend */
1357 if (strstr(gl_renderer, "8800"))
1358 {
1359 *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1360 return CARD_NVIDIA_GEFORCE_8800GTS;
1361 }
1362
1363 /* Geforce8 - midend mobile */
1364 if (strstr(gl_renderer, "8600 M"))
1365 {
1366 *vidmem = 512;
1367 return CARD_NVIDIA_GEFORCE_8600MGT;
1368 }
1369
1370 /* Geforce8 - midend */
1371 if (strstr(gl_renderer, "8600")
1372 || strstr(gl_renderer, "8700"))
1373 {
1374 *vidmem = 256;
1375 return CARD_NVIDIA_GEFORCE_8600GT;
1376 }
1377
1378 /* Geforce8 - lowend */
1379 if (strstr(gl_renderer, "8100")
1380 || strstr(gl_renderer, "8200")
1381 || strstr(gl_renderer, "8300")
1382 || strstr(gl_renderer, "8400")
1383 || strstr(gl_renderer, "8500"))
1384 {
1385 *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1386 return CARD_NVIDIA_GEFORCE_8300GS;
1387 }
1388
1389 /* Geforce8-compatible fall back if the GPU is not in the list yet */
1390 *vidmem = 128;
1391 return CARD_NVIDIA_GEFORCE_8300GS;
1392 }
1393
1394 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1395 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1396 */
1397 if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3])
1398 {
1399 /* Geforce7 - highend */
1400 if (strstr(gl_renderer, "7800")
1401 || strstr(gl_renderer, "7900")
1402 || strstr(gl_renderer, "7950")
1403 || strstr(gl_renderer, "Quadro FX 4")
1404 || strstr(gl_renderer, "Quadro FX 5"))
1405 {
1406 *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1407 return CARD_NVIDIA_GEFORCE_7800GT;
1408 }
1409
1410 /* Geforce7 midend */
1411 if (strstr(gl_renderer, "7600")
1412 || strstr(gl_renderer, "7700"))
1413 {
1414 *vidmem = 256; /* The 7600 uses 256-512MB */
1415 return CARD_NVIDIA_GEFORCE_7600;
1416 }
1417
1418 /* Geforce7 lower medium */
1419 if (strstr(gl_renderer, "7400"))
1420 {
1421 *vidmem = 256; /* The 7400 uses 256-512MB */
1422 return CARD_NVIDIA_GEFORCE_7400;
1423 }
1424
1425 /* Geforce7 lowend */
1426 if (strstr(gl_renderer, "7300"))
1427 {
1428 *vidmem = 256; /* Mac Pros with this card have 256 MB */
1429 return CARD_NVIDIA_GEFORCE_7300;
1430 }
1431
1432 /* Geforce6 highend */
1433 if (strstr(gl_renderer, "6800"))
1434 {
1435 *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1436 return CARD_NVIDIA_GEFORCE_6800;
1437 }
1438
1439 /* Geforce6 - midend */
1440 if (strstr(gl_renderer, "6600")
1441 || strstr(gl_renderer, "6610")
1442 || strstr(gl_renderer, "6700"))
1443 {
1444 *vidmem = 128; /* A 6600GT has 128-256MB */
1445 return CARD_NVIDIA_GEFORCE_6600GT;
1446 }
1447
1448 /* Geforce6/7 lowend */
1449 *vidmem = 64; /* */
1450 return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1451 }
1452
1453 if (WINE_D3D9_CAPABLE(gl_info))
1454 {
1455 /* GeforceFX - highend */
1456 if (strstr(gl_renderer, "5800")
1457 || strstr(gl_renderer, "5900")
1458 || strstr(gl_renderer, "5950")
1459 || strstr(gl_renderer, "Quadro FX"))
1460 {
1461 *vidmem = 256; /* 5800-5900 cards use 256MB */
1462 return CARD_NVIDIA_GEFORCEFX_5800;
1463 }
1464
1465 /* GeforceFX - midend */
1466 if (strstr(gl_renderer, "5600")
1467 || strstr(gl_renderer, "5650")
1468 || strstr(gl_renderer, "5700")
1469 || strstr(gl_renderer, "5750"))
1470 {
1471 *vidmem = 128; /* A 5600 uses 128-256MB */
1472 return CARD_NVIDIA_GEFORCEFX_5600;
1473 }
1474
1475 /* GeforceFX - lowend */
1476 *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1477 return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1478 }
1479
1480 if (WINE_D3D8_CAPABLE(gl_info))
1481 {
1482 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1483 {
1484 *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1485 return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1486 }
1487
1488 *vidmem = 64; /* Geforce3 cards have 64-128MB */
1489 return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1490 }
1491
1492 if (WINE_D3D7_CAPABLE(gl_info))
1493 {
1494 if (strstr(gl_renderer, "GeForce4 MX"))
1495 {
1496 /* Most Geforce4MX GPUs have at least 64MB of memory, some
1497 * early models had 32MB but most have 64MB or even 128MB. */
1498 *vidmem = 64;
1499 return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1500 }
1501
1502 if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1503 {
1504 *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1505 return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1506 }
1507
1508 if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1509 {
1510 *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1511 return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1512 }
1513
1514 /* Most Geforce1 cards have 32MB, there are also some rare 16
1515 * and 64MB (Dell) models. */
1516 *vidmem = 32;
1517 return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1518 }
1519
1520 if (strstr(gl_renderer, "TNT2"))
1521 {
1522 *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1523 return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1524 }
1525
1526 *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1527 return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1528
1529}
1530
1531static enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_info,
1532 const char *gl_renderer, unsigned int *vidmem)
1533{
1534 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1535 *
1536 * Beware: renderer string do not match exact card model,
1537 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1538#ifndef VBOX_WITH_WDDM
1539 if (WINE_D3D10_CAPABLE(gl_info))
1540#endif
1541 {
1542 /* Radeon EG CYPRESS XT / PRO HD5800 - highend */
1543 if (strstr(gl_renderer, "HD 5800") /* Radeon EG CYPRESS HD58xx generic renderer string */
1544 || strstr(gl_renderer, "HD 5850") /* Radeon EG CYPRESS XT */
1545 || strstr(gl_renderer, "HD 5870")) /* Radeon EG CYPRESS PRO */
1546 {
1547 *vidmem = 1024; /* note: HD58xx cards use 1024MB */
1548 return CARD_ATI_RADEON_HD5800;
1549 }
1550
1551 /* Radeon EG JUNIPER XT / LE HD5700 - midend */
1552 if (strstr(gl_renderer, "HD 5700") /* Radeon EG JUNIPER HD57xx generic renderer string */
1553 || strstr(gl_renderer, "HD 5750") /* Radeon EG JUNIPER LE */
1554 || strstr(gl_renderer, "HD 5770")) /* Radeon EG JUNIPER XT */
1555 {
1556 *vidmem = 512; /* note: HD5770 cards use 1024MB and HD5750 cards use 512MB or 1024MB */
1557 return CARD_ATI_RADEON_HD5700;
1558 }
1559
1560 /* Radeon R7xx HD4800 - highend */
1561 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1562 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1563 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1564 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1565 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1566 {
1567 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1568 return CARD_ATI_RADEON_HD4800;
1569 }
1570
1571 /* Radeon R740 HD4700 - midend */
1572 if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1573 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1574 {
1575 *vidmem = 512;
1576 return CARD_ATI_RADEON_HD4700;
1577 }
1578
1579 /* Radeon R730 HD4600 - midend */
1580 if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1581 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1582 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1583 {
1584 *vidmem = 512;
1585 return CARD_ATI_RADEON_HD4600;
1586 }
1587
1588 /* Radeon R710 HD4500/HD4350 - lowend */
1589 if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1590 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1591 {
1592 *vidmem = 256;
1593 return CARD_ATI_RADEON_HD4350;
1594 }
1595
1596 /* Radeon R6xx HD2900/HD3800 - highend */
1597 if (strstr(gl_renderer, "HD 2900")
1598 || strstr(gl_renderer, "HD 3870")
1599 || strstr(gl_renderer, "HD 3850"))
1600 {
1601 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1602 return CARD_ATI_RADEON_HD2900;
1603 }
1604
1605 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1606 if (strstr(gl_renderer, "HD 2600")
1607 || strstr(gl_renderer, "HD 3830")
1608 || strstr(gl_renderer, "HD 3690")
1609 || strstr(gl_renderer, "HD 3650"))
1610 {
1611 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1612 return CARD_ATI_RADEON_HD2600;
1613 }
1614
1615 /* Radeon R6xx HD2350/HD2400/HD3400 - lowend
1616 * Note HD2300=DX9, HD2350=DX10 */
1617 if (strstr(gl_renderer, "HD 2350")
1618 || strstr(gl_renderer, "HD 2400")
1619 || strstr(gl_renderer, "HD 3470")
1620 || strstr(gl_renderer, "HD 3450")
1621 || strstr(gl_renderer, "HD 3430")
1622 || strstr(gl_renderer, "HD 3400"))
1623 {
1624 *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */
1625 return CARD_ATI_RADEON_HD2350;
1626 }
1627
1628 /* Radeon R6xx/R7xx integrated */
1629 if (strstr(gl_renderer, "HD 3100")
1630 || strstr(gl_renderer, "HD 3200")
1631 || strstr(gl_renderer, "HD 3300"))
1632 {
1633 *vidmem = 128; /* 128MB */
1634 return CARD_ATI_RADEON_HD3200;
1635 }
1636
1637 /* Default for when no GPU has been found */
1638 *vidmem = 128; /* 128MB */
1639 return CARD_ATI_RADEON_HD3200;
1640 }
1641
1642 if (WINE_D3D8_CAPABLE(gl_info))
1643 {
1644 /* Radeon R5xx */
1645 if (strstr(gl_renderer, "X1600")
1646 || strstr(gl_renderer, "X1650")
1647 || strstr(gl_renderer, "X1800")
1648 || strstr(gl_renderer, "X1900")
1649 || strstr(gl_renderer, "X1950"))
1650 {
1651 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1652 return CARD_ATI_RADEON_X1600;
1653 }
1654
1655 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx)
1656 * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */
1657 if (strstr(gl_renderer, "X700")
1658 || strstr(gl_renderer, "X800")
1659 || strstr(gl_renderer, "X850")
1660 || strstr(gl_renderer, "X1300")
1661 || strstr(gl_renderer, "X1400")
1662 || strstr(gl_renderer, "X1450")
1663 || strstr(gl_renderer, "X1550")
1664 || strstr(gl_renderer, "X2300")
1665 || strstr(gl_renderer, "X2500")
1666 || strstr(gl_renderer, "HD 2300")
1667 )
1668 {
1669 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1670 return CARD_ATI_RADEON_X700;
1671 }
1672
1673 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1674 if (strstr(gl_renderer, "Radeon Xpress"))
1675 {
1676 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1677 return CARD_ATI_RADEON_XPRESS_200M;
1678 }
1679
1680 /* Radeon R3xx */
1681 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1682 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1683 }
1684
1685 if (WINE_D3D8_CAPABLE(gl_info))
1686 {
1687 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1688 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1689 }
1690
1691 if (WINE_D3D7_CAPABLE(gl_info))
1692 {
1693 *vidmem = 32; /* There are models with up to 64MB */
1694 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1695 }
1696
1697 *vidmem = 16; /* There are 16-32MB models */
1698 return CARD_ATI_RAGE_128PRO;
1699
1700}
1701
1702static enum wined3d_pci_device select_card_intel_binary(const struct wined3d_gl_info *gl_info,
1703 const char *gl_renderer, unsigned int *vidmem)
1704{
1705 if (strstr(gl_renderer, "X3100"))
1706 {
1707 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1708 *vidmem = 128;
1709 return CARD_INTEL_X3100;
1710 }
1711
1712 if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1713 {
1714 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1715 *vidmem = 64;
1716 return CARD_INTEL_I945GM;
1717 }
1718
1719 if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM;
1720 if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G;
1721 if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G;
1722 if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G;
1723 if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G;
1724 return CARD_INTEL_I915G;
1725
1726}
1727
1728static enum wined3d_pci_device select_card_ati_mesa(const struct wined3d_gl_info *gl_info,
1729 const char *gl_renderer, unsigned int *vidmem)
1730{
1731 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1732 *
1733 * Beware: renderer string do not match exact card model,
1734 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1735 if (strstr(gl_renderer, "Gallium"))
1736 {
1737 /* Radeon R7xx HD4800 - highend */
1738 if (strstr(gl_renderer, "R700") /* Radeon R7xx HD48xx generic renderer string */
1739 || strstr(gl_renderer, "RV770") /* Radeon RV770 */
1740 || strstr(gl_renderer, "RV790")) /* Radeon RV790 */
1741 {
1742 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1743 return CARD_ATI_RADEON_HD4800;
1744 }
1745
1746 /* Radeon R740 HD4700 - midend */
1747 if (strstr(gl_renderer, "RV740")) /* Radeon RV740 */
1748 {
1749 *vidmem = 512;
1750 return CARD_ATI_RADEON_HD4700;
1751 }
1752
1753 /* Radeon R730 HD4600 - midend */
1754 if (strstr(gl_renderer, "RV730")) /* Radeon RV730 */
1755 {
1756 *vidmem = 512;
1757 return CARD_ATI_RADEON_HD4600;
1758 }
1759
1760 /* Radeon R710 HD4500/HD4350 - lowend */
1761 if (strstr(gl_renderer, "RV710")) /* Radeon RV710 */
1762 {
1763 *vidmem = 256;
1764 return CARD_ATI_RADEON_HD4350;
1765 }
1766
1767 /* Radeon R6xx HD2900/HD3800 - highend */
1768 if (strstr(gl_renderer, "R600")
1769 || strstr(gl_renderer, "RV670")
1770 || strstr(gl_renderer, "R680"))
1771 {
1772 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1773 return CARD_ATI_RADEON_HD2900;
1774 }
1775
1776 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1777 if (strstr(gl_renderer, "RV630")
1778 || strstr(gl_renderer, "RV635"))
1779 {
1780 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1781 return CARD_ATI_RADEON_HD2600;
1782 }
1783
1784 /* Radeon R6xx HD2350/HD2400/HD3400 - lowend */
1785 if (strstr(gl_renderer, "RV610")
1786 || strstr(gl_renderer, "RV620"))
1787 {
1788 *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */
1789 return CARD_ATI_RADEON_HD2350;
1790 }
1791
1792 /* Radeon R6xx/R7xx integrated */
1793 if (strstr(gl_renderer, "RS780")
1794 || strstr(gl_renderer, "RS880"))
1795 {
1796 *vidmem = 128; /* 128MB */
1797 return CARD_ATI_RADEON_HD3200;
1798 }
1799
1800 /* Radeon R5xx */
1801 if (strstr(gl_renderer, "RV530")
1802 || strstr(gl_renderer, "RV535")
1803 || strstr(gl_renderer, "RV560")
1804 || strstr(gl_renderer, "R520")
1805 || strstr(gl_renderer, "RV570")
1806 || strstr(gl_renderer, "R580"))
1807 {
1808 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1809 return CARD_ATI_RADEON_X1600;
1810 }
1811
1812 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1813 if (strstr(gl_renderer, "R410")
1814 || strstr(gl_renderer, "R420")
1815 || strstr(gl_renderer, "R423")
1816 || strstr(gl_renderer, "R430")
1817 || strstr(gl_renderer, "R480")
1818 || strstr(gl_renderer, "R481")
1819 || strstr(gl_renderer, "RV410")
1820 || strstr(gl_renderer, "RV515")
1821 || strstr(gl_renderer, "RV516"))
1822 {
1823 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1824 return CARD_ATI_RADEON_X700;
1825 }
1826
1827 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1828 if (strstr(gl_renderer, "RS400")
1829 || strstr(gl_renderer, "RS480")
1830 || strstr(gl_renderer, "RS482")
1831 || strstr(gl_renderer, "RS485")
1832 || strstr(gl_renderer, "RS600")
1833 || strstr(gl_renderer, "RS690")
1834 || strstr(gl_renderer, "RS740"))
1835 {
1836 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1837 return CARD_ATI_RADEON_XPRESS_200M;
1838 }
1839
1840 /* Radeon R3xx */
1841 if (strstr(gl_renderer, "R300")
1842 || strstr(gl_renderer, "RV350")
1843 || strstr(gl_renderer, "RV351")
1844 || strstr(gl_renderer, "RV360")
1845 || strstr(gl_renderer, "RV370")
1846 || strstr(gl_renderer, "R350")
1847 || strstr(gl_renderer, "R360"))
1848 {
1849 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1850 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1851 }
1852 }
1853
1854 if (WINE_D3D9_CAPABLE(gl_info))
1855 {
1856 /* Radeon R7xx HD4800 - highend */
1857 if (strstr(gl_renderer, "(R700") /* Radeon R7xx HD48xx generic renderer string */
1858 || strstr(gl_renderer, "(RV770") /* Radeon RV770 */
1859 || strstr(gl_renderer, "(RV790")) /* Radeon RV790 */
1860 {
1861 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1862 return CARD_ATI_RADEON_HD4800;
1863 }
1864
1865 /* Radeon R740 HD4700 - midend */
1866 if (strstr(gl_renderer, "(RV740")) /* Radeon RV740 */
1867 {
1868 *vidmem = 512;
1869 return CARD_ATI_RADEON_HD4700;
1870 }
1871
1872 /* Radeon R730 HD4600 - midend */
1873 if (strstr(gl_renderer, "(RV730")) /* Radeon RV730 */
1874 {
1875 *vidmem = 512;
1876 return CARD_ATI_RADEON_HD4600;
1877 }
1878
1879 /* Radeon R710 HD4500/HD4350 - lowend */
1880 if (strstr(gl_renderer, "(RV710")) /* Radeon RV710 */
1881 {
1882 *vidmem = 256;
1883 return CARD_ATI_RADEON_HD4350;
1884 }
1885
1886 /* Radeon R6xx HD2900/HD3800 - highend */
1887 if (strstr(gl_renderer, "(R600")
1888 || strstr(gl_renderer, "(RV670")
1889 || strstr(gl_renderer, "(R680"))
1890 {
1891 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1892 return CARD_ATI_RADEON_HD2900;
1893 }
1894
1895 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1896 if (strstr(gl_renderer, "(RV630")
1897 || strstr(gl_renderer, "(RV635"))
1898 {
1899 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1900 return CARD_ATI_RADEON_HD2600;
1901 }
1902
1903 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1904 if (strstr(gl_renderer, "(RV610")
1905 || strstr(gl_renderer, "(RV620"))
1906 {
1907 *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */
1908 return CARD_ATI_RADEON_HD2350;
1909 }
1910
1911 /* Radeon R6xx/R7xx integrated */
1912 if (strstr(gl_renderer, "(RS780")
1913 || strstr(gl_renderer, "(RS880"))
1914 {
1915 *vidmem = 128; /* 128MB */
1916 return CARD_ATI_RADEON_HD3200;
1917 }
1918 }
1919
1920 if (WINE_D3D8_CAPABLE(gl_info))
1921 {
1922 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1923 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1924 }
1925
1926 if (WINE_D3D7_CAPABLE(gl_info))
1927 {
1928 *vidmem = 32; /* There are models with up to 64MB */
1929 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1930 }
1931
1932 *vidmem = 16; /* There are 16-32MB models */
1933 return CARD_ATI_RAGE_128PRO;
1934
1935}
1936
1937static enum wined3d_pci_device select_card_nvidia_mesa(const struct wined3d_gl_info *gl_info,
1938 const char *gl_renderer, unsigned int *vidmem)
1939{
1940 FIXME_(d3d_caps)("Card selection not handled for Mesa Nouveau driver\n");
1941 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1942 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1943 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1944 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
1945 return CARD_NVIDIA_RIVA_128;
1946}
1947
1948static enum wined3d_pci_device select_card_intel_mesa(const struct wined3d_gl_info *gl_info,
1949 const char *gl_renderer, unsigned int *vidmem)
1950{
1951 FIXME_(d3d_caps)("Card selection not handled for Mesa Intel driver\n");
1952 return CARD_INTEL_I915G;
1953}
1954
1955
1956struct vendor_card_selection
1957{
1958 enum wined3d_gl_vendor gl_vendor;
1959 enum wined3d_pci_vendor card_vendor;
1960 const char *description; /* Description of the card selector i.e. Apple OS/X Intel */
1961 enum wined3d_pci_device (*select_card)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1962 unsigned int *vidmem );
1963};
1964
1965static const struct vendor_card_selection vendor_card_select_table[] =
1966{
1967 {GL_VENDOR_NVIDIA, HW_VENDOR_NVIDIA, "Nvidia binary driver", select_card_nvidia_binary},
1968 {GL_VENDOR_APPLE, HW_VENDOR_NVIDIA, "Apple OSX NVidia binary driver", select_card_nvidia_binary},
1969 {GL_VENDOR_APPLE, HW_VENDOR_ATI, "Apple OSX AMD/ATI binary driver", select_card_ati_binary},
1970 {GL_VENDOR_APPLE, HW_VENDOR_INTEL, "Apple OSX Intel binary driver", select_card_intel_binary},
1971 {GL_VENDOR_FGLRX, HW_VENDOR_ATI, "AMD/ATI binary driver", select_card_ati_binary},
1972 {GL_VENDOR_MESA, HW_VENDOR_ATI, "Mesa AMD/ATI driver", select_card_ati_mesa},
1973 {GL_VENDOR_MESA, HW_VENDOR_NVIDIA, "Mesa Nouveau driver", select_card_nvidia_mesa},
1974 {GL_VENDOR_MESA, HW_VENDOR_INTEL, "Mesa Intel driver", select_card_intel_mesa}
1975};
1976
1977
1978static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1979 enum wined3d_gl_vendor *gl_vendor, enum wined3d_pci_vendor *card_vendor, unsigned int *vidmem)
1980{
1981 /* Above is a list of Nvidia and ATI GPUs. Both vendors have dozens of
1982 * different GPUs with roughly the same features. In most cases GPUs from a
1983 * certain family differ in clockspeeds, the amount of video memory and the
1984 * number of shader pipelines.
1985 *
1986 * A Direct3D device object contains the PCI id (vendor + device) of the
1987 * videocard which is used for rendering. Various applications use this
1988 * information to get a rough estimation of the features of the card and
1989 * some might use it for enabling 3d effects only on certain types of
1990 * videocards. In some cases games might even use it to work around bugs
1991 * which happen on certain videocards/driver combinations. The problem is
1992 * that OpenGL only exposes a rendering string containing the name of the
1993 * videocard and not the PCI id.
1994 *
1995 * Various games depend on the PCI id, so somehow we need to provide one.
1996 * A simple option is to parse the renderer string and translate this to
1997 * the right PCI id. This is a lot of work because there are more than 200
1998 * GPUs just for Nvidia. Various cards share the same renderer string, so
1999 * the amount of code might be 'small' but there are quite a number of
2000 * exceptions which would make this a pain to maintain. Another way would
2001 * be to query the PCI id from the operating system (assuming this is the
2002 * videocard which is used for rendering which is not always the case).
2003 * This would work but it is not very portable. Second it would not work
2004 * well in, let's say, a remote X situation in which the amount of 3d
2005 * features which can be used is limited.
2006 *
2007 * As said most games only use the PCI id to get an indication of the
2008 * capabilities of the card. It doesn't really matter if the given id is
2009 * the correct one if we return the id of a card with similar 3d features.
2010 *
2011 * The code below checks the OpenGL capabilities of a videocard and matches
2012 * that to a certain level of Direct3D functionality. Once a card passes
2013 * the Direct3D9 check, we know that the card (in case of Nvidia) is at
2014 * least a GeforceFX. To give a better estimate we do a basic check on the
2015 * renderer string but if that won't pass we return a default card. This
2016 * way is better than maintaining a full card database as even without a
2017 * full database we can return a card with similar features. Second the
2018 * size of the database can be made quite small because when you know what
2019 * type of 3d functionality a card has, you know to which GPU family the
2020 * GPU must belong. Because of this you only have to check a small part of
2021 * the renderer string to distinguishes between different models from that
2022 * family.
2023 *
2024 * The code also selects a default amount of video memory which we will
2025 * use for an estimation of the amount of free texture memory. In case of
2026 * real D3D the amount of texture memory includes video memory and system
2027 * memory (to be specific AGP memory or in case of PCIE TurboCache /
2028 * HyperMemory). We don't know how much system memory can be addressed by
2029 * the system but we can make a reasonable estimation about the amount of
2030 * video memory. If the value is slightly wrong it doesn't matter as we
2031 * didn't include AGP-like memory which makes the amount of addressable
2032 * memory higher and second OpenGL isn't that critical it moves to system
2033 * memory behind our backs if really needed. Note that the amount of video
2034 * memory can be overruled using a registry setting. */
2035
2036 int i;
2037
2038 for (i = 0; i < (sizeof(vendor_card_select_table) / sizeof(*vendor_card_select_table)); ++i)
2039 {
2040 if ((vendor_card_select_table[i].gl_vendor != *gl_vendor)
2041 || (vendor_card_select_table[i].card_vendor != *card_vendor))
2042 continue;
2043 TRACE_(d3d_caps)("Applying card_selector \"%s\".\n", vendor_card_select_table[i].description);
2044 return vendor_card_select_table[i].select_card(gl_info, gl_renderer, vidmem);
2045 }
2046
2047 FIXME_(d3d_caps)("No card selector available for GL vendor %d and card vendor %04x.\n",
2048 *gl_vendor, *card_vendor);
2049
2050 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
2051 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
2052 * them a good generic choice. */
2053 *card_vendor = HW_VENDOR_NVIDIA;
2054 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
2055 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
2056 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
2057 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
2058 return CARD_NVIDIA_RIVA_128;
2059}
2060
2061static const struct fragment_pipeline *select_fragment_implementation(struct wined3d_adapter *adapter)
2062{
2063 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2064 int vs_selected_mode, ps_selected_mode;
2065
2066 select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode);
2067 if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL)
2068 && gl_info->supported[ARB_FRAGMENT_PROGRAM]) return &arbfp_fragment_pipeline;
2069 else if (ps_selected_mode == SHADER_ATI) return &atifs_fragment_pipeline;
2070 else if (gl_info->supported[NV_REGISTER_COMBINERS]
2071 && gl_info->supported[NV_TEXTURE_SHADER2]) return &nvts_fragment_pipeline;
2072 else if (gl_info->supported[NV_REGISTER_COMBINERS]) return &nvrc_fragment_pipeline;
2073 else return &ffp_fragment_pipeline;
2074}
2075
2076static const shader_backend_t *select_shader_backend(struct wined3d_adapter *adapter)
2077{
2078 int vs_selected_mode, ps_selected_mode;
2079
2080 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
2081 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) return &glsl_shader_backend;
2082 if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) return &arb_program_shader_backend;
2083 return &none_shader_backend;
2084}
2085
2086static const struct blit_shader *select_blit_implementation(struct wined3d_adapter *adapter)
2087{
2088 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2089 int vs_selected_mode, ps_selected_mode;
2090
2091 select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode);
2092 if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL)
2093 && gl_info->supported[ARB_FRAGMENT_PROGRAM]) return &arbfp_blit;
2094 else return &ffp_blit;
2095}
2096
2097/* Context activation is done by the caller. */
2098static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_adapter *adapter)
2099{
2100 struct wined3d_driver_info *driver_info = &adapter->driver_info;
2101 struct wined3d_gl_info *gl_info = &adapter->gl_info;
2102 const char *GL_Extensions = NULL;
2103 const char *WGL_Extensions = NULL;
2104 const char *gl_vendor_str, *gl_renderer_str, *gl_version_str;
2105 struct fragment_caps fragment_caps;
2106 enum wined3d_gl_vendor gl_vendor;
2107 enum wined3d_pci_vendor card_vendor;
2108 enum wined3d_pci_device device;
2109 GLint gl_max;
2110 GLfloat gl_floatv[2];
2111 unsigned i;
2112 HDC hdc;
2113 unsigned int vidmem=0;
2114 DWORD gl_version;
2115 size_t len;
2116
2117 TRACE_(d3d_caps)("(%p)\n", gl_info);
2118
2119 ENTER_GL();
2120
2121 gl_renderer_str = (const char *)glGetString(GL_RENDERER);
2122 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_renderer_str));
2123 if (!gl_renderer_str)
2124 {
2125 LEAVE_GL();
2126 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
2127 return FALSE;
2128 }
2129
2130 gl_vendor_str = (const char *)glGetString(GL_VENDOR);
2131 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_vendor_str));
2132 if (!gl_vendor_str)
2133 {
2134 LEAVE_GL();
2135 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
2136 return FALSE;
2137 }
2138
2139 /* Parse the GL_VERSION field into major and minor information */
2140 gl_version_str = (const char *)glGetString(GL_VERSION);
2141 TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_version_str));
2142 if (!gl_version_str)
2143 {
2144 LEAVE_GL();
2145 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
2146 return FALSE;
2147 }
2148 gl_version = wined3d_parse_gl_version(gl_version_str);
2149
2150 /*
2151 * Initialize openGL extension related variables
2152 * with Default values
2153 */
2154 memset(gl_info->supported, 0, sizeof(gl_info->supported));
2155 gl_info->limits.blends = 1;
2156 gl_info->limits.buffers = 1;
2157 gl_info->limits.textures = 1;
2158 gl_info->limits.fragment_samplers = 1;
2159 gl_info->limits.vertex_samplers = 0;
2160 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
2161 gl_info->limits.sampler_stages = 1;
2162 gl_info->limits.glsl_vs_float_constants = 0;
2163 gl_info->limits.glsl_ps_float_constants = 0;
2164 gl_info->limits.arb_vs_float_constants = 0;
2165 gl_info->limits.arb_vs_native_constants = 0;
2166 gl_info->limits.arb_vs_instructions = 0;
2167 gl_info->limits.arb_vs_temps = 0;
2168 gl_info->limits.arb_ps_float_constants = 0;
2169 gl_info->limits.arb_ps_local_constants = 0;
2170 gl_info->limits.arb_ps_instructions = 0;
2171 gl_info->limits.arb_ps_temps = 0;
2172
2173 /* Retrieve opengl defaults */
2174 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
2175 gl_info->limits.clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
2176 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
2177
2178 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
2179 gl_info->limits.lights = gl_max;
2180 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
2181
2182 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
2183 gl_info->limits.texture_size = gl_max;
2184 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
2185
2186 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
2187 gl_info->limits.pointsize_min = gl_floatv[0];
2188 gl_info->limits.pointsize_max = gl_floatv[1];
2189 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
2190
2191 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
2192 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
2193 if (!GL_Extensions)
2194 {
2195 LEAVE_GL();
2196 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
2197 return FALSE;
2198 }
2199
2200 LEAVE_GL();
2201
2202 TRACE_(d3d_caps)("GL_Extensions reported:\n");
2203
2204 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
2205
2206#ifdef VBOX_WITH_WDDM
2207 gl_info->supported[VBOX_SHARED_CONTEXTS] = TRUE;
2208#endif
2209
2210 while (*GL_Extensions)
2211 {
2212 const char *start;
2213 char current_ext[256];
2214
2215 while (isspace(*GL_Extensions)) ++GL_Extensions;
2216 start = GL_Extensions;
2217 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
2218
2219 len = GL_Extensions - start;
2220 if (!len || len >= sizeof(current_ext)) continue;
2221
2222 memcpy(current_ext, start, len);
2223 current_ext[len] = '\0';
2224 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
2225
2226 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
2227 {
2228 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
2229 {
2230 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
2231 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
2232 break;
2233 }
2234 }
2235 }
2236
2237 /* Now work out what GL support this card really has */
2238#define USE_GL_FUNC(type, pfn, ext, replace) \
2239{ \
2240 DWORD ver = ver_for_ext(ext); \
2241 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
2242 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
2243 else gl_info->pfn = NULL; \
2244}
2245 GL_EXT_FUNCS_GEN;
2246#undef USE_GL_FUNC
2247
2248#define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
2249 WGL_EXT_FUNCS_GEN;
2250#undef USE_GL_FUNC
2251
2252 ENTER_GL();
2253
2254 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
2255 * loading the functions, otherwise the code above will load the extension entry points instead of the
2256 * core functions, which may not work. */
2257 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
2258 {
2259 if (!gl_info->supported[EXTENSION_MAP[i].extension]
2260 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
2261 {
2262 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
2263 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
2264 }
2265 }
2266
2267 if (gl_info->supported[APPLE_FENCE])
2268 {
2269 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
2270 * The apple extension interacts with some other apple exts. Disable the NV
2271 * extension if the apple one is support to prevent confusion in other parts
2272 * of the code. */
2273 gl_info->supported[NV_FENCE] = FALSE;
2274 }
2275 if (gl_info->supported[APPLE_FLOAT_PIXELS])
2276 {
2277 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
2278 *
2279 * The enums are the same:
2280 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
2281 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
2282 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
2283 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
2284 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
2285 */
2286 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
2287 {
2288 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
2289 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
2290 }
2291 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
2292 {
2293 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
2294 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
2295 }
2296 }
2297 if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
2298 {
2299 /* GL_ARB_map_buffer_range and GL_APPLE_flush_buffer_range provide the same
2300 * functionality. Prefer the ARB extension */
2301 gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] = FALSE;
2302 }
2303 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
2304 {
2305 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
2306 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
2307 }
2308 if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
2309 {
2310 TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
2311 gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
2312 }
2313 if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && gl_info->supported[EXT_VERTEX_ARRAY_BGRA])
2314 {
2315 TRACE_(d3d_caps)(" IMPLIED: ARB_vertex_array_bgra support (by EXT_vertex_array_bgra).\n");
2316 gl_info->supported[ARB_VERTEX_ARRAY_BGRA] = TRUE;
2317 }
2318 if (gl_info->supported[NV_TEXTURE_SHADER2])
2319 {
2320 if (gl_info->supported[NV_REGISTER_COMBINERS])
2321 {
2322 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
2323 * are supported. The nv extensions provide the same functionality as the
2324 * ATI one, and a bit more(signed pixelformats). */
2325 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
2326 }
2327 }
2328
2329 if (gl_info->supported[NV_REGISTER_COMBINERS])
2330 {
2331 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
2332 gl_info->limits.general_combiners = gl_max;
2333 TRACE_(d3d_caps)("Max general combiners: %d.\n", gl_max);
2334 }
2335 if (gl_info->supported[ARB_DRAW_BUFFERS])
2336 {
2337 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
2338 gl_info->limits.buffers = gl_max;
2339 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
2340 }
2341 if (gl_info->supported[ARB_MULTITEXTURE])
2342 {
2343 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
2344 gl_info->limits.textures = min(MAX_TEXTURES, gl_max);
2345 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->limits.textures);
2346
2347 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
2348 {
2349 GLint tmp;
2350 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2351 gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
2352 }
2353 else
2354 {
2355 gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, gl_max);
2356 }
2357 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers);
2358
2359 if (gl_info->supported[ARB_VERTEX_SHADER])
2360 {
2361 GLint tmp;
2362 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2363 gl_info->limits.vertex_samplers = tmp;
2364 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2365 gl_info->limits.combined_samplers = tmp;
2366
2367 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
2368 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
2369 * an issue because then the sampler setup only depends on the two shaders. If a pixel
2370 * shader is used with fixed function vertex processing we're fine too because fixed function
2371 * vertex processing doesn't use any samplers. If fixed function fragment processing is
2372 * used we have to make sure that all vertex sampler setups are valid together with all
2373 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
2374 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
2375 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
2376 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
2377 * a fixed function pipeline anymore.
2378 *
2379 * So this is just a check to check that our assumption holds true. If not, write a warning
2380 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
2381 if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12
2382 && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers)
2383 {
2384 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
2385 gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers);
2386 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
2387 if (gl_info->limits.combined_samplers > MAX_TEXTURES)
2388 gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES;
2389 else
2390 gl_info->limits.vertex_samplers = 0;
2391 }
2392 }
2393 else
2394 {
2395 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers;
2396 }
2397 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers);
2398 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->limits.combined_samplers);
2399 }
2400 if (gl_info->supported[ARB_VERTEX_BLEND])
2401 {
2402 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
2403 gl_info->limits.blends = gl_max;
2404 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->limits.blends);
2405 }
2406 if (gl_info->supported[EXT_TEXTURE3D])
2407 {
2408 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
2409 gl_info->limits.texture3d_size = gl_max;
2410 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->limits.texture3d_size);
2411 }
2412 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
2413 {
2414 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
2415 gl_info->limits.anisotropy = gl_max;
2416 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->limits.anisotropy);
2417 }
2418 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
2419 {
2420 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
2421 gl_info->limits.arb_ps_float_constants = gl_max;
2422 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants);
2423 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
2424 gl_info->limits.arb_ps_native_constants = gl_max;
2425 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n",
2426 gl_info->limits.arb_ps_native_constants);
2427 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
2428 gl_info->limits.arb_ps_temps = gl_max;
2429 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps);
2430 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
2431 gl_info->limits.arb_ps_instructions = gl_max;
2432 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions);
2433 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
2434 gl_info->limits.arb_ps_local_constants = gl_max;
2435 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions);
2436 }
2437 if (gl_info->supported[ARB_VERTEX_PROGRAM])
2438 {
2439 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
2440 gl_info->limits.arb_vs_float_constants = gl_max;
2441 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants);
2442 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
2443 gl_info->limits.arb_vs_native_constants = gl_max;
2444 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native float constants: %d.\n",
2445 gl_info->limits.arb_vs_native_constants);
2446 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
2447 gl_info->limits.arb_vs_temps = gl_max;
2448 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps);
2449 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
2450 gl_info->limits.arb_vs_instructions = gl_max;
2451 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions);
2452
2453 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
2454 }
2455 if (gl_info->supported[ARB_VERTEX_SHADER])
2456 {
2457 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
2458 gl_info->limits.glsl_vs_float_constants = gl_max / 4;
2459 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
2460 }
2461 if (gl_info->supported[ARB_FRAGMENT_SHADER])
2462 {
2463 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
2464 gl_info->limits.glsl_ps_float_constants = gl_max / 4;
2465 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants);
2466 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
2467 gl_info->limits.glsl_varyings = gl_max;
2468 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
2469 }
2470 if (gl_info->supported[ARB_SHADING_LANGUAGE_100])
2471 {
2472 const char *str = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
2473 unsigned int major, minor;
2474
2475 TRACE_(d3d_caps)("GLSL version string: %s.\n", debugstr_a(str));
2476
2477 /* The format of the GLSL version string is "major.minor[.release] [vendor info]". */
2478 sscanf(str, "%u.%u", &major, &minor);
2479 gl_info->glsl_version = MAKEDWORD_VERSION(major, minor);
2480 }
2481 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
2482 {
2483 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess);
2484 }
2485 else
2486 {
2487 gl_info->limits.shininess = 128.0f;
2488 }
2489 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
2490 {
2491 /* If we have full NP2 texture support, disable
2492 * GL_ARB_texture_rectangle because we will never use it.
2493 * This saves a few redundant glDisable calls. */
2494 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
2495 }
2496 if (gl_info->supported[ATI_FRAGMENT_SHADER])
2497 {
2498 /* Disable NV_register_combiners and fragment shader if this is supported.
2499 * generally the NV extensions are preferred over the ATI ones, and this
2500 * extension is disabled if register_combiners and texture_shader2 are both
2501 * supported. So we reach this place only if we have incomplete NV dxlevel 8
2502 * fragment processing support. */
2503 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
2504 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
2505 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
2506 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
2507 }
2508 if (gl_info->supported[NV_HALF_FLOAT])
2509 {
2510 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
2511 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
2512 }
2513 if (gl_info->supported[ARB_POINT_SPRITE])
2514 {
2515 gl_info->limits.point_sprite_units = gl_info->limits.textures;
2516 }
2517 else
2518 {
2519 gl_info->limits.point_sprite_units = 0;
2520 }
2521 checkGLcall("extension detection");
2522
2523 LEAVE_GL();
2524
2525 adapter->fragment_pipe = select_fragment_implementation(adapter);
2526 adapter->shader_backend = select_shader_backend(adapter);
2527 adapter->blitter = select_blit_implementation(adapter);
2528
2529 adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
2530 gl_info->limits.texture_stages = fragment_caps.MaxTextureBlendStages;
2531 TRACE_(d3d_caps)("Max texture stages: %u.\n", gl_info->limits.texture_stages);
2532
2533 /* In some cases the number of texture stages can be larger than the number
2534 * of samplers. The GF4 for example can use only 2 samplers (no fragment
2535 * shaders), but 8 texture stages (register combiners). */
2536 gl_info->limits.sampler_stages = max(gl_info->limits.fragment_samplers, gl_info->limits.texture_stages);
2537
2538 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
2539 {
2540 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbuffer;
2541 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbuffer;
2542 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffers;
2543 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffers;
2544 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorage;
2545 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisample;
2546 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameteriv;
2547 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebuffer;
2548 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebuffer;
2549 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffers;
2550 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffers;
2551 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatus;
2552 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1D;
2553 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2D;
2554 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3D;
2555 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbuffer;
2556 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameteriv;
2557 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebuffer;
2558 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmap;
2559 }
2560 else
2561 {
2562 if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT])
2563 {
2564 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbufferEXT;
2565 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbufferEXT;
2566 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffersEXT;
2567 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffersEXT;
2568 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorageEXT;
2569 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameterivEXT;
2570 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebufferEXT;
2571 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebufferEXT;
2572 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffersEXT;
2573 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffersEXT;
2574 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatusEXT;
2575 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1DEXT;
2576 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2DEXT;
2577 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3DEXT;
2578 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbufferEXT;
2579 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameterivEXT;
2580 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmapEXT;
2581 }
2582 else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2583 {
2584 WARN_(d3d_caps)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
2585 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
2586 }
2587 if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
2588 {
2589 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebufferEXT;
2590 }
2591 if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
2592 {
2593 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisampleEXT;
2594 }
2595 }
2596
2597 /* MRTs are currently only supported when FBOs are used. */
2598 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
2599 {
2600 gl_info->limits.buffers = 1;
2601 }
2602
2603 gl_vendor = wined3d_guess_gl_vendor(gl_info, gl_vendor_str, gl_renderer_str);
2604 card_vendor = wined3d_guess_card_vendor(gl_vendor_str, gl_renderer_str);
2605 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x/0x%04x)\n", debugstr_a(gl_vendor_str), gl_vendor, card_vendor);
2606
2607 device = wined3d_guess_card(gl_info, gl_renderer_str, &gl_vendor, &card_vendor, &vidmem);
2608 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", card_vendor, device);
2609
2610 /* If we have an estimate use it, else default to 64MB; */
2611 if(vidmem)
2612 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
2613 else
2614 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
2615
2616 gl_info->wrap_lookup[WINED3DTADDRESS_WRAP - WINED3DTADDRESS_WRAP] = GL_REPEAT;
2617 gl_info->wrap_lookup[WINED3DTADDRESS_MIRROR - WINED3DTADDRESS_WRAP] =
2618 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
2619 gl_info->wrap_lookup[WINED3DTADDRESS_CLAMP - WINED3DTADDRESS_WRAP] = GL_CLAMP_TO_EDGE;
2620 gl_info->wrap_lookup[WINED3DTADDRESS_BORDER - WINED3DTADDRESS_WRAP] =
2621 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2622 gl_info->wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP] =
2623 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
2624
2625 /* Make sure there's an active HDC else the WGL extensions will fail */
2626 hdc = pwglGetCurrentDC();
2627 if (hdc) {
2628 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2629 if(GL_EXTCALL(wglGetExtensionsStringARB))
2630 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2631
2632 if (NULL == WGL_Extensions) {
2633 ERR(" WGL_Extensions returns NULL\n");
2634 } else {
2635 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2636 while (*WGL_Extensions != 0x00) {
2637 const char *Start;
2638 char ThisExtn[256];
2639
2640 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2641 Start = WGL_Extensions;
2642 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2643 WGL_Extensions++;
2644 }
2645
2646 len = WGL_Extensions - Start;
2647 if (len == 0 || len >= sizeof(ThisExtn))
2648 continue;
2649
2650 memcpy(ThisExtn, Start, len);
2651 ThisExtn[len] = '\0';
2652 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
2653
2654 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2655 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2656 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2657 }
2658 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2659 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2660 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2661 }
2662 }
2663 }
2664 }
2665
2666 fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device);
2667 init_driver_info(driver_info, card_vendor, device);
2668 add_gl_compat_wrappers(gl_info);
2669
2670 return TRUE;
2671}
2672
2673/**********************************************************
2674 * IWineD3D implementation follows
2675 **********************************************************/
2676
2677static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2678 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2679
2680 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2681
2682 return This->adapter_count;
2683}
2684
2685static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void *init_function)
2686{
2687 FIXME("iface %p, init_function %p stub!\n", iface, init_function);
2688
2689 return WINED3D_OK;
2690}
2691
2692static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2693 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2694
2695 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2696
2697 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2698 return NULL;
2699 }
2700
2701 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2702}
2703
2704/* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2705 of the same bpp but different resolutions */
2706
2707/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2708static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2709 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2710 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2711
2712 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2713 return 0;
2714 }
2715
2716 /* TODO: Store modes per adapter and read it from the adapter structure */
2717 if (Adapter == 0) { /* Display */
2718 const struct wined3d_format_desc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2719 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2720 unsigned int i = 0;
2721 unsigned int j = 0;
2722 DEVMODEW mode;
2723
2724 memset(&mode, 0, sizeof(mode));
2725 mode.dmSize = sizeof(mode);
2726
2727 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2728 {
2729 ++j;
2730
2731 if (Format == WINED3DFMT_UNKNOWN)
2732 {
2733 /* This is for D3D8, do not enumerate P8 here */
2734 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2735 }
2736 else if (mode.dmBitsPerPel == format_bits)
2737 {
2738 ++i;
2739 }
2740 }
2741
2742 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2743 return i;
2744 } else {
2745 FIXME_(d3d_caps)("Adapter not primary display\n");
2746 }
2747 return 0;
2748}
2749
2750/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2751static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2752 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2753 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2754
2755 /* Validate the parameters as much as possible */
2756 if (NULL == pMode ||
2757 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2758 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2759 return WINED3DERR_INVALIDCALL;
2760 }
2761
2762 /* TODO: Store modes per adapter and read it from the adapter structure */
2763 if (Adapter == 0)
2764 {
2765 const struct wined3d_format_desc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2766 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2767 DEVMODEW DevModeW;
2768 int ModeIdx = 0;
2769 UINT i = 0;
2770 int j = 0;
2771
2772 ZeroMemory(&DevModeW, sizeof(DevModeW));
2773 DevModeW.dmSize = sizeof(DevModeW);
2774
2775 /* If we are filtering to a specific format (D3D9), then need to skip
2776 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2777 just count through the ones with valid bit depths */
2778 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0))
2779 {
2780 if (Format == WINED3DFMT_UNKNOWN)
2781 {
2782 /* This is for D3D8, do not enumerate P8 here */
2783 if (DevModeW.dmBitsPerPel == 32 || DevModeW.dmBitsPerPel == 16) ++i;
2784 }
2785 else if (DevModeW.dmBitsPerPel == format_bits)
2786 {
2787 ++i;
2788 }
2789 }
2790
2791 if (i == 0) {
2792 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2793 return WINED3DERR_INVALIDCALL;
2794 }
2795 ModeIdx = j - 1;
2796
2797 /* Now get the display mode via the calculated index */
2798 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2799 pMode->Width = DevModeW.dmPelsWidth;
2800 pMode->Height = DevModeW.dmPelsHeight;
2801 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2802 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2803 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2804
2805 if (Format == WINED3DFMT_UNKNOWN) {
2806 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2807 } else {
2808 pMode->Format = Format;
2809 }
2810 } else {
2811 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2812 return WINED3DERR_INVALIDCALL;
2813 }
2814
2815 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2816 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2817 DevModeW.dmBitsPerPel);
2818
2819 }
2820 else
2821 {
2822 FIXME_(d3d_caps)("Adapter not primary display\n");
2823 }
2824
2825 return WINED3D_OK;
2826}
2827
2828static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE *pMode)
2829{
2830 TRACE("iface %p, adapter_idx %u, display_mode %p.\n", iface, Adapter, pMode);
2831
2832 if (NULL == pMode ||
2833 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2834 return WINED3DERR_INVALIDCALL;
2835 }
2836
2837 if (Adapter == 0) { /* Display */
2838 int bpp = 0;
2839 DEVMODEW DevModeW;
2840
2841 ZeroMemory(&DevModeW, sizeof(DevModeW));
2842 DevModeW.dmSize = sizeof(DevModeW);
2843
2844 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2845 pMode->Width = DevModeW.dmPelsWidth;
2846 pMode->Height = DevModeW.dmPelsHeight;
2847 bpp = DevModeW.dmBitsPerPel;
2848 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2849 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2850 {
2851 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2852 }
2853
2854 pMode->Format = pixelformat_for_depth(bpp);
2855 } else {
2856 FIXME_(d3d_caps)("Adapter not primary display\n");
2857 }
2858
2859 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2860 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2861 return WINED3D_OK;
2862}
2863
2864/* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2865 and fields being inserted in the middle, a new structure is used in place */
2866static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2867 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2868 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2869 struct wined3d_adapter *adapter;
2870 size_t len;
2871
2872 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2873
2874 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2875 return WINED3DERR_INVALIDCALL;
2876 }
2877
2878 adapter = &This->adapters[Adapter];
2879
2880 /* Return the information requested */
2881 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2882
2883 if (pIdentifier->driver_size)
2884 {
2885 const char *name = adapter->driver_info.name;
2886 len = min(strlen(name), pIdentifier->driver_size - 1);
2887 memcpy(pIdentifier->driver, name, len);
2888 pIdentifier->driver[len] = '\0';
2889 }
2890
2891 if (pIdentifier->description_size)
2892 {
2893 const char *description = adapter->driver_info.description;
2894 len = min(strlen(description), pIdentifier->description_size - 1);
2895 memcpy(pIdentifier->description, description, len);
2896 pIdentifier->description[len] = '\0';
2897 }
2898
2899 /* Note that d3d8 doesn't supply a device name. */
2900 if (pIdentifier->device_name_size)
2901 {
2902 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2903
2904 len = strlen(device_name);
2905 if (len >= pIdentifier->device_name_size)
2906 {
2907 ERR("Device name size too small.\n");
2908 return WINED3DERR_INVALIDCALL;
2909 }
2910
2911 memcpy(pIdentifier->device_name, device_name, len);
2912 pIdentifier->device_name[len] = '\0';
2913 }
2914
2915 pIdentifier->driver_version.u.HighPart = adapter->driver_info.version_high;
2916 pIdentifier->driver_version.u.LowPart = adapter->driver_info.version_low;
2917 pIdentifier->vendor_id = adapter->driver_info.vendor;
2918 pIdentifier->device_id = adapter->driver_info.device;
2919 pIdentifier->subsystem_id = 0;
2920 pIdentifier->revision = 0;
2921 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2922 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2923 memcpy(&pIdentifier->adapter_luid, &adapter->luid, sizeof(pIdentifier->adapter_luid));
2924 pIdentifier->video_memory = adapter->TextureRam;
2925
2926 return WINED3D_OK;
2927}
2928
2929static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2930 const WineD3D_PixelFormat *cfg, const struct wined3d_format_desc *format_desc)
2931{
2932 short redSize, greenSize, blueSize, alphaSize, colorBits;
2933
2934 if(!cfg)
2935 return FALSE;
2936
2937 /* Float formats need FBOs. If FBOs are used this function isn't called */
2938 if (format_desc->Flags & WINED3DFMT_FLAG_FLOAT) return FALSE;
2939
2940 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2941 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2942 {
2943 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2944 return FALSE;
2945 }
2946
2947 if(cfg->redSize < redSize)
2948 return FALSE;
2949
2950 if(cfg->greenSize < greenSize)
2951 return FALSE;
2952
2953 if(cfg->blueSize < blueSize)
2954 return FALSE;
2955
2956 if(cfg->alphaSize < alphaSize)
2957 return FALSE;
2958
2959 return TRUE;
2960 }
2961
2962 /* Probably a RGBA_float or color index mode */
2963 return FALSE;
2964}
2965
2966static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2967 const WineD3D_PixelFormat *cfg, const struct wined3d_format_desc *format_desc)
2968{
2969 short depthSize, stencilSize;
2970 BOOL lockable = FALSE;
2971
2972 if(!cfg)
2973 return FALSE;
2974
2975 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2976 {
2977 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2978 return FALSE;
2979 }
2980
2981 /* Float formats need FBOs. If FBOs are used this function isn't called */
2982 if (format_desc->Flags & WINED3DFMT_FLAG_FLOAT) return FALSE;
2983
2984 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32_FLOAT))
2985 lockable = TRUE;
2986
2987 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2988 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2989 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2990 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2991 return FALSE;
2992
2993 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2994 * allow more stencil bits than requested. */
2995 if(cfg->stencilSize < stencilSize)
2996 return FALSE;
2997
2998 return TRUE;
2999}
3000
3001static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3002 WINED3DFORMAT AdapterFormat,
3003 WINED3DFORMAT RenderTargetFormat,
3004 WINED3DFORMAT DepthStencilFormat) {
3005 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3006 int nCfgs;
3007 const WineD3D_PixelFormat *cfgs;
3008 const struct wined3d_adapter *adapter;
3009 const struct wined3d_format_desc *rt_format_desc;
3010 const struct wined3d_format_desc *ds_format_desc;
3011 int it;
3012
3013 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
3014 This, Adapter,
3015 DeviceType, debug_d3ddevicetype(DeviceType),
3016 AdapterFormat, debug_d3dformat(AdapterFormat),
3017 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
3018 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
3019
3020 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3021 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
3022 return WINED3DERR_INVALIDCALL;
3023 }
3024
3025 adapter = &This->adapters[Adapter];
3026 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
3027 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
3028 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3029 {
3030 if ((rt_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET) &&
3031 (ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) {
3032 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
3033 return WINED3D_OK;
3034 }
3035 }
3036 else
3037 {
3038 cfgs = adapter->cfgs;
3039 nCfgs = adapter->nCfgs;
3040 for (it = 0; it < nCfgs; ++it) {
3041 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
3042 {
3043 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
3044 {
3045 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
3046 return WINED3D_OK;
3047 }
3048 }
3049 }
3050 }
3051 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
3052
3053 return WINED3DERR_NOTAVAILABLE;
3054}
3055
3056static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3057 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
3058{
3059 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3060 const struct wined3d_format_desc *glDesc;
3061 const struct wined3d_adapter *adapter;
3062
3063 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
3064 This,
3065 Adapter,
3066 DeviceType, debug_d3ddevicetype(DeviceType),
3067 SurfaceFormat, debug_d3dformat(SurfaceFormat),
3068 Windowed,
3069 MultiSampleType,
3070 pQualityLevels);
3071
3072 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3073 return WINED3DERR_INVALIDCALL;
3074 }
3075
3076 /* TODO: handle Windowed, add more quality levels */
3077
3078 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
3079 if(pQualityLevels) *pQualityLevels = 1;
3080 return WINED3D_OK;
3081 }
3082
3083 /* By default multisampling is disabled right now as it causes issues
3084 * on some Nvidia driver versions and it doesn't work well in combination
3085 * with FBOs yet. */
3086 if(!wined3d_settings.allow_multisampling)
3087 return WINED3DERR_NOTAVAILABLE;
3088
3089 adapter = &This->adapters[Adapter];
3090 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
3091 if (!glDesc) return WINED3DERR_INVALIDCALL;
3092
3093 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
3094 int i, nCfgs;
3095 const WineD3D_PixelFormat *cfgs;
3096
3097 cfgs = adapter->cfgs;
3098 nCfgs = adapter->nCfgs;
3099 for(i=0; i<nCfgs; i++) {
3100 if(cfgs[i].numSamples != MultiSampleType)
3101 continue;
3102
3103 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
3104 continue;
3105
3106 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
3107
3108 if(pQualityLevels)
3109 *pQualityLevels = 1; /* Guess at a value! */
3110 return WINED3D_OK;
3111 }
3112 }
3113 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
3114 short redSize, greenSize, blueSize, alphaSize, colorBits;
3115 int i, nCfgs;
3116 const WineD3D_PixelFormat *cfgs;
3117
3118 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
3119 {
3120 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
3121 return WINED3DERR_NOTAVAILABLE;
3122 }
3123
3124 cfgs = adapter->cfgs;
3125 nCfgs = adapter->nCfgs;
3126 for(i=0; i<nCfgs; i++) {
3127 if(cfgs[i].numSamples != MultiSampleType)
3128 continue;
3129 if(cfgs[i].redSize != redSize)
3130 continue;
3131 if(cfgs[i].greenSize != greenSize)
3132 continue;
3133 if(cfgs[i].blueSize != blueSize)
3134 continue;
3135 /* Not all drivers report alpha-less formats since they use 32-bit anyway, so accept alpha even if we didn't ask for it. */
3136 if(alphaSize && cfgs[i].alphaSize != alphaSize)
3137 continue;
3138 if(cfgs[i].colorSize != (glDesc->byte_count << 3))
3139 continue;
3140
3141 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
3142
3143 if(pQualityLevels)
3144 *pQualityLevels = 1; /* Guess at a value! */
3145 return WINED3D_OK;
3146 }
3147 }
3148 return WINED3DERR_NOTAVAILABLE;
3149}
3150
3151static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3152 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed)
3153{
3154 HRESULT hr = WINED3DERR_NOTAVAILABLE;
3155 UINT nmodes;
3156
3157 TRACE("iface %p, adapter_idx %u, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
3158 iface, Adapter, debug_d3ddevicetype(DeviceType), debug_d3dformat(DisplayFormat),
3159 debug_d3dformat(BackBufferFormat), Windowed);
3160
3161 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3162 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
3163 return WINED3DERR_INVALIDCALL;
3164 }
3165
3166 /* The task of this function is to check whether a certain display / backbuffer format
3167 * combination is available on the given adapter. In fullscreen mode microsoft specified
3168 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
3169 * and display format should match exactly.
3170 * In windowed mode format conversion can occur and this depends on the driver. When format
3171 * conversion is done, this function should nevertheless fail and applications need to use
3172 * CheckDeviceFormatConversion.
3173 * At the moment we assume that fullscreen and windowed have the same capabilities */
3174
3175 /* There are only 4 display formats */
3176 if (!(DisplayFormat == WINED3DFMT_B5G6R5_UNORM
3177 || DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
3178 || DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
3179 || DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM))
3180 {
3181 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
3182 return WINED3DERR_NOTAVAILABLE;
3183 }
3184
3185 /* If the requested DisplayFormat is not available, don't continue */
3186 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
3187 if(!nmodes) {
3188 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
3189 return WINED3DERR_NOTAVAILABLE;
3190 }
3191
3192 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
3193 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
3194 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
3195 return WINED3DERR_NOTAVAILABLE;
3196 }
3197
3198 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
3199 if (DisplayFormat == WINED3DFMT_B5G6R5_UNORM && BackBufferFormat != WINED3DFMT_B5G6R5_UNORM)
3200 {
3201 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3202 return WINED3DERR_NOTAVAILABLE;
3203 }
3204
3205 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
3206 if (DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
3207 && !(BackBufferFormat == WINED3DFMT_B5G5R5X1_UNORM || BackBufferFormat == WINED3DFMT_B5G5R5A1_UNORM))
3208 {
3209 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3210 return WINED3DERR_NOTAVAILABLE;
3211 }
3212
3213 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
3214 if (DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
3215 && !(BackBufferFormat == WINED3DFMT_B8G8R8X8_UNORM || BackBufferFormat == WINED3DFMT_B8G8R8A8_UNORM))
3216 {
3217 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3218 return WINED3DERR_NOTAVAILABLE;
3219 }
3220
3221 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
3222 if (DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM
3223 && (BackBufferFormat != WINED3DFMT_B10G10R10A2_UNORM || Windowed))
3224 {
3225 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3226 return WINED3DERR_NOTAVAILABLE;
3227 }
3228
3229 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
3230 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
3231 if(FAILED(hr))
3232 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3233
3234 return hr;
3235}
3236
3237
3238/* Check if we support bumpmapping for a format */
3239static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter,
3240 WINED3DDEVTYPE DeviceType, const struct wined3d_format_desc *format_desc)
3241{
3242 switch(format_desc->format)
3243 {
3244 case WINED3DFMT_R8G8_SNORM:
3245 case WINED3DFMT_R16G16_SNORM:
3246 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3247 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3248 case WINED3DFMT_R8G8B8A8_SNORM:
3249 /* Ask the fixed function pipeline implementation if it can deal
3250 * with the conversion. If we've got a GL extension giving native
3251 * support this will be an identity conversion. */
3252 if (adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup))
3253 {
3254 TRACE_(d3d_caps)("[OK]\n");
3255 return TRUE;
3256 }
3257 TRACE_(d3d_caps)("[FAILED]\n");
3258 return FALSE;
3259
3260 default:
3261 TRACE_(d3d_caps)("[FAILED]\n");
3262 return FALSE;
3263 }
3264}
3265
3266/* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
3267static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter,
3268 const struct wined3d_format_desc *display_format_desc, const struct wined3d_format_desc *ds_format_desc)
3269{
3270 int it=0;
3271
3272 /* Only allow depth/stencil formats */
3273 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
3274
3275 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3276 {
3277 /* With FBOs WGL limitations do not apply, but the format needs to be FBO attachable */
3278 if (ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) return TRUE;
3279 }
3280 else
3281 {
3282 /* Walk through all WGL pixel formats to find a match */
3283 for (it = 0; it < adapter->nCfgs; ++it)
3284 {
3285 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
3286 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
3287 {
3288 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
3289 {
3290 return TRUE;
3291 }
3292 }
3293 }
3294 }
3295
3296 return FALSE;
3297}
3298
3299static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3300{
3301 /* The flags entry of a format contains the filtering capability */
3302 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
3303
3304 return FALSE;
3305}
3306
3307/* Check the render target capabilities of a format */
3308static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter,
3309 const struct wined3d_format_desc *adapter_format_desc, const struct wined3d_format_desc *check_format_desc)
3310{
3311 /* Filter out non-RT formats */
3312 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
3313 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
3314 WineD3D_PixelFormat *cfgs = adapter->cfgs;
3315 int it;
3316 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
3317 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
3318
3319 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
3320 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
3321
3322 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
3323 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
3324 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
3325 TRACE_(d3d_caps)("[FAILED]\n");
3326 return FALSE;
3327 }
3328
3329 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
3330 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
3331 for (it = 0; it < adapter->nCfgs; ++it)
3332 {
3333 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
3334 &cfgs[it], check_format_desc))
3335 {
3336 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
3337 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
3338 return TRUE;
3339 }
3340 }
3341 }
3342 else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3343 {
3344 /* For now return TRUE for FBOs until we have some proper checks.
3345 * Note that this function will only be called when the format is around for texturing. */
3346 return TRUE;
3347 }
3348 return FALSE;
3349}
3350
3351static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3352{
3353 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3354
3355 /* Check for supported sRGB formats (Texture loading and framebuffer) */
3356 if (!gl_info->supported[EXT_TEXTURE_SRGB])
3357 {
3358 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
3359 return FALSE;
3360 }
3361
3362 switch (format_desc->format)
3363 {
3364 case WINED3DFMT_B8G8R8A8_UNORM:
3365 case WINED3DFMT_B8G8R8X8_UNORM:
3366 case WINED3DFMT_B4G4R4A4_UNORM:
3367 case WINED3DFMT_L8_UNORM:
3368 case WINED3DFMT_L8A8_UNORM:
3369 case WINED3DFMT_DXT1:
3370 case WINED3DFMT_DXT2:
3371 case WINED3DFMT_DXT3:
3372 case WINED3DFMT_DXT4:
3373 case WINED3DFMT_DXT5:
3374 TRACE_(d3d_caps)("[OK]\n");
3375 return TRUE;
3376
3377 default:
3378 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
3379 return FALSE;
3380 }
3381 return FALSE;
3382}
3383
3384static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter,
3385 WINED3DDEVTYPE DeviceType, const struct wined3d_format_desc *format_desc)
3386{
3387 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
3388 * doing the color fixup in shaders.
3389 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
3390 if ((format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) || (format_desc->format == WINED3DFMT_B8G8R8A8_UNORM))
3391 {
3392 int vs_selected_mode;
3393 int ps_selected_mode;
3394 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3395
3396 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
3397 TRACE_(d3d_caps)("[OK]\n");
3398 return TRUE;
3399 }
3400 }
3401
3402 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
3403 return FALSE;
3404}
3405
3406/* Check if a format support blending in combination with pixel shaders */
3407static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapter,
3408 const struct wined3d_format_desc *format_desc)
3409{
3410 /* The flags entry of a format contains the post pixel shader blending capability */
3411 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
3412
3413 return FALSE;
3414}
3415
3416static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3417{
3418 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
3419 * but we have to report mipmapping so we cannot reject this flag. Tests show that
3420 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
3421 * that wrapping is supported. The lack of filtering will sort out the mipmapping
3422 * capability anyway.
3423 *
3424 * For now lets report this on all formats, but in the future we may want to
3425 * restrict it to some should games need that
3426 */
3427 return TRUE;
3428}
3429
3430/* Check if a texture format is supported on the given adapter */
3431static BOOL CheckTextureCapability(struct wined3d_adapter *adapter,
3432 WINED3DDEVTYPE DeviceType, const struct wined3d_format_desc *format_desc)
3433{
3434 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3435
3436 switch (format_desc->format)
3437 {
3438 /*****
3439 * supported: RGB(A) formats
3440 */
3441 case WINED3DFMT_B8G8R8_UNORM: /* Enable for dx7, blacklisted for 8 and 9 above */
3442 case WINED3DFMT_B8G8R8A8_UNORM:
3443 case WINED3DFMT_B8G8R8X8_UNORM:
3444 case WINED3DFMT_B5G6R5_UNORM:
3445 case WINED3DFMT_B5G5R5X1_UNORM:
3446 case WINED3DFMT_B5G5R5A1_UNORM:
3447 case WINED3DFMT_B4G4R4A4_UNORM:
3448 case WINED3DFMT_A8_UNORM:
3449 case WINED3DFMT_B4G4R4X4_UNORM:
3450 case WINED3DFMT_R8G8B8A8_UNORM:
3451 case WINED3DFMT_R8G8B8X8_UNORM:
3452 case WINED3DFMT_B10G10R10A2_UNORM:
3453 case WINED3DFMT_R10G10B10A2_UNORM:
3454 case WINED3DFMT_R16G16_UNORM:
3455 TRACE_(d3d_caps)("[OK]\n");
3456 return TRUE;
3457
3458 case WINED3DFMT_B2G3R3_UNORM:
3459 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
3460 return FALSE;
3461
3462 /*****
3463 * Not supported: Palettized
3464 * Only some Geforce/Voodoo3/G400 cards offer 8-bit textures in case of <=Direct3D7.
3465 * Since it is not widely available, don't offer it. Further no Windows driver offers
3466 * WINED3DFMT_P8_UINT_A8_NORM, so don't offer it either.
3467 */
3468 case WINED3DFMT_P8_UINT:
3469 case WINED3DFMT_P8_UINT_A8_UNORM:
3470 return FALSE;
3471
3472 /*****
3473 * Supported: (Alpha)-Luminance
3474 */
3475 case WINED3DFMT_L8_UNORM:
3476 case WINED3DFMT_L8A8_UNORM:
3477 case WINED3DFMT_L16_UNORM:
3478 TRACE_(d3d_caps)("[OK]\n");
3479 return TRUE;
3480
3481 /* Not supported on Windows, thus disabled */
3482 case WINED3DFMT_L4A4_UNORM:
3483 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
3484 return FALSE;
3485
3486 /*****
3487 * Supported: Depth/Stencil formats
3488 */
3489 case WINED3DFMT_D16_LOCKABLE:
3490 case WINED3DFMT_D16_UNORM:
3491 case WINED3DFMT_S1_UINT_D15_UNORM:
3492 case WINED3DFMT_X8D24_UNORM:
3493 case WINED3DFMT_S4X4_UINT_D24_UNORM:
3494 case WINED3DFMT_D24_UNORM_S8_UINT:
3495 case WINED3DFMT_S8_UINT_D24_FLOAT:
3496 case WINED3DFMT_D32_UNORM:
3497 case WINED3DFMT_D32_FLOAT:
3498 return TRUE;
3499
3500 /*****
3501 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
3502 * GL_NV_texture_shader). Emulated by shaders
3503 */
3504 case WINED3DFMT_R8G8_SNORM:
3505 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3506 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3507 case WINED3DFMT_R8G8B8A8_SNORM:
3508 case WINED3DFMT_R16G16_SNORM:
3509 /* Ask the shader backend if it can deal with the conversion. If
3510 * we've got a GL extension giving native support this will be an
3511 * identity conversion. */
3512 if (adapter->shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
3513 {
3514 TRACE_(d3d_caps)("[OK]\n");
3515 return TRUE;
3516 }
3517 TRACE_(d3d_caps)("[FAILED]\n");
3518 return FALSE;
3519
3520 case WINED3DFMT_DXT1:
3521 case WINED3DFMT_DXT2:
3522 case WINED3DFMT_DXT3:
3523 case WINED3DFMT_DXT4:
3524 case WINED3DFMT_DXT5:
3525 if (gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC])
3526 {
3527 TRACE_(d3d_caps)("[OK]\n");
3528 return TRUE;
3529 }
3530 TRACE_(d3d_caps)("[FAILED]\n");
3531 return FALSE;
3532
3533
3534 /*****
3535 * Odd formats - not supported
3536 */
3537 case WINED3DFMT_VERTEXDATA:
3538 case WINED3DFMT_R16_UINT:
3539 case WINED3DFMT_R32_UINT:
3540 case WINED3DFMT_R16G16B16A16_SNORM:
3541 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM:
3542 case WINED3DFMT_R10G11B11_SNORM:
3543 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3544 return FALSE;
3545
3546 /*****
3547 * WINED3DFMT_R8G8_SNORM_Cx: Not supported right now
3548 */
3549 case WINED3DFMT_R8G8_SNORM_Cx:
3550 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3551 return FALSE;
3552
3553 /* YUV formats */
3554 case WINED3DFMT_UYVY:
3555 case WINED3DFMT_YUY2:
3556 if (gl_info->supported[APPLE_YCBCR_422])
3557 {
3558 TRACE_(d3d_caps)("[OK]\n");
3559 return TRUE;
3560 }
3561 TRACE_(d3d_caps)("[FAILED]\n");
3562 return FALSE;
3563 case WINED3DFMT_YV12:
3564 TRACE_(d3d_caps)("[FAILED]\n");
3565 return FALSE;
3566
3567 /* Not supported */
3568 case WINED3DFMT_R16G16B16A16_UNORM:
3569 case WINED3DFMT_B2G3R3A8_UNORM:
3570 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3571 return FALSE;
3572
3573 /* Floating point formats */
3574 case WINED3DFMT_R16_FLOAT:
3575 case WINED3DFMT_R16G16_FLOAT:
3576 case WINED3DFMT_R16G16B16A16_FLOAT:
3577 if (gl_info->supported[ARB_TEXTURE_FLOAT] && gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3578 {
3579 TRACE_(d3d_caps)("[OK]\n");
3580 return TRUE;
3581 }
3582 TRACE_(d3d_caps)("[FAILED]\n");
3583 return FALSE;
3584
3585 case WINED3DFMT_R32_FLOAT:
3586 case WINED3DFMT_R32G32_FLOAT:
3587 case WINED3DFMT_R32G32B32A32_FLOAT:
3588 if (gl_info->supported[ARB_TEXTURE_FLOAT])
3589 {
3590 TRACE_(d3d_caps)("[OK]\n");
3591 return TRUE;
3592 }
3593 TRACE_(d3d_caps)("[FAILED]\n");
3594 return FALSE;
3595
3596 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3597 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3598 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3599 * We can do instancing with all shader versions, but we need vertex shaders.
3600 *
3601 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3602 * to enable instancing. WineD3D doesn't need that and just ignores it.
3603 *
3604 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3605 */
3606 case WINED3DFMT_INST:
3607 TRACE("ATI Instancing check hack\n");
3608 if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
3609 {
3610 TRACE_(d3d_caps)("[OK]\n");
3611 return TRUE;
3612 }
3613 TRACE_(d3d_caps)("[FAILED]\n");
3614 return FALSE;
3615
3616 /* Some weird FOURCC formats */
3617 case WINED3DFMT_R8G8_B8G8:
3618 case WINED3DFMT_G8R8_G8B8:
3619 case WINED3DFMT_MULTI2_ARGB8:
3620 TRACE_(d3d_caps)("[FAILED]\n");
3621 return FALSE;
3622
3623 /* Vendor specific formats */
3624 case WINED3DFMT_ATI2N:
3625 if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC]
3626 || gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
3627 {
3628 if (adapter->shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3629 && adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup))
3630 {
3631 TRACE_(d3d_caps)("[OK]\n");
3632 return TRUE;
3633 }
3634
3635 TRACE_(d3d_caps)("[OK]\n");
3636 return TRUE;
3637 }
3638 TRACE_(d3d_caps)("[FAILED]\n");
3639 return FALSE;
3640
3641 case WINED3DFMT_NVHU:
3642 case WINED3DFMT_NVHS:
3643 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3644 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3645 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3646 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3647 * Applications have to deal with not having NVHS and NVHU.
3648 */
3649 TRACE_(d3d_caps)("[FAILED]\n");
3650 return FALSE;
3651
3652 case WINED3DFMT_UNKNOWN:
3653 return FALSE;
3654
3655 default:
3656 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3657 break;
3658 }
3659 return FALSE;
3660}
3661
3662static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter,
3663 const struct wined3d_format_desc *adapter_format_desc,
3664 WINED3DDEVTYPE DeviceType, const struct wined3d_format_desc *check_format_desc,
3665 WINED3DSURFTYPE SurfaceType)
3666{
3667 if(SurfaceType == SURFACE_GDI) {
3668 switch(check_format_desc->format)
3669 {
3670 case WINED3DFMT_B8G8R8_UNORM:
3671 case WINED3DFMT_B8G8R8A8_UNORM:
3672 case WINED3DFMT_B8G8R8X8_UNORM:
3673 case WINED3DFMT_B5G6R5_UNORM:
3674 case WINED3DFMT_B5G5R5X1_UNORM:
3675 case WINED3DFMT_B5G5R5A1_UNORM:
3676 case WINED3DFMT_B4G4R4A4_UNORM:
3677 case WINED3DFMT_B2G3R3_UNORM:
3678 case WINED3DFMT_A8_UNORM:
3679 case WINED3DFMT_B2G3R3A8_UNORM:
3680 case WINED3DFMT_B4G4R4X4_UNORM:
3681 case WINED3DFMT_R10G10B10A2_UNORM:
3682 case WINED3DFMT_R8G8B8A8_UNORM:
3683 case WINED3DFMT_R8G8B8X8_UNORM:
3684 case WINED3DFMT_R16G16_UNORM:
3685 case WINED3DFMT_B10G10R10A2_UNORM:
3686 case WINED3DFMT_R16G16B16A16_UNORM:
3687 case WINED3DFMT_P8_UINT:
3688 TRACE_(d3d_caps)("[OK]\n");
3689 return TRUE;
3690 default:
3691 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3692 return FALSE;
3693 }
3694 }
3695
3696 /* All format that are supported for textures are supported for surfaces as well */
3697 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3698 /* All depth stencil formats are supported on surfaces */
3699 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3700
3701 /* If opengl can't process the format natively, the blitter may be able to convert it */
3702 if (adapter->blitter->blit_supported(&adapter->gl_info, BLIT_OP_BLIT,
3703 NULL, WINED3DPOOL_DEFAULT, 0, check_format_desc,
3704 NULL, WINED3DPOOL_DEFAULT, 0, adapter_format_desc))
3705 {
3706 TRACE_(d3d_caps)("[OK]\n");
3707 return TRUE;
3708 }
3709
3710 /* Reject other formats */
3711 TRACE_(d3d_caps)("[FAILED]\n");
3712 return FALSE;
3713}
3714
3715static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter,
3716 const struct wined3d_format_desc *format_desc)
3717{
3718 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3719
3720 if (!gl_info->limits.vertex_samplers)
3721 {
3722 TRACE_(d3d_caps)("[FAILED]\n");
3723 return FALSE;
3724 }
3725
3726 switch (format_desc->format)
3727 {
3728 case WINED3DFMT_R32G32B32A32_FLOAT:
3729 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
3730 {
3731 TRACE_(d3d_caps)("[FAILED]\n");
3732 return FALSE;
3733 }
3734 TRACE_(d3d_caps)("[OK]\n");
3735 return TRUE;
3736
3737 default:
3738 TRACE_(d3d_caps)("[FAILED]\n");
3739 return FALSE;
3740 }
3741 return FALSE;
3742}
3743
3744static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3745 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3746 WINED3DSURFTYPE SurfaceType)
3747{
3748 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3749 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3750 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3751 const struct wined3d_format_desc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3752 const struct wined3d_format_desc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3753 DWORD UsageCaps = 0;
3754
3755 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3756 This,
3757 Adapter,
3758 DeviceType, debug_d3ddevicetype(DeviceType),
3759 AdapterFormat, debug_d3dformat(AdapterFormat),
3760 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3761 RType, debug_d3dresourcetype(RType),
3762 CheckFormat, debug_d3dformat(CheckFormat));
3763
3764 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3765 return WINED3DERR_INVALIDCALL;
3766 }
3767
3768 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3769
3770 if(SurfaceType != SURFACE_OPENGL) {
3771 TRACE("[FAILED]\n");
3772 return WINED3DERR_NOTAVAILABLE;
3773 }
3774
3775 /* Cubetexture allows:
3776 * - D3DUSAGE_AUTOGENMIPMAP
3777 * - D3DUSAGE_DEPTHSTENCIL
3778 * - D3DUSAGE_DYNAMIC
3779 * - D3DUSAGE_NONSECURE (d3d9ex)
3780 * - D3DUSAGE_RENDERTARGET
3781 * - D3DUSAGE_SOFTWAREPROCESSING
3782 * - D3DUSAGE_QUERY_WRAPANDMIP
3783 */
3784 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3785 {
3786 /* Check if the texture format is around */
3787 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3788 {
3789 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3790 /* Check for automatic mipmap generation support */
3791 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3792 {
3793 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3794 } else {
3795 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3796 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3797 }
3798 }
3799
3800 /* Always report dynamic locking */
3801 if(Usage & WINED3DUSAGE_DYNAMIC)
3802 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3803
3804 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3805 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3806 {
3807 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3808 } else {
3809 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3810 return WINED3DERR_NOTAVAILABLE;
3811 }
3812 }
3813
3814 /* Always report software processing */
3815 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3816 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3817
3818 /* Check QUERY_FILTER support */
3819 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3820 if (CheckFilterCapability(adapter, format_desc))
3821 {
3822 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3823 } else {
3824 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3825 return WINED3DERR_NOTAVAILABLE;
3826 }
3827 }
3828
3829 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3830 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3831 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3832 {
3833 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3834 } else {
3835 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3836 return WINED3DERR_NOTAVAILABLE;
3837 }
3838 }
3839
3840 /* Check QUERY_SRGBREAD support */
3841 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3842 if (CheckSrgbReadCapability(adapter, format_desc))
3843 {
3844 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3845 } else {
3846 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3847 return WINED3DERR_NOTAVAILABLE;
3848 }
3849 }
3850
3851 /* Check QUERY_SRGBWRITE support */
3852 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3853 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3854 {
3855 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3856 } else {
3857 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3858 return WINED3DERR_NOTAVAILABLE;
3859 }
3860 }
3861
3862 /* Check QUERY_VERTEXTEXTURE support */
3863 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3864 if (CheckVertexTextureCapability(adapter, format_desc))
3865 {
3866 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3867 } else {
3868 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3869 return WINED3DERR_NOTAVAILABLE;
3870 }
3871 }
3872
3873 /* Check QUERY_WRAPANDMIP support */
3874 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3875 if (CheckWrapAndMipCapability(adapter, format_desc))
3876 {
3877 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3878 } else {
3879 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3880 return WINED3DERR_NOTAVAILABLE;
3881 }
3882 }
3883 } else {
3884 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3885 return WINED3DERR_NOTAVAILABLE;
3886 }
3887 } else {
3888 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3889 return WINED3DERR_NOTAVAILABLE;
3890 }
3891 } else if(RType == WINED3DRTYPE_SURFACE) {
3892 /* Surface allows:
3893 * - D3DUSAGE_DEPTHSTENCIL
3894 * - D3DUSAGE_NONSECURE (d3d9ex)
3895 * - D3DUSAGE_RENDERTARGET
3896 */
3897
3898 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3899 {
3900 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3901 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3902 {
3903 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3904 } else {
3905 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3906 return WINED3DERR_NOTAVAILABLE;
3907 }
3908 }
3909
3910 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3911 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3912 {
3913 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3914 } else {
3915 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3916 return WINED3DERR_NOTAVAILABLE;
3917 }
3918 }
3919
3920 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3921 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3922 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3923 {
3924 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3925 } else {
3926 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3927 return WINED3DERR_NOTAVAILABLE;
3928 }
3929 }
3930 } else {
3931 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3932 return WINED3DERR_NOTAVAILABLE;
3933 }
3934
3935 } else if(RType == WINED3DRTYPE_TEXTURE) {
3936 /* Texture allows:
3937 * - D3DUSAGE_AUTOGENMIPMAP
3938 * - D3DUSAGE_DEPTHSTENCIL
3939 * - D3DUSAGE_DMAP
3940 * - D3DUSAGE_DYNAMIC
3941 * - D3DUSAGE_NONSECURE (d3d9ex)
3942 * - D3DUSAGE_RENDERTARGET
3943 * - D3DUSAGE_SOFTWAREPROCESSING
3944 * - D3DUSAGE_TEXTAPI (d3d9ex)
3945 * - D3DUSAGE_QUERY_WRAPANDMIP
3946 */
3947
3948 if(SurfaceType != SURFACE_OPENGL) {
3949 TRACE("[FAILED]\n");
3950 return WINED3DERR_NOTAVAILABLE;
3951 }
3952
3953 /* Check if the texture format is around */
3954 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3955 {
3956 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3957 /* Check for automatic mipmap generation support */
3958 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3959 {
3960 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3961 } else {
3962 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3963 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3964 }
3965 }
3966
3967 /* Always report dynamic locking */
3968 if(Usage & WINED3DUSAGE_DYNAMIC)
3969 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3970
3971 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3972 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3973 {
3974 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3975 } else {
3976 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3977 return WINED3DERR_NOTAVAILABLE;
3978 }
3979 }
3980
3981 /* Always report software processing */
3982 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3983 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3984
3985 /* Check QUERY_FILTER support */
3986 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3987 if (CheckFilterCapability(adapter, format_desc))
3988 {
3989 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3990 } else {
3991 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3992 return WINED3DERR_NOTAVAILABLE;
3993 }
3994 }
3995
3996 /* Check QUERY_LEGACYBUMPMAP support */
3997 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3998 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3999 {
4000 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
4001 } else {
4002 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
4003 return WINED3DERR_NOTAVAILABLE;
4004 }
4005 }
4006
4007 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
4008 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
4009 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
4010 {
4011 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
4012 } else {
4013 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
4014 return WINED3DERR_NOTAVAILABLE;
4015 }
4016 }
4017
4018 /* Check QUERY_SRGBREAD support */
4019 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
4020 if (CheckSrgbReadCapability(adapter, format_desc))
4021 {
4022 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
4023 } else {
4024 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
4025 return WINED3DERR_NOTAVAILABLE;
4026 }
4027 }
4028
4029 /* Check QUERY_SRGBWRITE support */
4030 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
4031 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
4032 {
4033 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
4034 } else {
4035 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
4036 return WINED3DERR_NOTAVAILABLE;
4037 }
4038 }
4039
4040 /* Check QUERY_VERTEXTEXTURE support */
4041 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
4042 if (CheckVertexTextureCapability(adapter, format_desc))
4043 {
4044 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
4045 } else {
4046 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
4047 return WINED3DERR_NOTAVAILABLE;
4048 }
4049 }
4050
4051 /* Check QUERY_WRAPANDMIP support */
4052 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
4053 if (CheckWrapAndMipCapability(adapter, format_desc))
4054 {
4055 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
4056 } else {
4057 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
4058 return WINED3DERR_NOTAVAILABLE;
4059 }
4060 }
4061
4062 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
4063 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
4064 {
4065 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
4066 } else {
4067 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
4068 return WINED3DERR_NOTAVAILABLE;
4069 }
4070 }
4071 } else {
4072 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
4073 return WINED3DERR_NOTAVAILABLE;
4074 }
4075 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
4076 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
4077 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
4078 *
4079 * Volumetexture allows:
4080 * - D3DUSAGE_DYNAMIC
4081 * - D3DUSAGE_NONSECURE (d3d9ex)
4082 * - D3DUSAGE_SOFTWAREPROCESSING
4083 * - D3DUSAGE_QUERY_WRAPANDMIP
4084 */
4085
4086 if(SurfaceType != SURFACE_OPENGL) {
4087 TRACE("[FAILED]\n");
4088 return WINED3DERR_NOTAVAILABLE;
4089 }
4090
4091 /* Check volume texture and volume usage caps */
4092 if (gl_info->supported[EXT_TEXTURE3D])
4093 {
4094 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
4095 {
4096 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
4097 return WINED3DERR_NOTAVAILABLE;
4098 }
4099
4100 /* Always report dynamic locking */
4101 if(Usage & WINED3DUSAGE_DYNAMIC)
4102 UsageCaps |= WINED3DUSAGE_DYNAMIC;
4103
4104 /* Always report software processing */
4105 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
4106 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
4107
4108 /* Check QUERY_FILTER support */
4109 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
4110 if (CheckFilterCapability(adapter, format_desc))
4111 {
4112 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
4113 } else {
4114 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
4115 return WINED3DERR_NOTAVAILABLE;
4116 }
4117 }
4118
4119 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
4120 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
4121 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
4122 {
4123 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
4124 } else {
4125 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
4126 return WINED3DERR_NOTAVAILABLE;
4127 }
4128 }
4129
4130 /* Check QUERY_SRGBREAD support */
4131 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
4132 if (CheckSrgbReadCapability(adapter, format_desc))
4133 {
4134 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
4135 } else {
4136 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
4137 return WINED3DERR_NOTAVAILABLE;
4138 }
4139 }
4140
4141 /* Check QUERY_SRGBWRITE support */
4142 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
4143 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
4144 {
4145 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
4146 } else {
4147 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
4148 return WINED3DERR_NOTAVAILABLE;
4149 }
4150 }
4151
4152 /* Check QUERY_VERTEXTEXTURE support */
4153 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
4154 if (CheckVertexTextureCapability(adapter, format_desc))
4155 {
4156 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
4157 } else {
4158 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
4159 return WINED3DERR_NOTAVAILABLE;
4160 }
4161 }
4162
4163 /* Check QUERY_WRAPANDMIP support */
4164 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
4165 if (CheckWrapAndMipCapability(adapter, format_desc))
4166 {
4167 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
4168 } else {
4169 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
4170 return WINED3DERR_NOTAVAILABLE;
4171 }
4172 }
4173 } else {
4174 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
4175 return WINED3DERR_NOTAVAILABLE;
4176 }
4177
4178 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
4179 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
4180 * app needing one of those formats, don't advertize them to avoid leading apps into
4181 * temptation. The windows drivers don't support most of those formats on volumes anyway,
4182 * except of R32F.
4183 */
4184 switch(CheckFormat) {
4185 case WINED3DFMT_P8_UINT:
4186 case WINED3DFMT_L4A4_UNORM:
4187 case WINED3DFMT_R32_FLOAT:
4188 case WINED3DFMT_R16_FLOAT:
4189 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
4190 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
4191 case WINED3DFMT_R16G16_UNORM:
4192 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4193 return WINED3DERR_NOTAVAILABLE;
4194
4195 case WINED3DFMT_R8G8B8A8_SNORM:
4196 case WINED3DFMT_R16G16_SNORM:
4197 if (!gl_info->supported[NV_TEXTURE_SHADER])
4198 {
4199 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4200 return WINED3DERR_NOTAVAILABLE;
4201 }
4202 break;
4203
4204 case WINED3DFMT_R8G8_SNORM:
4205 if (!gl_info->supported[NV_TEXTURE_SHADER])
4206 {
4207 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4208 return WINED3DERR_NOTAVAILABLE;
4209 }
4210 break;
4211
4212 case WINED3DFMT_DXT1:
4213 case WINED3DFMT_DXT2:
4214 case WINED3DFMT_DXT3:
4215 case WINED3DFMT_DXT4:
4216 case WINED3DFMT_DXT5:
4217 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
4218 * compressed texture results in an error. While the D3D refrast does
4219 * support s3tc volumes, at least the nvidia windows driver does not, so
4220 * we're free not to support this format.
4221 */
4222 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
4223 return WINED3DERR_NOTAVAILABLE;
4224
4225 default:
4226 /* Do nothing, continue with checking the format below */
4227 break;
4228 }
4229 } else if(RType == WINED3DRTYPE_BUFFER){
4230 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
4231 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
4232 return WINED3DERR_NOTAVAILABLE;
4233 }
4234
4235 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
4236 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
4237 * usage flags match. */
4238 if(UsageCaps == Usage) {
4239 return WINED3D_OK;
4240 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
4241 return WINED3DOK_NOAUTOGEN;
4242 } else {
4243 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);
4244 return WINED3DERR_NOTAVAILABLE;
4245 }
4246}
4247
4248static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT adapter_idx,
4249 WINED3DDEVTYPE device_type, WINED3DFORMAT src_format, WINED3DFORMAT dst_format)
4250{
4251 FIXME("iface %p, adapter_idx %u, device_type %s, src_format %s, dst_format %s stub!\n",
4252 iface, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(src_format),
4253 debug_d3dformat(dst_format));
4254
4255 return WINED3D_OK;
4256}
4257
4258/* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
4259 subset of a D3DCAPS9 structure. However, it has to come via a void *
4260 as the d3d8 interface cannot import the d3d9 header */
4261static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
4262
4263 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4264 struct wined3d_adapter *adapter = &This->adapters[Adapter];
4265 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4266 int vs_selected_mode;
4267 int ps_selected_mode;
4268 struct shader_caps shader_caps;
4269 struct fragment_caps fragment_caps;
4270 DWORD ckey_caps, blit_caps, fx_caps;
4271
4272 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
4273
4274 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
4275 return WINED3DERR_INVALIDCALL;
4276 }
4277
4278 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
4279
4280 /* ------------------------------------------------
4281 The following fields apply to both d3d8 and d3d9
4282 ------------------------------------------------ */
4283 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
4284 pCaps->AdapterOrdinal = Adapter;
4285
4286 pCaps->Caps = 0;
4287 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
4288 WINED3DCAPS2_FULLSCREENGAMMA |
4289 WINED3DCAPS2_DYNAMICTEXTURES;
4290 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
4291 {
4292 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
4293 }
4294
4295 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
4296 WINED3DCAPS3_COPY_TO_VIDMEM |
4297 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
4298
4299 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
4300 WINED3DPRESENT_INTERVAL_ONE;
4301
4302 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
4303 WINED3DCURSORCAPS_LOWRES;
4304
4305 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
4306 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
4307 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
4308 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4309 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
4310 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
4311 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
4312 WINED3DDEVCAPS_PUREDEVICE |
4313 WINED3DDEVCAPS_HWRASTERIZATION |
4314 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
4315 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
4316 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
4317 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
4318 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
4319 WINED3DDEVCAPS_RTPATCHES;
4320
4321 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
4322 WINED3DPMISCCAPS_CULLCCW |
4323 WINED3DPMISCCAPS_CULLCW |
4324 WINED3DPMISCCAPS_COLORWRITEENABLE |
4325 WINED3DPMISCCAPS_CLIPTLVERTS |
4326 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
4327 WINED3DPMISCCAPS_MASKZ |
4328 WINED3DPMISCCAPS_BLENDOP |
4329 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
4330 /* TODO:
4331 WINED3DPMISCCAPS_NULLREFERENCE
4332 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
4333 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
4334 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
4335
4336 if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
4337 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
4338 if (gl_info->supported[EXT_DRAW_BUFFERS2])
4339 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS;
4340
4341 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
4342 WINED3DPRASTERCAPS_PAT |
4343 WINED3DPRASTERCAPS_WFOG |
4344 WINED3DPRASTERCAPS_ZFOG |
4345 WINED3DPRASTERCAPS_FOGVERTEX |
4346 WINED3DPRASTERCAPS_FOGTABLE |
4347 WINED3DPRASTERCAPS_STIPPLE |
4348 WINED3DPRASTERCAPS_SUBPIXEL |
4349 WINED3DPRASTERCAPS_ZTEST |
4350 WINED3DPRASTERCAPS_SCISSORTEST |
4351 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
4352 WINED3DPRASTERCAPS_DEPTHBIAS;
4353
4354 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4355 {
4356 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
4357 WINED3DPRASTERCAPS_ZBIAS |
4358 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
4359 }
4360 if (gl_info->supported[NV_FOG_DISTANCE])
4361 {
4362 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
4363 }
4364 /* FIXME Add:
4365 WINED3DPRASTERCAPS_COLORPERSPECTIVE
4366 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
4367 WINED3DPRASTERCAPS_ANTIALIASEDGES
4368 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
4369 WINED3DPRASTERCAPS_WBUFFER */
4370
4371 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
4372 WINED3DPCMPCAPS_EQUAL |
4373 WINED3DPCMPCAPS_GREATER |
4374 WINED3DPCMPCAPS_GREATEREQUAL |
4375 WINED3DPCMPCAPS_LESS |
4376 WINED3DPCMPCAPS_LESSEQUAL |
4377 WINED3DPCMPCAPS_NEVER |
4378 WINED3DPCMPCAPS_NOTEQUAL;
4379
4380 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
4381 WINED3DPBLENDCAPS_BOTHSRCALPHA |
4382 WINED3DPBLENDCAPS_DESTALPHA |
4383 WINED3DPBLENDCAPS_DESTCOLOR |
4384 WINED3DPBLENDCAPS_INVDESTALPHA |
4385 WINED3DPBLENDCAPS_INVDESTCOLOR |
4386 WINED3DPBLENDCAPS_INVSRCALPHA |
4387 WINED3DPBLENDCAPS_INVSRCCOLOR |
4388 WINED3DPBLENDCAPS_ONE |
4389 WINED3DPBLENDCAPS_SRCALPHA |
4390 WINED3DPBLENDCAPS_SRCALPHASAT |
4391 WINED3DPBLENDCAPS_SRCCOLOR |
4392 WINED3DPBLENDCAPS_ZERO;
4393
4394 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
4395 WINED3DPBLENDCAPS_DESTCOLOR |
4396 WINED3DPBLENDCAPS_INVDESTALPHA |
4397 WINED3DPBLENDCAPS_INVDESTCOLOR |
4398 WINED3DPBLENDCAPS_INVSRCALPHA |
4399 WINED3DPBLENDCAPS_INVSRCCOLOR |
4400 WINED3DPBLENDCAPS_ONE |
4401 WINED3DPBLENDCAPS_SRCALPHA |
4402 WINED3DPBLENDCAPS_SRCCOLOR |
4403 WINED3DPBLENDCAPS_ZERO;
4404 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
4405 * according to the glBlendFunc manpage
4406 *
4407 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
4408 * legacy settings for srcblend only
4409 */
4410
4411 if (gl_info->supported[EXT_BLEND_COLOR])
4412 {
4413 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
4414 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
4415 }
4416
4417
4418 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
4419 WINED3DPCMPCAPS_EQUAL |
4420 WINED3DPCMPCAPS_GREATER |
4421 WINED3DPCMPCAPS_GREATEREQUAL |
4422 WINED3DPCMPCAPS_LESS |
4423 WINED3DPCMPCAPS_LESSEQUAL |
4424 WINED3DPCMPCAPS_NEVER |
4425 WINED3DPCMPCAPS_NOTEQUAL;
4426
4427 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
4428 WINED3DPSHADECAPS_COLORGOURAUDRGB |
4429 WINED3DPSHADECAPS_ALPHAFLATBLEND |
4430 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
4431 WINED3DPSHADECAPS_COLORFLATRGB |
4432 WINED3DPSHADECAPS_FOGFLAT |
4433 WINED3DPSHADECAPS_FOGGOURAUD |
4434 WINED3DPSHADECAPS_SPECULARFLATRGB;
4435
4436 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
4437 WINED3DPTEXTURECAPS_ALPHAPALETTE |
4438 WINED3DPTEXTURECAPS_TRANSPARENCY |
4439 WINED3DPTEXTURECAPS_BORDER |
4440 WINED3DPTEXTURECAPS_MIPMAP |
4441 WINED3DPTEXTURECAPS_PROJECTED |
4442 WINED3DPTEXTURECAPS_PERSPECTIVE;
4443
4444 if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
4445 {
4446 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
4447 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
4448 }
4449
4450 if (gl_info->supported[EXT_TEXTURE3D])
4451 {
4452 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
4453 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
4454 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
4455 }
4456
4457 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4458 {
4459 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
4460 WINED3DPTEXTURECAPS_MIPCUBEMAP |
4461 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
4462
4463 }
4464
4465 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4466 WINED3DPTFILTERCAPS_MAGFPOINT |
4467 WINED3DPTFILTERCAPS_MINFLINEAR |
4468 WINED3DPTFILTERCAPS_MINFPOINT |
4469 WINED3DPTFILTERCAPS_MIPFLINEAR |
4470 WINED3DPTFILTERCAPS_MIPFPOINT |
4471 WINED3DPTFILTERCAPS_LINEAR |
4472 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4473 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4474 WINED3DPTFILTERCAPS_MIPLINEAR |
4475 WINED3DPTFILTERCAPS_MIPNEAREST |
4476 WINED3DPTFILTERCAPS_NEAREST;
4477
4478 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4479 {
4480 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4481 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4482 }
4483
4484 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4485 {
4486 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4487 WINED3DPTFILTERCAPS_MAGFPOINT |
4488 WINED3DPTFILTERCAPS_MINFLINEAR |
4489 WINED3DPTFILTERCAPS_MINFPOINT |
4490 WINED3DPTFILTERCAPS_MIPFLINEAR |
4491 WINED3DPTFILTERCAPS_MIPFPOINT |
4492 WINED3DPTFILTERCAPS_LINEAR |
4493 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4494 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4495 WINED3DPTFILTERCAPS_MIPLINEAR |
4496 WINED3DPTFILTERCAPS_MIPNEAREST |
4497 WINED3DPTFILTERCAPS_NEAREST;
4498
4499 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4500 {
4501 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4502 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4503 }
4504 } else
4505 pCaps->CubeTextureFilterCaps = 0;
4506
4507 if (gl_info->supported[EXT_TEXTURE3D])
4508 {
4509 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4510 WINED3DPTFILTERCAPS_MAGFPOINT |
4511 WINED3DPTFILTERCAPS_MINFLINEAR |
4512 WINED3DPTFILTERCAPS_MINFPOINT |
4513 WINED3DPTFILTERCAPS_MIPFLINEAR |
4514 WINED3DPTFILTERCAPS_MIPFPOINT |
4515 WINED3DPTFILTERCAPS_LINEAR |
4516 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4517 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4518 WINED3DPTFILTERCAPS_MIPLINEAR |
4519 WINED3DPTFILTERCAPS_MIPNEAREST |
4520 WINED3DPTFILTERCAPS_NEAREST;
4521 } else
4522 pCaps->VolumeTextureFilterCaps = 0;
4523
4524 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4525 WINED3DPTADDRESSCAPS_CLAMP |
4526 WINED3DPTADDRESSCAPS_WRAP;
4527
4528 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4529 {
4530 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4531 }
4532 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4533 {
4534 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4535 }
4536 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4537 {
4538 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4539 }
4540
4541 if (gl_info->supported[EXT_TEXTURE3D])
4542 {
4543 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4544 WINED3DPTADDRESSCAPS_CLAMP |
4545 WINED3DPTADDRESSCAPS_WRAP;
4546 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4547 {
4548 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4549 }
4550 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4551 {
4552 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4553 }
4554 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4555 {
4556 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4557 }
4558 } else
4559 pCaps->VolumeTextureAddressCaps = 0;
4560
4561 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4562 WINED3DLINECAPS_ZTEST |
4563 WINED3DLINECAPS_BLEND |
4564 WINED3DLINECAPS_ALPHACMP |
4565 WINED3DLINECAPS_FOG;
4566 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4567 * idea how generating the smoothing alpha values works; the result is different
4568 */
4569
4570 pCaps->MaxTextureWidth = gl_info->limits.texture_size;
4571 pCaps->MaxTextureHeight = gl_info->limits.texture_size;
4572
4573 if (gl_info->supported[EXT_TEXTURE3D])
4574 pCaps->MaxVolumeExtent = gl_info->limits.texture3d_size;
4575 else
4576 pCaps->MaxVolumeExtent = 0;
4577
4578 pCaps->MaxTextureRepeat = 32768;
4579 pCaps->MaxTextureAspectRatio = gl_info->limits.texture_size;
4580 pCaps->MaxVertexW = 1.0f;
4581
4582 pCaps->GuardBandLeft = 0.0f;
4583 pCaps->GuardBandTop = 0.0f;
4584 pCaps->GuardBandRight = 0.0f;
4585 pCaps->GuardBandBottom = 0.0f;
4586
4587 pCaps->ExtentsAdjust = 0.0f;
4588
4589 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4590 WINED3DSTENCILCAPS_INCRSAT |
4591 WINED3DSTENCILCAPS_INVERT |
4592 WINED3DSTENCILCAPS_KEEP |
4593 WINED3DSTENCILCAPS_REPLACE |
4594 WINED3DSTENCILCAPS_ZERO;
4595 if (gl_info->supported[EXT_STENCIL_WRAP])
4596 {
4597 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4598 WINED3DSTENCILCAPS_INCR;
4599 }
4600 if (gl_info->supported[EXT_STENCIL_TWO_SIDE] || gl_info->supported[ATI_SEPARATE_STENCIL])
4601 {
4602 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4603 }
4604
4605 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4606
4607 pCaps->MaxUserClipPlanes = gl_info->limits.clipplanes;
4608 pCaps->MaxActiveLights = gl_info->limits.lights;
4609
4610 pCaps->MaxVertexBlendMatrices = gl_info->limits.blends;
4611 pCaps->MaxVertexBlendMatrixIndex = 0;
4612
4613 pCaps->MaxAnisotropy = gl_info->limits.anisotropy;
4614 pCaps->MaxPointSize = gl_info->limits.pointsize_max;
4615
4616
4617 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4618 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4619 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4620 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4621 WINED3DVTXPCAPS_LOCALVIEWER |
4622 WINED3DVTXPCAPS_VERTEXFOG |
4623 WINED3DVTXPCAPS_TEXGEN;
4624
4625 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4626 pCaps->MaxVertexIndex = 0xFFFFF;
4627 pCaps->MaxStreams = MAX_STREAMS;
4628 pCaps->MaxStreamStride = 1024;
4629
4630 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4631 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4632 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4633 pCaps->MaxNpatchTessellationLevel = 0;
4634 pCaps->MasterAdapterOrdinal = 0;
4635 pCaps->AdapterOrdinalInGroup = 0;
4636 pCaps->NumberOfAdaptersInGroup = 1;
4637
4638 pCaps->NumSimultaneousRTs = gl_info->limits.buffers;
4639
4640 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4641 WINED3DPTFILTERCAPS_MAGFPOINT |
4642 WINED3DPTFILTERCAPS_MINFLINEAR |
4643 WINED3DPTFILTERCAPS_MAGFLINEAR;
4644 pCaps->VertexTextureFilterCaps = 0;
4645
4646 memset(&shader_caps, 0, sizeof(shader_caps));
4647 adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
4648
4649 memset(&fragment_caps, 0, sizeof(fragment_caps));
4650 adapter->fragment_pipe->get_caps(&adapter->gl_info, &fragment_caps);
4651
4652 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4653 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4654
4655 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4656 * Ignore shader model capabilities if disabled in config
4657 */
4658 if(vs_selected_mode == SHADER_NONE) {
4659 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4660 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4661 pCaps->MaxVertexShaderConst = 0;
4662 } else {
4663 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4664 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4665 }
4666
4667 if(ps_selected_mode == SHADER_NONE) {
4668 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4669 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4670 pCaps->PixelShader1xMaxValue = 0.0f;
4671 } else {
4672 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4673 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4674 }
4675
4676 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4677 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4678 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4679
4680 pCaps->VS20Caps = shader_caps.VS20Caps;
4681 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4682 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4683 pCaps->PS20Caps = shader_caps.PS20Caps;
4684 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4685 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4686
4687 /* The following caps are shader specific, but they are things we cannot detect, or which
4688 * are the same among all shader models. So to avoid code duplication set the shader version
4689 * specific, but otherwise constant caps here
4690 */
4691 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4692 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4693 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4694 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4695 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4696 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_vs_temps);
4697 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4698
4699 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4700 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
4701 }
4702 else if (pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0))
4703 {
4704 pCaps->VS20Caps.Caps = 0;
4705 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4706 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_vs_temps);
4707 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4708
4709 pCaps->MaxVShaderInstructionsExecuted = 65535;
4710 pCaps->MaxVertexShader30InstructionSlots = 0;
4711 } else { /* VS 1.x */
4712 pCaps->VS20Caps.Caps = 0;
4713 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4714 pCaps->VS20Caps.NumTemps = 0;
4715 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4716
4717 pCaps->MaxVShaderInstructionsExecuted = 0;
4718 pCaps->MaxVertexShader30InstructionSlots = 0;
4719 }
4720
4721 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4722 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4723 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4724
4725 /* 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 */
4726 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4727 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4728 WINED3DPS20CAPS_PREDICATION |
4729 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4730 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4731 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4732 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_ps_temps);
4733 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4734 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4735
4736 pCaps->MaxPShaderInstructionsExecuted = 65535;
4737 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS,
4738 adapter->gl_info.limits.arb_ps_instructions);
4739 }
4740 else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0))
4741 {
4742 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4743 pCaps->PS20Caps.Caps = 0;
4744 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4745 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_ps_temps);
4746 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4747 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4748
4749 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4750 pCaps->MaxPixelShader30InstructionSlots = 0;
4751 } else { /* PS 1.x */
4752 pCaps->PS20Caps.Caps = 0;
4753 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4754 pCaps->PS20Caps.NumTemps = 0;
4755 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4756 pCaps->PS20Caps.NumInstructionSlots = 0;
4757
4758 pCaps->MaxPShaderInstructionsExecuted = 0;
4759 pCaps->MaxPixelShader30InstructionSlots = 0;
4760 }
4761
4762 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4763 /* OpenGL supports all the formats below, perhaps not always
4764 * without conversion, but it supports them.
4765 * Further GLSL doesn't seem to have an official unsigned type so
4766 * don't advertise it yet as I'm not sure how we handle it.
4767 * We might need to add some clamping in the shader engine to
4768 * support it.
4769 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4770 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4771 WINED3DDTCAPS_UBYTE4N |
4772 WINED3DDTCAPS_SHORT2N |
4773 WINED3DDTCAPS_SHORT4N;
4774 if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
4775 {
4776 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4777 WINED3DDTCAPS_FLOAT16_4;
4778 }
4779 } else
4780 pCaps->DeclTypes = 0;
4781
4782 /* Set DirectDraw helper Caps */
4783 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4784 WINEDDCKEYCAPS_SRCBLT;
4785 fx_caps = WINEDDFXCAPS_BLTALPHA |
4786 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4787 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4788 WINEDDFXCAPS_BLTROTATION90 |
4789 WINEDDFXCAPS_BLTSHRINKX |
4790 WINEDDFXCAPS_BLTSHRINKXN |
4791 WINEDDFXCAPS_BLTSHRINKY |
4792 WINEDDFXCAPS_BLTSHRINKXN |
4793 WINEDDFXCAPS_BLTSTRETCHX |
4794 WINEDDFXCAPS_BLTSTRETCHXN |
4795 WINEDDFXCAPS_BLTSTRETCHY |
4796 WINEDDFXCAPS_BLTSTRETCHYN;
4797 blit_caps = WINEDDCAPS_BLT |
4798 WINEDDCAPS_BLTCOLORFILL |
4799 WINEDDCAPS_BLTDEPTHFILL |
4800 WINEDDCAPS_BLTSTRETCH |
4801 WINEDDCAPS_CANBLTSYSMEM |
4802 WINEDDCAPS_CANCLIP |
4803 WINEDDCAPS_CANCLIPSTRETCHED |
4804 WINEDDCAPS_COLORKEY |
4805 WINEDDCAPS_COLORKEYHWASSIST |
4806 WINEDDCAPS_ALIGNBOUNDARYSRC;
4807
4808 /* Fill the ddraw caps structure */
4809 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4810 WINEDDCAPS_PALETTE |
4811 blit_caps;
4812 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4813 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4814 WINEDDCAPS2_PRIMARYGAMMA |
4815 WINEDDCAPS2_WIDESURFACES |
4816 WINEDDCAPS2_CANRENDERWINDOWED;
4817 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4818 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4819 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4820 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4821 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4822 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4823 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4824 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4825 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4826
4827 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4828 WINEDDSCAPS_BACKBUFFER |
4829 WINEDDSCAPS_FLIP |
4830 WINEDDSCAPS_FRONTBUFFER |
4831 WINEDDSCAPS_OFFSCREENPLAIN |
4832 WINEDDSCAPS_PALETTE |
4833 WINEDDSCAPS_PRIMARYSURFACE |
4834 WINEDDSCAPS_SYSTEMMEMORY |
4835 WINEDDSCAPS_VIDEOMEMORY |
4836 WINEDDSCAPS_VISIBLE;
4837 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4838
4839 /* Set D3D caps if OpenGL is available. */
4840 if (adapter->opengl)
4841 {
4842 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4843 WINEDDSCAPS_MIPMAP |
4844 WINEDDSCAPS_TEXTURE |
4845 WINEDDSCAPS_ZBUFFER;
4846 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4847 }
4848
4849 return WINED3D_OK;
4850}
4851
4852static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT adapter_idx,
4853 WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, IUnknown *parent,
4854 IWineD3DDeviceParent *device_parent, IWineD3DDevice **device)
4855{
4856 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4857 IWineD3DDeviceImpl *object;
4858 HRESULT hr;
4859
4860 TRACE("iface %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x.\n"
4861 "parent %p, device_parent %p, device %p.\n",
4862 iface, adapter_idx, device_type, focus_window, flags,
4863 parent, device_parent, device);
4864
4865 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4866 * number and create a device without a 3D adapter for 2D only operation. */
4867 if (IWineD3D_GetAdapterCount(iface) && adapter_idx >= IWineD3D_GetAdapterCount(iface))
4868 {
4869 return WINED3DERR_INVALIDCALL;
4870 }
4871
4872 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4873 if (!object)
4874 {
4875 ERR("Failed to allocate device memory.\n");
4876 return E_OUTOFMEMORY;
4877 }
4878
4879 hr = device_init(object, This, adapter_idx, device_type, focus_window, flags, parent, device_parent);
4880 if (FAILED(hr))
4881 {
4882 WARN("Failed to initialize device, hr %#x.\n", hr);
4883 HeapFree(GetProcessHeap(), 0, object);
4884 return hr;
4885 }
4886
4887 TRACE("Created device %p.\n", object);
4888 *device = (IWineD3DDevice *)object;
4889
4890 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *device);
4891
4892 return WINED3D_OK;
4893}
4894
4895static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4896 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4897 IUnknown_AddRef(This->parent);
4898 *pParent = This->parent;
4899 return WINED3D_OK;
4900}
4901
4902static void WINE_GLAPI invalid_func(const void *data)
4903{
4904 ERR("Invalid vertex attribute function called\n");
4905 DebugBreak();
4906}
4907
4908static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4909{
4910 ERR("Invalid texcoord function called\n");
4911 DebugBreak();
4912}
4913
4914/* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4915 * the extension detection and are used in drawStridedSlow
4916 */
4917static void WINE_GLAPI position_d3dcolor(const void *data)
4918{
4919 DWORD pos = *((const DWORD *)data);
4920
4921 FIXME("Add a test for fixed function position from d3dcolor type\n");
4922 glVertex4s(D3DCOLOR_B_R(pos),
4923 D3DCOLOR_B_G(pos),
4924 D3DCOLOR_B_B(pos),
4925 D3DCOLOR_B_A(pos));
4926}
4927
4928static void WINE_GLAPI position_float4(const void *data)
4929{
4930 const GLfloat *pos = data;
4931
4932 if (pos[3] != 0.0f && pos[3] != 1.0f)
4933 {
4934 float w = 1.0f / pos[3];
4935
4936 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4937 }
4938 else
4939 {
4940 glVertex3fv(pos);
4941 }
4942}
4943
4944static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4945{
4946 DWORD diffuseColor = *((const DWORD *)data);
4947
4948 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4949 D3DCOLOR_B_G(diffuseColor),
4950 D3DCOLOR_B_B(diffuseColor),
4951 D3DCOLOR_B_A(diffuseColor));
4952}
4953
4954static void WINE_GLAPI specular_d3dcolor(const void *data)
4955{
4956 DWORD specularColor = *((const DWORD *)data);
4957 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4958 D3DCOLOR_B_G(specularColor),
4959 D3DCOLOR_B_B(specularColor)};
4960
4961 specular_func_3ubv(d);
4962}
4963
4964static void WINE_GLAPI warn_no_specular_func(const void *data)
4965{
4966 WARN("GL_EXT_secondary_color not supported\n");
4967}
4968
4969static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4970{
4971 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4972 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4973 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4974 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4975 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4976 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4977 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4978 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4979 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4980 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4981 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4982 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4983 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4984 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4985 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4986 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4987 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4988
4989 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4990 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4991 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4992 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4993 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4994 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4995 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4996 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4997 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4998 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4999 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
5000 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
5001 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
5002 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
5003 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
5004 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
5005 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
5006
5007 /* No 4 component entry points here */
5008 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
5009 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
5010 if (gl_info->supported[EXT_SECONDARY_COLOR])
5011 {
5012 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
5013 }
5014 else
5015 {
5016 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
5017 }
5018 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
5019 if (gl_info->supported[EXT_SECONDARY_COLOR])
5020 {
5021 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
5022 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
5023 }
5024 else
5025 {
5026 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
5027 }
5028 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
5029 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
5030 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
5031 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
5032 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
5033 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
5034 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
5035 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
5036 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
5037 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
5038 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
5039 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
5040
5041 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
5042 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
5043 */
5044 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
5045 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
5046 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
5047 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
5048 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
5049 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
5050 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
5051 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
5052 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
5053 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
5054 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
5055 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
5056 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
5057 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
5058 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
5059 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
5060 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
5061
5062 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
5063 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
5064 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
5065 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
5066 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
5067 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
5068 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
5069 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
5070 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
5071 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
5072 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
5073 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
5074 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
5075 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
5076 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
5077 if (gl_info->supported[NV_HALF_FLOAT])
5078 {
5079 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
5080 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
5081 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
5082 } else {
5083 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
5084 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
5085 }
5086}
5087
5088static BOOL InitAdapters(IWineD3DImpl *This)
5089{
5090 static HMODULE mod_gl;
5091 BOOL ret;
5092 int ps_selected_mode, vs_selected_mode;
5093
5094 /* No need to hold any lock. The calling library makes sure only one thread calls
5095 * wined3d simultaneously
5096 */
5097
5098 TRACE("Initializing adapters\n");
5099
5100 if(!mod_gl) {
5101#ifdef USE_WIN32_OPENGL
5102#define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
5103#ifdef VBOX_WITH_WDDM
5104 BOOL (APIENTRY *pDrvValidateVersion)(DWORD) DECLSPEC_HIDDEN;
5105 mod_gl = LoadLibraryA("VBoxOGL.dll");
5106#else
5107 mod_gl = LoadLibraryA("opengl32.dll");
5108#endif
5109 if(!mod_gl) {
5110 ERR("Can't load opengl32.dll!\n");
5111 goto nogl_adapter;
5112 }
5113#ifdef VBOX_WITH_WDDM
5114 /* init properly */
5115 pDrvValidateVersion = (void*)GetProcAddress(mod_gl, "DrvValidateVersion");
5116 if(!pDrvValidateVersion) {
5117 ERR("Can't get DrvValidateVersion\n");
5118 goto nogl_adapter;
5119 }
5120 if(!pDrvValidateVersion(1)) {
5121 ERR("DrvValidateVersion FAILED\n");
5122 goto nogl_adapter;
5123 }
5124#endif
5125#else
5126#define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
5127 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
5128 mod_gl = GetModuleHandleA("gdi32.dll");
5129#endif
5130 }
5131
5132/* Load WGL core functions from opengl32.dll */
5133#define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
5134 WGL_FUNCS_GEN;
5135#undef USE_WGL_FUNC
5136
5137 if(!pwglGetProcAddress) {
5138 ERR("Unable to load wglGetProcAddress!\n");
5139 goto nogl_adapter;
5140 }
5141
5142/* Dynamically load all GL core functions */
5143 GL_FUNCS_GEN;
5144#undef USE_GL_FUNC
5145
5146 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
5147 * otherwise because we have to use winex11.drv's override
5148 */
5149#ifdef USE_WIN32_OPENGL
5150 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
5151 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
5152#else
5153 wglFinish = (void*)pwglGetProcAddress("wglFinish");
5154 wglFlush = (void*)pwglGetProcAddress("wglFlush");
5155#endif
5156
5157 glEnableWINE = glEnable;
5158 glDisableWINE = glDisable;
5159
5160 /* For now only one default adapter */
5161 {
5162 struct wined3d_adapter *adapter = &This->adapters[0];
5163 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
5164 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
5165 int iPixelFormat;
5166 int res;
5167 int i;
5168 WineD3D_PixelFormat *cfgs;
5169 DISPLAY_DEVICEW DisplayDevice;
5170 HDC hdc;
5171
5172 TRACE("Initializing default adapter\n");
5173 adapter->ordinal = 0;
5174 adapter->monitorPoint.x = -1;
5175 adapter->monitorPoint.y = -1;
5176
5177 if (!AllocateLocallyUniqueId(&adapter->luid))
5178 {
5179 DWORD err = GetLastError();
5180 ERR("Failed to set adapter LUID (%#x).\n", err);
5181 goto nogl_adapter;
5182 }
5183 TRACE("Allocated LUID %08x:%08x for adapter.\n",
5184 adapter->luid.HighPart, adapter->luid.LowPart);
5185
5186 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
5187 {
5188 ERR("Failed to get a gl context for default adapter\n");
5189 goto nogl_adapter;
5190 }
5191
5192 ret = IWineD3DImpl_FillGLCaps(adapter);
5193 if(!ret) {
5194 ERR("Failed to initialize gl caps for default adapter\n");
5195 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5196 goto nogl_adapter;
5197 }
5198 ret = initPixelFormats(&adapter->gl_info, adapter->driver_info.vendor);
5199 if(!ret) {
5200 ERR("Failed to init gl formats\n");
5201 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5202 goto nogl_adapter;
5203 }
5204
5205 hdc = fake_gl_ctx.dc;
5206
5207 /* Use the VideoRamSize registry setting when set */
5208 if(wined3d_settings.emulated_textureram)
5209 adapter->TextureRam = wined3d_settings.emulated_textureram;
5210 else
5211 adapter->TextureRam = adapter->gl_info.vidmem;
5212 adapter->UsedTextureRam = 0;
5213 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
5214
5215 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
5216 DisplayDevice.cb = sizeof(DisplayDevice);
5217 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
5218 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
5219 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
5220
5221 if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
5222 {
5223 int attribute;
5224 int attribs[11];
5225 int values[11];
5226 int nAttribs = 0;
5227
5228 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
5229 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
5230
5231 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
5232 cfgs = adapter->cfgs;
5233 attribs[nAttribs++] = WGL_RED_BITS_ARB;
5234 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
5235 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
5236 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
5237 attribs[nAttribs++] = WGL_COLOR_BITS_ARB;
5238 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
5239 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
5240 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
5241 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
5242 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
5243 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
5244
5245 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
5246 {
5247 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
5248
5249 if(!res)
5250 continue;
5251
5252 /* Cache the pixel format */
5253 cfgs->iPixelFormat = iPixelFormat;
5254 cfgs->redSize = values[0];
5255 cfgs->greenSize = values[1];
5256 cfgs->blueSize = values[2];
5257 cfgs->alphaSize = values[3];
5258 cfgs->colorSize = values[4];
5259 cfgs->depthSize = values[5];
5260 cfgs->stencilSize = values[6];
5261 cfgs->windowDrawable = values[7];
5262 cfgs->iPixelType = values[8];
5263 cfgs->doubleBuffer = values[9];
5264 cfgs->auxBuffers = values[10];
5265
5266 cfgs->numSamples = 0;
5267 /* Check multisample support */
5268 if (gl_info->supported[ARB_MULTISAMPLE])
5269 {
5270 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
5271 int value[2];
5272 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
5273 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
5274 * value[1] = number of multi sample buffers*/
5275 if(value[0])
5276 cfgs->numSamples = value[1];
5277 }
5278 }
5279
5280 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
5281 "depth=%d, stencil=%d, samples=%d, windowDrawable=%d\n",
5282 cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer,
5283 cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize,
5284 cfgs->depthSize, cfgs->stencilSize, cfgs->numSamples, cfgs->windowDrawable);
5285 cfgs++;
5286 }
5287 }
5288 else
5289 {
5290 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
5291 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
5292 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
5293
5294 cfgs = adapter->cfgs;
5295 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
5296 {
5297 PIXELFORMATDESCRIPTOR ppfd;
5298
5299 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
5300 if(!res)
5301 continue;
5302
5303 /* We only want HW acceleration using an OpenGL ICD driver.
5304 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
5305 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
5306 */
5307 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
5308 {
5309 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
5310 continue;
5311 }
5312
5313 cfgs->iPixelFormat = iPixelFormat;
5314 cfgs->redSize = ppfd.cRedBits;
5315 cfgs->greenSize = ppfd.cGreenBits;
5316 cfgs->blueSize = ppfd.cBlueBits;
5317 cfgs->alphaSize = ppfd.cAlphaBits;
5318 cfgs->colorSize = ppfd.cColorBits;
5319 cfgs->depthSize = ppfd.cDepthBits;
5320 cfgs->stencilSize = ppfd.cStencilBits;
5321 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
5322 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
5323 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
5324 cfgs->auxBuffers = ppfd.cAuxBuffers;
5325 cfgs->numSamples = 0;
5326
5327 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
5328 "depth=%d, stencil=%d, windowDrawable=%d\n",
5329 cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer,
5330 cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize,
5331 cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable);
5332 cfgs++;
5333 adapter->nCfgs++;
5334 }
5335
5336 /* 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 */
5337 if(!adapter->nCfgs)
5338 {
5339 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
5340
5341 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5342 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
5343 goto nogl_adapter;
5344 }
5345 }
5346
5347 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
5348 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
5349 * but just fake it using D24(X8?) which is fine. D3D also allows that.
5350 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
5351 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
5352 * driver is allowed to consume more bits EXCEPT for stencil bits.
5353 *
5354 * Mark an adapter with this broken stencil behavior.
5355 */
5356 adapter->brokenStencil = TRUE;
5357 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
5358 {
5359 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
5360 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
5361 adapter->brokenStencil = FALSE;
5362 break;
5363 }
5364 }
5365
5366 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5367
5368 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
5369 fillGLAttribFuncs(&adapter->gl_info);
5370 adapter->opengl = TRUE;
5371 }
5372 This->adapter_count = 1;
5373 TRACE("%u adapters successfully initialized\n", This->adapter_count);
5374
5375 return TRUE;
5376
5377nogl_adapter:
5378 /* Initialize an adapter for ddraw-only memory counting */
5379 memset(This->adapters, 0, sizeof(This->adapters));
5380 This->adapters[0].ordinal = 0;
5381 This->adapters[0].opengl = FALSE;
5382 This->adapters[0].monitorPoint.x = -1;
5383 This->adapters[0].monitorPoint.y = -1;
5384
5385 This->adapters[0].driver_info.name = "Display";
5386 This->adapters[0].driver_info.description = "WineD3D DirectDraw Emulation";
5387 if(wined3d_settings.emulated_textureram) {
5388 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
5389 } else {
5390 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
5391 }
5392
5393 initPixelFormatsNoGL(&This->adapters[0].gl_info);
5394
5395 This->adapter_count = 1;
5396 return FALSE;
5397}
5398
5399/**********************************************************
5400 * IWineD3D VTbl follows
5401 **********************************************************/
5402
5403static const struct IWineD3DVtbl IWineD3D_Vtbl =
5404{
5405 /* IUnknown */
5406 IWineD3DImpl_QueryInterface,
5407 IWineD3DImpl_AddRef,
5408 IWineD3DImpl_Release,
5409 /* IWineD3D */
5410 IWineD3DImpl_GetParent,
5411 IWineD3DImpl_GetAdapterCount,
5412 IWineD3DImpl_RegisterSoftwareDevice,
5413 IWineD3DImpl_GetAdapterMonitor,
5414 IWineD3DImpl_GetAdapterModeCount,
5415 IWineD3DImpl_EnumAdapterModes,
5416 IWineD3DImpl_GetAdapterDisplayMode,
5417 IWineD3DImpl_GetAdapterIdentifier,
5418 IWineD3DImpl_CheckDeviceMultiSampleType,
5419 IWineD3DImpl_CheckDepthStencilMatch,
5420 IWineD3DImpl_CheckDeviceType,
5421 IWineD3DImpl_CheckDeviceFormat,
5422 IWineD3DImpl_CheckDeviceFormatConversion,
5423 IWineD3DImpl_GetDeviceCaps,
5424 IWineD3DImpl_CreateDevice
5425};
5426
5427static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
5428
5429const struct wined3d_parent_ops wined3d_null_parent_ops =
5430{
5431 wined3d_null_wined3d_object_destroyed,
5432};
5433
5434HRESULT wined3d_init(IWineD3DImpl *wined3d, UINT version, IUnknown *parent)
5435{
5436 wined3d->lpVtbl = &IWineD3D_Vtbl;
5437 wined3d->dxVersion = version;
5438 wined3d->ref = 1;
5439 wined3d->parent = parent;
5440
5441 if (!InitAdapters(wined3d))
5442 {
5443 WARN("Failed to initialize adapters.\n");
5444 if (version > 7)
5445 {
5446 MESSAGE("Direct3D%u is not available without OpenGL.\n", version);
5447 return E_FAIL;
5448 }
5449 }
5450
5451 return WINED3D_OK;
5452}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette