VirtualBox

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

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

wddm: VBOXWDDM->VBOX_WITH_WDDM

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

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