VirtualBox

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

Last change on this file since 29710 was 29452, checked in by vboxsync, 15 years ago

wddm/3d: make wine directly use VBoxOGL.dll instead of opengl32.dll

  • 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 while (*GL_Extensions)
2185 {
2186 const char *start;
2187 char current_ext[256];
2188
2189 while (isspace(*GL_Extensions)) ++GL_Extensions;
2190 start = GL_Extensions;
2191 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
2192
2193 len = GL_Extensions - start;
2194 if (!len || len >= sizeof(current_ext)) continue;
2195
2196 memcpy(current_ext, start, len);
2197 current_ext[len] = '\0';
2198 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
2199
2200 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
2201 {
2202 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
2203 {
2204 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
2205 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
2206 break;
2207 }
2208 }
2209 }
2210
2211 /* Now work out what GL support this card really has */
2212#define USE_GL_FUNC(type, pfn, ext, replace) \
2213{ \
2214 DWORD ver = ver_for_ext(ext); \
2215 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
2216 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
2217 else gl_info->pfn = NULL; \
2218}
2219 GL_EXT_FUNCS_GEN;
2220#undef USE_GL_FUNC
2221
2222#define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
2223 WGL_EXT_FUNCS_GEN;
2224#undef USE_GL_FUNC
2225
2226 ENTER_GL();
2227
2228 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
2229 * loading the functions, otherwise the code above will load the extension entry points instead of the
2230 * core functions, which may not work. */
2231 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
2232 {
2233 if (!gl_info->supported[EXTENSION_MAP[i].extension]
2234 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
2235 {
2236 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
2237 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
2238 }
2239 }
2240
2241 if (gl_info->supported[APPLE_FENCE])
2242 {
2243 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
2244 * The apple extension interacts with some other apple exts. Disable the NV
2245 * extension if the apple one is support to prevent confusion in other parts
2246 * of the code. */
2247 gl_info->supported[NV_FENCE] = FALSE;
2248 }
2249 if (gl_info->supported[APPLE_FLOAT_PIXELS])
2250 {
2251 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
2252 *
2253 * The enums are the same:
2254 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
2255 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
2256 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
2257 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
2258 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
2259 */
2260 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
2261 {
2262 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
2263 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
2264 }
2265 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
2266 {
2267 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
2268 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
2269 }
2270 }
2271 if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
2272 {
2273 /* GL_ARB_map_buffer_range and GL_APPLE_flush_buffer_range provide the same
2274 * functionality. Prefer the ARB extension */
2275 gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] = FALSE;
2276 }
2277 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
2278 {
2279 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
2280 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
2281 }
2282 if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
2283 {
2284 TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
2285 gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
2286 }
2287 if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && gl_info->supported[EXT_VERTEX_ARRAY_BGRA])
2288 {
2289 TRACE_(d3d_caps)(" IMPLIED: ARB_vertex_array_bgra support (by EXT_vertex_array_bgra).\n");
2290 gl_info->supported[ARB_VERTEX_ARRAY_BGRA] = TRUE;
2291 }
2292 if (gl_info->supported[NV_TEXTURE_SHADER2])
2293 {
2294 if (gl_info->supported[NV_REGISTER_COMBINERS])
2295 {
2296 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
2297 * are supported. The nv extensions provide the same functionality as the
2298 * ATI one, and a bit more(signed pixelformats). */
2299 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
2300 }
2301 }
2302
2303 if (gl_info->supported[NV_REGISTER_COMBINERS])
2304 {
2305 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
2306 gl_info->limits.general_combiners = gl_max;
2307 TRACE_(d3d_caps)("Max general combiners: %d.\n", gl_max);
2308 }
2309 if (gl_info->supported[ARB_DRAW_BUFFERS])
2310 {
2311 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
2312 gl_info->limits.buffers = gl_max;
2313 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
2314 }
2315 if (gl_info->supported[ARB_MULTITEXTURE])
2316 {
2317 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
2318 gl_info->limits.textures = min(MAX_TEXTURES, gl_max);
2319 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->limits.textures);
2320
2321 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
2322 {
2323 GLint tmp;
2324 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2325 gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
2326 }
2327 else
2328 {
2329 gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, gl_max);
2330 }
2331 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers);
2332
2333 if (gl_info->supported[ARB_VERTEX_SHADER])
2334 {
2335 GLint tmp;
2336 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2337 gl_info->limits.vertex_samplers = tmp;
2338 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
2339 gl_info->limits.combined_samplers = tmp;
2340
2341 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
2342 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
2343 * an issue because then the sampler setup only depends on the two shaders. If a pixel
2344 * shader is used with fixed function vertex processing we're fine too because fixed function
2345 * vertex processing doesn't use any samplers. If fixed function fragment processing is
2346 * used we have to make sure that all vertex sampler setups are valid together with all
2347 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
2348 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
2349 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
2350 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
2351 * a fixed function pipeline anymore.
2352 *
2353 * So this is just a check to check that our assumption holds true. If not, write a warning
2354 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
2355 if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12
2356 && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers)
2357 {
2358 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
2359 gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers);
2360 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
2361 if (gl_info->limits.combined_samplers > MAX_TEXTURES)
2362 gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES;
2363 else
2364 gl_info->limits.vertex_samplers = 0;
2365 }
2366 }
2367 else
2368 {
2369 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers;
2370 }
2371 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers);
2372 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->limits.combined_samplers);
2373 }
2374 if (gl_info->supported[ARB_VERTEX_BLEND])
2375 {
2376 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
2377 gl_info->limits.blends = gl_max;
2378 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->limits.blends);
2379 }
2380 if (gl_info->supported[EXT_TEXTURE3D])
2381 {
2382 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
2383 gl_info->limits.texture3d_size = gl_max;
2384 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->limits.texture3d_size);
2385 }
2386 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
2387 {
2388 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
2389 gl_info->limits.anisotropy = gl_max;
2390 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->limits.anisotropy);
2391 }
2392 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
2393 {
2394 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
2395 gl_info->limits.arb_ps_float_constants = gl_max;
2396 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants);
2397 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
2398 gl_info->limits.arb_ps_native_constants = gl_max;
2399 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n",
2400 gl_info->limits.arb_ps_native_constants);
2401 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
2402 gl_info->limits.arb_ps_temps = gl_max;
2403 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps);
2404 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
2405 gl_info->limits.arb_ps_instructions = gl_max;
2406 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions);
2407 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
2408 gl_info->limits.arb_ps_local_constants = gl_max;
2409 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions);
2410 }
2411 if (gl_info->supported[ARB_VERTEX_PROGRAM])
2412 {
2413 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
2414 gl_info->limits.arb_vs_float_constants = gl_max;
2415 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants);
2416 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
2417 gl_info->limits.arb_vs_native_constants = gl_max;
2418 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native float constants: %d.\n",
2419 gl_info->limits.arb_vs_native_constants);
2420 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
2421 gl_info->limits.arb_vs_temps = gl_max;
2422 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps);
2423 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
2424 gl_info->limits.arb_vs_instructions = gl_max;
2425 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions);
2426
2427 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
2428 }
2429 if (gl_info->supported[ARB_VERTEX_SHADER])
2430 {
2431 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
2432 gl_info->limits.glsl_vs_float_constants = gl_max / 4;
2433 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
2434 }
2435 if (gl_info->supported[ARB_FRAGMENT_SHADER])
2436 {
2437 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
2438 gl_info->limits.glsl_ps_float_constants = gl_max / 4;
2439 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants);
2440 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
2441 gl_info->limits.glsl_varyings = gl_max;
2442 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
2443 }
2444 if (gl_info->supported[ARB_SHADING_LANGUAGE_100])
2445 {
2446 const char *str = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
2447 unsigned int major, minor;
2448
2449 TRACE_(d3d_caps)("GLSL version string: %s.\n", debugstr_a(str));
2450
2451 /* The format of the GLSL version string is "major.minor[.release] [vendor info]". */
2452 sscanf(str, "%u.%u", &major, &minor);
2453 gl_info->glsl_version = MAKEDWORD_VERSION(major, minor);
2454 }
2455 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
2456 {
2457 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess);
2458 }
2459 else
2460 {
2461 gl_info->limits.shininess = 128.0f;
2462 }
2463 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
2464 {
2465 /* If we have full NP2 texture support, disable
2466 * GL_ARB_texture_rectangle because we will never use it.
2467 * This saves a few redundant glDisable calls. */
2468 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
2469 }
2470 if (gl_info->supported[ATI_FRAGMENT_SHADER])
2471 {
2472 /* Disable NV_register_combiners and fragment shader if this is supported.
2473 * generally the NV extensions are preferred over the ATI ones, and this
2474 * extension is disabled if register_combiners and texture_shader2 are both
2475 * supported. So we reach this place only if we have incomplete NV dxlevel 8
2476 * fragment processing support. */
2477 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
2478 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
2479 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
2480 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
2481 }
2482 if (gl_info->supported[NV_HALF_FLOAT])
2483 {
2484 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
2485 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
2486 }
2487 if (gl_info->supported[ARB_POINT_SPRITE])
2488 {
2489 gl_info->limits.point_sprite_units = gl_info->limits.textures;
2490 }
2491 else
2492 {
2493 gl_info->limits.point_sprite_units = 0;
2494 }
2495 checkGLcall("extension detection");
2496
2497 LEAVE_GL();
2498
2499 adapter->fragment_pipe = select_fragment_implementation(adapter);
2500 adapter->shader_backend = select_shader_backend(adapter);
2501 adapter->blitter = select_blit_implementation(adapter);
2502
2503 adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
2504 gl_info->limits.texture_stages = fragment_caps.MaxTextureBlendStages;
2505 TRACE_(d3d_caps)("Max texture stages: %u.\n", gl_info->limits.texture_stages);
2506
2507 /* In some cases the number of texture stages can be larger than the number
2508 * of samplers. The GF4 for example can use only 2 samplers (no fragment
2509 * shaders), but 8 texture stages (register combiners). */
2510 gl_info->limits.sampler_stages = max(gl_info->limits.fragment_samplers, gl_info->limits.texture_stages);
2511
2512 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
2513 {
2514 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbuffer;
2515 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbuffer;
2516 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffers;
2517 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffers;
2518 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorage;
2519 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisample;
2520 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameteriv;
2521 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebuffer;
2522 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebuffer;
2523 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffers;
2524 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffers;
2525 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatus;
2526 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1D;
2527 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2D;
2528 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3D;
2529 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbuffer;
2530 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameteriv;
2531 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebuffer;
2532 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmap;
2533 }
2534 else
2535 {
2536 if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT])
2537 {
2538 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbufferEXT;
2539 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbufferEXT;
2540 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffersEXT;
2541 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffersEXT;
2542 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorageEXT;
2543 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameterivEXT;
2544 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebufferEXT;
2545 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebufferEXT;
2546 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffersEXT;
2547 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffersEXT;
2548 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatusEXT;
2549 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1DEXT;
2550 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2DEXT;
2551 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3DEXT;
2552 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbufferEXT;
2553 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameterivEXT;
2554 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmapEXT;
2555 }
2556 else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2557 {
2558 WARN_(d3d_caps)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
2559 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
2560 }
2561 if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
2562 {
2563 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebufferEXT;
2564 }
2565 if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
2566 {
2567 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisampleEXT;
2568 }
2569 }
2570
2571 /* MRTs are currently only supported when FBOs are used. */
2572 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
2573 {
2574 gl_info->limits.buffers = 1;
2575 }
2576
2577 gl_vendor = wined3d_guess_gl_vendor(gl_info, gl_vendor_str, gl_renderer_str);
2578 card_vendor = wined3d_guess_card_vendor(gl_vendor_str, gl_renderer_str);
2579 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x/0x%04x)\n", debugstr_a(gl_vendor_str), gl_vendor, card_vendor);
2580
2581 device = wined3d_guess_card(gl_info, gl_renderer_str, &gl_vendor, &card_vendor, &vidmem);
2582 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", card_vendor, device);
2583
2584 /* If we have an estimate use it, else default to 64MB; */
2585 if(vidmem)
2586 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
2587 else
2588 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
2589
2590 gl_info->wrap_lookup[WINED3DTADDRESS_WRAP - WINED3DTADDRESS_WRAP] = GL_REPEAT;
2591 gl_info->wrap_lookup[WINED3DTADDRESS_MIRROR - WINED3DTADDRESS_WRAP] =
2592 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
2593 gl_info->wrap_lookup[WINED3DTADDRESS_CLAMP - WINED3DTADDRESS_WRAP] = GL_CLAMP_TO_EDGE;
2594 gl_info->wrap_lookup[WINED3DTADDRESS_BORDER - WINED3DTADDRESS_WRAP] =
2595 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2596 gl_info->wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP] =
2597 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
2598
2599 /* Make sure there's an active HDC else the WGL extensions will fail */
2600 hdc = pwglGetCurrentDC();
2601 if (hdc) {
2602 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2603 if(GL_EXTCALL(wglGetExtensionsStringARB))
2604 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2605
2606 if (NULL == WGL_Extensions) {
2607 ERR(" WGL_Extensions returns NULL\n");
2608 } else {
2609 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2610 while (*WGL_Extensions != 0x00) {
2611 const char *Start;
2612 char ThisExtn[256];
2613
2614 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2615 Start = WGL_Extensions;
2616 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2617 WGL_Extensions++;
2618 }
2619
2620 len = WGL_Extensions - Start;
2621 if (len == 0 || len >= sizeof(ThisExtn))
2622 continue;
2623
2624 memcpy(ThisExtn, Start, len);
2625 ThisExtn[len] = '\0';
2626 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
2627
2628 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2629 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2630 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2631 }
2632 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2633 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2634 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2635 }
2636 }
2637 }
2638 }
2639
2640 fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device);
2641 init_driver_info(driver_info, card_vendor, device);
2642 add_gl_compat_wrappers(gl_info);
2643
2644 return TRUE;
2645}
2646
2647/**********************************************************
2648 * IWineD3D implementation follows
2649 **********************************************************/
2650
2651static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2652 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2653
2654 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2655
2656 return This->adapter_count;
2657}
2658
2659static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void *init_function)
2660{
2661 FIXME("iface %p, init_function %p stub!\n", iface, init_function);
2662
2663 return WINED3D_OK;
2664}
2665
2666static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2667 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2668
2669 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2670
2671 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2672 return NULL;
2673 }
2674
2675 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2676}
2677
2678/* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2679 of the same bpp but different resolutions */
2680
2681/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2682static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2683 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2684 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2685
2686 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2687 return 0;
2688 }
2689
2690 /* TODO: Store modes per adapter and read it from the adapter structure */
2691 if (Adapter == 0) { /* Display */
2692 const struct wined3d_format_desc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2693 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2694 unsigned int i = 0;
2695 unsigned int j = 0;
2696 DEVMODEW mode;
2697
2698 memset(&mode, 0, sizeof(mode));
2699 mode.dmSize = sizeof(mode);
2700
2701 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2702 {
2703 ++j;
2704
2705 if (Format == WINED3DFMT_UNKNOWN)
2706 {
2707 /* This is for D3D8, do not enumerate P8 here */
2708 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2709 }
2710 else if (mode.dmBitsPerPel == format_bits)
2711 {
2712 ++i;
2713 }
2714 }
2715
2716 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2717 return i;
2718 } else {
2719 FIXME_(d3d_caps)("Adapter not primary display\n");
2720 }
2721 return 0;
2722}
2723
2724/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2725static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2726 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2727 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2728
2729 /* Validate the parameters as much as possible */
2730 if (NULL == pMode ||
2731 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2732 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2733 return WINED3DERR_INVALIDCALL;
2734 }
2735
2736 /* TODO: Store modes per adapter and read it from the adapter structure */
2737 if (Adapter == 0)
2738 {
2739 const struct wined3d_format_desc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2740 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2741 DEVMODEW DevModeW;
2742 int ModeIdx = 0;
2743 UINT i = 0;
2744 int j = 0;
2745
2746 ZeroMemory(&DevModeW, sizeof(DevModeW));
2747 DevModeW.dmSize = sizeof(DevModeW);
2748
2749 /* If we are filtering to a specific format (D3D9), then need to skip
2750 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2751 just count through the ones with valid bit depths */
2752 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0))
2753 {
2754 if (Format == WINED3DFMT_UNKNOWN)
2755 {
2756 /* This is for D3D8, do not enumerate P8 here */
2757 if (DevModeW.dmBitsPerPel == 32 || DevModeW.dmBitsPerPel == 16) ++i;
2758 }
2759 else if (DevModeW.dmBitsPerPel == format_bits)
2760 {
2761 ++i;
2762 }
2763 }
2764
2765 if (i == 0) {
2766 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2767 return WINED3DERR_INVALIDCALL;
2768 }
2769 ModeIdx = j - 1;
2770
2771 /* Now get the display mode via the calculated index */
2772 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2773 pMode->Width = DevModeW.dmPelsWidth;
2774 pMode->Height = DevModeW.dmPelsHeight;
2775 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2776 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2777 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2778
2779 if (Format == WINED3DFMT_UNKNOWN) {
2780 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2781 } else {
2782 pMode->Format = Format;
2783 }
2784 } else {
2785 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2786 return WINED3DERR_INVALIDCALL;
2787 }
2788
2789 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2790 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2791 DevModeW.dmBitsPerPel);
2792
2793 }
2794 else
2795 {
2796 FIXME_(d3d_caps)("Adapter not primary display\n");
2797 }
2798
2799 return WINED3D_OK;
2800}
2801
2802static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE *pMode)
2803{
2804 TRACE("iface %p, adapter_idx %u, display_mode %p.\n", iface, Adapter, pMode);
2805
2806 if (NULL == pMode ||
2807 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2808 return WINED3DERR_INVALIDCALL;
2809 }
2810
2811 if (Adapter == 0) { /* Display */
2812 int bpp = 0;
2813 DEVMODEW DevModeW;
2814
2815 ZeroMemory(&DevModeW, sizeof(DevModeW));
2816 DevModeW.dmSize = sizeof(DevModeW);
2817
2818 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2819 pMode->Width = DevModeW.dmPelsWidth;
2820 pMode->Height = DevModeW.dmPelsHeight;
2821 bpp = DevModeW.dmBitsPerPel;
2822 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2823 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2824 {
2825 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2826 }
2827
2828 pMode->Format = pixelformat_for_depth(bpp);
2829 } else {
2830 FIXME_(d3d_caps)("Adapter not primary display\n");
2831 }
2832
2833 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2834 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2835 return WINED3D_OK;
2836}
2837
2838/* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2839 and fields being inserted in the middle, a new structure is used in place */
2840static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2841 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2842 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2843 struct wined3d_adapter *adapter;
2844 size_t len;
2845
2846 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2847
2848 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2849 return WINED3DERR_INVALIDCALL;
2850 }
2851
2852 adapter = &This->adapters[Adapter];
2853
2854 /* Return the information requested */
2855 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2856
2857 if (pIdentifier->driver_size)
2858 {
2859 const char *name = adapter->driver_info.name;
2860 len = min(strlen(name), pIdentifier->driver_size - 1);
2861 memcpy(pIdentifier->driver, name, len);
2862 pIdentifier->driver[len] = '\0';
2863 }
2864
2865 if (pIdentifier->description_size)
2866 {
2867 const char *description = adapter->driver_info.description;
2868 len = min(strlen(description), pIdentifier->description_size - 1);
2869 memcpy(pIdentifier->description, description, len);
2870 pIdentifier->description[len] = '\0';
2871 }
2872
2873 /* Note that d3d8 doesn't supply a device name. */
2874 if (pIdentifier->device_name_size)
2875 {
2876 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2877
2878 len = strlen(device_name);
2879 if (len >= pIdentifier->device_name_size)
2880 {
2881 ERR("Device name size too small.\n");
2882 return WINED3DERR_INVALIDCALL;
2883 }
2884
2885 memcpy(pIdentifier->device_name, device_name, len);
2886 pIdentifier->device_name[len] = '\0';
2887 }
2888
2889 pIdentifier->driver_version.u.HighPart = adapter->driver_info.version_high;
2890 pIdentifier->driver_version.u.LowPart = adapter->driver_info.version_low;
2891 pIdentifier->vendor_id = adapter->driver_info.vendor;
2892 pIdentifier->device_id = adapter->driver_info.device;
2893 pIdentifier->subsystem_id = 0;
2894 pIdentifier->revision = 0;
2895 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2896 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2897 memcpy(&pIdentifier->adapter_luid, &adapter->luid, sizeof(pIdentifier->adapter_luid));
2898 pIdentifier->video_memory = adapter->TextureRam;
2899
2900 return WINED3D_OK;
2901}
2902
2903static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2904 const WineD3D_PixelFormat *cfg, const struct wined3d_format_desc *format_desc)
2905{
2906 short redSize, greenSize, blueSize, alphaSize, colorBits;
2907
2908 if(!cfg)
2909 return FALSE;
2910
2911 /* Float formats need FBOs. If FBOs are used this function isn't called */
2912 if (format_desc->Flags & WINED3DFMT_FLAG_FLOAT) return FALSE;
2913
2914 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2915 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2916 {
2917 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2918 return FALSE;
2919 }
2920
2921 if(cfg->redSize < redSize)
2922 return FALSE;
2923
2924 if(cfg->greenSize < greenSize)
2925 return FALSE;
2926
2927 if(cfg->blueSize < blueSize)
2928 return FALSE;
2929
2930 if(cfg->alphaSize < alphaSize)
2931 return FALSE;
2932
2933 return TRUE;
2934 }
2935
2936 /* Probably a RGBA_float or color index mode */
2937 return FALSE;
2938}
2939
2940static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2941 const WineD3D_PixelFormat *cfg, const struct wined3d_format_desc *format_desc)
2942{
2943 short depthSize, stencilSize;
2944 BOOL lockable = FALSE;
2945
2946 if(!cfg)
2947 return FALSE;
2948
2949 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2950 {
2951 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2952 return FALSE;
2953 }
2954
2955 /* Float formats need FBOs. If FBOs are used this function isn't called */
2956 if (format_desc->Flags & WINED3DFMT_FLAG_FLOAT) return FALSE;
2957
2958 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32_FLOAT))
2959 lockable = TRUE;
2960
2961 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2962 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2963 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2964 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2965 return FALSE;
2966
2967 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2968 * allow more stencil bits than requested. */
2969 if(cfg->stencilSize < stencilSize)
2970 return FALSE;
2971
2972 return TRUE;
2973}
2974
2975static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2976 WINED3DFORMAT AdapterFormat,
2977 WINED3DFORMAT RenderTargetFormat,
2978 WINED3DFORMAT DepthStencilFormat) {
2979 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2980 int nCfgs;
2981 const WineD3D_PixelFormat *cfgs;
2982 const struct wined3d_adapter *adapter;
2983 const struct wined3d_format_desc *rt_format_desc;
2984 const struct wined3d_format_desc *ds_format_desc;
2985 int it;
2986
2987 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2988 This, Adapter,
2989 DeviceType, debug_d3ddevicetype(DeviceType),
2990 AdapterFormat, debug_d3dformat(AdapterFormat),
2991 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2992 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2993
2994 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2995 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2996 return WINED3DERR_INVALIDCALL;
2997 }
2998
2999 adapter = &This->adapters[Adapter];
3000 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
3001 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
3002 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3003 {
3004 if ((rt_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET) &&
3005 (ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) {
3006 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
3007 return WINED3D_OK;
3008 }
3009 }
3010 else
3011 {
3012 cfgs = adapter->cfgs;
3013 nCfgs = adapter->nCfgs;
3014 for (it = 0; it < nCfgs; ++it) {
3015 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
3016 {
3017 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
3018 {
3019 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
3020 return WINED3D_OK;
3021 }
3022 }
3023 }
3024 }
3025 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
3026
3027 return WINED3DERR_NOTAVAILABLE;
3028}
3029
3030static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3031 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
3032{
3033 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3034 const struct wined3d_format_desc *glDesc;
3035 const struct wined3d_adapter *adapter;
3036
3037 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
3038 This,
3039 Adapter,
3040 DeviceType, debug_d3ddevicetype(DeviceType),
3041 SurfaceFormat, debug_d3dformat(SurfaceFormat),
3042 Windowed,
3043 MultiSampleType,
3044 pQualityLevels);
3045
3046 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3047 return WINED3DERR_INVALIDCALL;
3048 }
3049
3050 /* TODO: handle Windowed, add more quality levels */
3051
3052 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
3053 if(pQualityLevels) *pQualityLevels = 1;
3054 return WINED3D_OK;
3055 }
3056
3057 /* By default multisampling is disabled right now as it causes issues
3058 * on some Nvidia driver versions and it doesn't work well in combination
3059 * with FBOs yet. */
3060 if(!wined3d_settings.allow_multisampling)
3061 return WINED3DERR_NOTAVAILABLE;
3062
3063 adapter = &This->adapters[Adapter];
3064 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
3065 if (!glDesc) return WINED3DERR_INVALIDCALL;
3066
3067 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
3068 int i, nCfgs;
3069 const WineD3D_PixelFormat *cfgs;
3070
3071 cfgs = adapter->cfgs;
3072 nCfgs = adapter->nCfgs;
3073 for(i=0; i<nCfgs; i++) {
3074 if(cfgs[i].numSamples != MultiSampleType)
3075 continue;
3076
3077 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
3078 continue;
3079
3080 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
3081
3082 if(pQualityLevels)
3083 *pQualityLevels = 1; /* Guess at a value! */
3084 return WINED3D_OK;
3085 }
3086 }
3087 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
3088 short redSize, greenSize, blueSize, alphaSize, colorBits;
3089 int i, nCfgs;
3090 const WineD3D_PixelFormat *cfgs;
3091
3092 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
3093 {
3094 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
3095 return WINED3DERR_NOTAVAILABLE;
3096 }
3097
3098 cfgs = adapter->cfgs;
3099 nCfgs = adapter->nCfgs;
3100 for(i=0; i<nCfgs; i++) {
3101 if(cfgs[i].numSamples != MultiSampleType)
3102 continue;
3103 if(cfgs[i].redSize != redSize)
3104 continue;
3105 if(cfgs[i].greenSize != greenSize)
3106 continue;
3107 if(cfgs[i].blueSize != blueSize)
3108 continue;
3109 /* Not all drivers report alpha-less formats since they use 32-bit anyway, so accept alpha even if we didn't ask for it. */
3110 if(alphaSize && cfgs[i].alphaSize != alphaSize)
3111 continue;
3112 if(cfgs[i].colorSize != (glDesc->byte_count << 3))
3113 continue;
3114
3115 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
3116
3117 if(pQualityLevels)
3118 *pQualityLevels = 1; /* Guess at a value! */
3119 return WINED3D_OK;
3120 }
3121 }
3122 return WINED3DERR_NOTAVAILABLE;
3123}
3124
3125static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3126 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed)
3127{
3128 HRESULT hr = WINED3DERR_NOTAVAILABLE;
3129 UINT nmodes;
3130
3131 TRACE("iface %p, adapter_idx %u, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
3132 iface, Adapter, debug_d3ddevicetype(DeviceType), debug_d3dformat(DisplayFormat),
3133 debug_d3dformat(BackBufferFormat), Windowed);
3134
3135 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3136 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
3137 return WINED3DERR_INVALIDCALL;
3138 }
3139
3140 /* The task of this function is to check whether a certain display / backbuffer format
3141 * combination is available on the given adapter. In fullscreen mode microsoft specified
3142 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
3143 * and display format should match exactly.
3144 * In windowed mode format conversion can occur and this depends on the driver. When format
3145 * conversion is done, this function should nevertheless fail and applications need to use
3146 * CheckDeviceFormatConversion.
3147 * At the moment we assume that fullscreen and windowed have the same capabilities */
3148
3149 /* There are only 4 display formats */
3150 if (!(DisplayFormat == WINED3DFMT_B5G6R5_UNORM
3151 || DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
3152 || DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
3153 || DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM))
3154 {
3155 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
3156 return WINED3DERR_NOTAVAILABLE;
3157 }
3158
3159 /* If the requested DisplayFormat is not available, don't continue */
3160 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
3161 if(!nmodes) {
3162 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
3163 return WINED3DERR_NOTAVAILABLE;
3164 }
3165
3166 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
3167 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
3168 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
3169 return WINED3DERR_NOTAVAILABLE;
3170 }
3171
3172 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
3173 if (DisplayFormat == WINED3DFMT_B5G6R5_UNORM && BackBufferFormat != WINED3DFMT_B5G6R5_UNORM)
3174 {
3175 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3176 return WINED3DERR_NOTAVAILABLE;
3177 }
3178
3179 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
3180 if (DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
3181 && !(BackBufferFormat == WINED3DFMT_B5G5R5X1_UNORM || BackBufferFormat == WINED3DFMT_B5G5R5A1_UNORM))
3182 {
3183 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3184 return WINED3DERR_NOTAVAILABLE;
3185 }
3186
3187 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
3188 if (DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
3189 && !(BackBufferFormat == WINED3DFMT_B8G8R8X8_UNORM || BackBufferFormat == WINED3DFMT_B8G8R8A8_UNORM))
3190 {
3191 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3192 return WINED3DERR_NOTAVAILABLE;
3193 }
3194
3195 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
3196 if (DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM
3197 && (BackBufferFormat != WINED3DFMT_B10G10R10A2_UNORM || Windowed))
3198 {
3199 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3200 return WINED3DERR_NOTAVAILABLE;
3201 }
3202
3203 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
3204 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
3205 if(FAILED(hr))
3206 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
3207
3208 return hr;
3209}
3210
3211
3212/* Check if we support bumpmapping for a format */
3213static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter,
3214 WINED3DDEVTYPE DeviceType, const struct wined3d_format_desc *format_desc)
3215{
3216 switch(format_desc->format)
3217 {
3218 case WINED3DFMT_R8G8_SNORM:
3219 case WINED3DFMT_R16G16_SNORM:
3220 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3221 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3222 case WINED3DFMT_R8G8B8A8_SNORM:
3223 /* Ask the fixed function pipeline implementation if it can deal
3224 * with the conversion. If we've got a GL extension giving native
3225 * support this will be an identity conversion. */
3226 if (adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup))
3227 {
3228 TRACE_(d3d_caps)("[OK]\n");
3229 return TRUE;
3230 }
3231 TRACE_(d3d_caps)("[FAILED]\n");
3232 return FALSE;
3233
3234 default:
3235 TRACE_(d3d_caps)("[FAILED]\n");
3236 return FALSE;
3237 }
3238}
3239
3240/* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
3241static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter,
3242 const struct wined3d_format_desc *display_format_desc, const struct wined3d_format_desc *ds_format_desc)
3243{
3244 int it=0;
3245
3246 /* Only allow depth/stencil formats */
3247 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
3248
3249 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3250 {
3251 /* With FBOs WGL limitations do not apply, but the format needs to be FBO attachable */
3252 if (ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) return TRUE;
3253 }
3254 else
3255 {
3256 /* Walk through all WGL pixel formats to find a match */
3257 for (it = 0; it < adapter->nCfgs; ++it)
3258 {
3259 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
3260 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
3261 {
3262 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
3263 {
3264 return TRUE;
3265 }
3266 }
3267 }
3268 }
3269
3270 return FALSE;
3271}
3272
3273static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3274{
3275 /* The flags entry of a format contains the filtering capability */
3276 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
3277
3278 return FALSE;
3279}
3280
3281/* Check the render target capabilities of a format */
3282static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter,
3283 const struct wined3d_format_desc *adapter_format_desc, const struct wined3d_format_desc *check_format_desc)
3284{
3285 /* Filter out non-RT formats */
3286 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
3287 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
3288 WineD3D_PixelFormat *cfgs = adapter->cfgs;
3289 int it;
3290 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
3291 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
3292
3293 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
3294 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
3295
3296 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
3297 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
3298 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
3299 TRACE_(d3d_caps)("[FAILED]\n");
3300 return FALSE;
3301 }
3302
3303 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
3304 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
3305 for (it = 0; it < adapter->nCfgs; ++it)
3306 {
3307 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
3308 &cfgs[it], check_format_desc))
3309 {
3310 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
3311 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
3312 return TRUE;
3313 }
3314 }
3315 }
3316 else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
3317 {
3318 /* For now return TRUE for FBOs until we have some proper checks.
3319 * Note that this function will only be called when the format is around for texturing. */
3320 return TRUE;
3321 }
3322 return FALSE;
3323}
3324
3325static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3326{
3327 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3328
3329 /* Check for supported sRGB formats (Texture loading and framebuffer) */
3330 if (!gl_info->supported[EXT_TEXTURE_SRGB])
3331 {
3332 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
3333 return FALSE;
3334 }
3335
3336 switch (format_desc->format)
3337 {
3338 case WINED3DFMT_B8G8R8A8_UNORM:
3339 case WINED3DFMT_B8G8R8X8_UNORM:
3340 case WINED3DFMT_B4G4R4A4_UNORM:
3341 case WINED3DFMT_L8_UNORM:
3342 case WINED3DFMT_L8A8_UNORM:
3343 case WINED3DFMT_DXT1:
3344 case WINED3DFMT_DXT2:
3345 case WINED3DFMT_DXT3:
3346 case WINED3DFMT_DXT4:
3347 case WINED3DFMT_DXT5:
3348 TRACE_(d3d_caps)("[OK]\n");
3349 return TRUE;
3350
3351 default:
3352 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
3353 return FALSE;
3354 }
3355 return FALSE;
3356}
3357
3358static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter,
3359 WINED3DDEVTYPE DeviceType, const struct wined3d_format_desc *format_desc)
3360{
3361 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
3362 * doing the color fixup in shaders.
3363 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
3364 if ((format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) || (format_desc->format == WINED3DFMT_B8G8R8A8_UNORM))
3365 {
3366 int vs_selected_mode;
3367 int ps_selected_mode;
3368 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3369
3370 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
3371 TRACE_(d3d_caps)("[OK]\n");
3372 return TRUE;
3373 }
3374 }
3375
3376 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
3377 return FALSE;
3378}
3379
3380/* Check if a format support blending in combination with pixel shaders */
3381static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapter,
3382 const struct wined3d_format_desc *format_desc)
3383{
3384 /* The flags entry of a format contains the post pixel shader blending capability */
3385 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
3386
3387 return FALSE;
3388}
3389
3390static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc)
3391{
3392 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
3393 * but we have to report mipmapping so we cannot reject this flag. Tests show that
3394 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
3395 * that wrapping is supported. The lack of filtering will sort out the mipmapping
3396 * capability anyway.
3397 *
3398 * For now lets report this on all formats, but in the future we may want to
3399 * restrict it to some should games need that
3400 */
3401 return TRUE;
3402}
3403
3404/* Check if a texture format is supported on the given adapter */
3405static BOOL CheckTextureCapability(struct wined3d_adapter *adapter,
3406 WINED3DDEVTYPE DeviceType, const struct wined3d_format_desc *format_desc)
3407{
3408 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3409
3410 switch (format_desc->format)
3411 {
3412 /*****
3413 * supported: RGB(A) formats
3414 */
3415 case WINED3DFMT_B8G8R8_UNORM: /* Enable for dx7, blacklisted for 8 and 9 above */
3416 case WINED3DFMT_B8G8R8A8_UNORM:
3417 case WINED3DFMT_B8G8R8X8_UNORM:
3418 case WINED3DFMT_B5G6R5_UNORM:
3419 case WINED3DFMT_B5G5R5X1_UNORM:
3420 case WINED3DFMT_B5G5R5A1_UNORM:
3421 case WINED3DFMT_B4G4R4A4_UNORM:
3422 case WINED3DFMT_A8_UNORM:
3423 case WINED3DFMT_B4G4R4X4_UNORM:
3424 case WINED3DFMT_R8G8B8A8_UNORM:
3425 case WINED3DFMT_R8G8B8X8_UNORM:
3426 case WINED3DFMT_B10G10R10A2_UNORM:
3427 case WINED3DFMT_R10G10B10A2_UNORM:
3428 case WINED3DFMT_R16G16_UNORM:
3429 TRACE_(d3d_caps)("[OK]\n");
3430 return TRUE;
3431
3432 case WINED3DFMT_B2G3R3_UNORM:
3433 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
3434 return FALSE;
3435
3436 /*****
3437 * Not supported: Palettized
3438 * Only some Geforce/Voodoo3/G400 cards offer 8-bit textures in case of <=Direct3D7.
3439 * Since it is not widely available, don't offer it. Further no Windows driver offers
3440 * WINED3DFMT_P8_UINT_A8_NORM, so don't offer it either.
3441 */
3442 case WINED3DFMT_P8_UINT:
3443 case WINED3DFMT_P8_UINT_A8_UNORM:
3444 return FALSE;
3445
3446 /*****
3447 * Supported: (Alpha)-Luminance
3448 */
3449 case WINED3DFMT_L8_UNORM:
3450 case WINED3DFMT_L8A8_UNORM:
3451 case WINED3DFMT_L16_UNORM:
3452 TRACE_(d3d_caps)("[OK]\n");
3453 return TRUE;
3454
3455 /* Not supported on Windows, thus disabled */
3456 case WINED3DFMT_L4A4_UNORM:
3457 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
3458 return FALSE;
3459
3460 /*****
3461 * Supported: Depth/Stencil formats
3462 */
3463 case WINED3DFMT_D16_LOCKABLE:
3464 case WINED3DFMT_D16_UNORM:
3465 case WINED3DFMT_S1_UINT_D15_UNORM:
3466 case WINED3DFMT_X8D24_UNORM:
3467 case WINED3DFMT_S4X4_UINT_D24_UNORM:
3468 case WINED3DFMT_D24_UNORM_S8_UINT:
3469 case WINED3DFMT_S8_UINT_D24_FLOAT:
3470 case WINED3DFMT_D32_UNORM:
3471 case WINED3DFMT_D32_FLOAT:
3472 return TRUE;
3473
3474 /*****
3475 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
3476 * GL_NV_texture_shader). Emulated by shaders
3477 */
3478 case WINED3DFMT_R8G8_SNORM:
3479 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3480 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3481 case WINED3DFMT_R8G8B8A8_SNORM:
3482 case WINED3DFMT_R16G16_SNORM:
3483 /* Ask the shader backend if it can deal with the conversion. If
3484 * we've got a GL extension giving native support this will be an
3485 * identity conversion. */
3486 if (adapter->shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
3487 {
3488 TRACE_(d3d_caps)("[OK]\n");
3489 return TRUE;
3490 }
3491 TRACE_(d3d_caps)("[FAILED]\n");
3492 return FALSE;
3493
3494 case WINED3DFMT_DXT1:
3495 case WINED3DFMT_DXT2:
3496 case WINED3DFMT_DXT3:
3497 case WINED3DFMT_DXT4:
3498 case WINED3DFMT_DXT5:
3499 if (gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC])
3500 {
3501 TRACE_(d3d_caps)("[OK]\n");
3502 return TRUE;
3503 }
3504 TRACE_(d3d_caps)("[FAILED]\n");
3505 return FALSE;
3506
3507
3508 /*****
3509 * Odd formats - not supported
3510 */
3511 case WINED3DFMT_VERTEXDATA:
3512 case WINED3DFMT_R16_UINT:
3513 case WINED3DFMT_R32_UINT:
3514 case WINED3DFMT_R16G16B16A16_SNORM:
3515 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM:
3516 case WINED3DFMT_R10G11B11_SNORM:
3517 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3518 return FALSE;
3519
3520 /*****
3521 * WINED3DFMT_R8G8_SNORM_Cx: Not supported right now
3522 */
3523 case WINED3DFMT_R8G8_SNORM_Cx:
3524 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3525 return FALSE;
3526
3527 /* YUV formats */
3528 case WINED3DFMT_UYVY:
3529 case WINED3DFMT_YUY2:
3530 if (gl_info->supported[APPLE_YCBCR_422])
3531 {
3532 TRACE_(d3d_caps)("[OK]\n");
3533 return TRUE;
3534 }
3535 TRACE_(d3d_caps)("[FAILED]\n");
3536 return FALSE;
3537 case WINED3DFMT_YV12:
3538 TRACE_(d3d_caps)("[FAILED]\n");
3539 return FALSE;
3540
3541 /* Not supported */
3542 case WINED3DFMT_R16G16B16A16_UNORM:
3543 case WINED3DFMT_B2G3R3A8_UNORM:
3544 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3545 return FALSE;
3546
3547 /* Floating point formats */
3548 case WINED3DFMT_R16_FLOAT:
3549 case WINED3DFMT_R16G16_FLOAT:
3550 case WINED3DFMT_R16G16B16A16_FLOAT:
3551 if (gl_info->supported[ARB_TEXTURE_FLOAT] && gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3552 {
3553 TRACE_(d3d_caps)("[OK]\n");
3554 return TRUE;
3555 }
3556 TRACE_(d3d_caps)("[FAILED]\n");
3557 return FALSE;
3558
3559 case WINED3DFMT_R32_FLOAT:
3560 case WINED3DFMT_R32G32_FLOAT:
3561 case WINED3DFMT_R32G32B32A32_FLOAT:
3562 if (gl_info->supported[ARB_TEXTURE_FLOAT])
3563 {
3564 TRACE_(d3d_caps)("[OK]\n");
3565 return TRUE;
3566 }
3567 TRACE_(d3d_caps)("[FAILED]\n");
3568 return FALSE;
3569
3570 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3571 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3572 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3573 * We can do instancing with all shader versions, but we need vertex shaders.
3574 *
3575 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3576 * to enable instancing. WineD3D doesn't need that and just ignores it.
3577 *
3578 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3579 */
3580 case WINED3DFMT_INST:
3581 TRACE("ATI Instancing check hack\n");
3582 if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
3583 {
3584 TRACE_(d3d_caps)("[OK]\n");
3585 return TRUE;
3586 }
3587 TRACE_(d3d_caps)("[FAILED]\n");
3588 return FALSE;
3589
3590 /* Some weird FOURCC formats */
3591 case WINED3DFMT_R8G8_B8G8:
3592 case WINED3DFMT_G8R8_G8B8:
3593 case WINED3DFMT_MULTI2_ARGB8:
3594 TRACE_(d3d_caps)("[FAILED]\n");
3595 return FALSE;
3596
3597 /* Vendor specific formats */
3598 case WINED3DFMT_ATI2N:
3599 if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC]
3600 || gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
3601 {
3602 if (adapter->shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3603 && adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup))
3604 {
3605 TRACE_(d3d_caps)("[OK]\n");
3606 return TRUE;
3607 }
3608
3609 TRACE_(d3d_caps)("[OK]\n");
3610 return TRUE;
3611 }
3612 TRACE_(d3d_caps)("[FAILED]\n");
3613 return FALSE;
3614
3615 case WINED3DFMT_NVHU:
3616 case WINED3DFMT_NVHS:
3617 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3618 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3619 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3620 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3621 * Applications have to deal with not having NVHS and NVHU.
3622 */
3623 TRACE_(d3d_caps)("[FAILED]\n");
3624 return FALSE;
3625
3626 case WINED3DFMT_UNKNOWN:
3627 return FALSE;
3628
3629 default:
3630 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3631 break;
3632 }
3633 return FALSE;
3634}
3635
3636static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter,
3637 const struct wined3d_format_desc *adapter_format_desc,
3638 WINED3DDEVTYPE DeviceType, const struct wined3d_format_desc *check_format_desc,
3639 WINED3DSURFTYPE SurfaceType)
3640{
3641 if(SurfaceType == SURFACE_GDI) {
3642 switch(check_format_desc->format)
3643 {
3644 case WINED3DFMT_B8G8R8_UNORM:
3645 case WINED3DFMT_B8G8R8A8_UNORM:
3646 case WINED3DFMT_B8G8R8X8_UNORM:
3647 case WINED3DFMT_B5G6R5_UNORM:
3648 case WINED3DFMT_B5G5R5X1_UNORM:
3649 case WINED3DFMT_B5G5R5A1_UNORM:
3650 case WINED3DFMT_B4G4R4A4_UNORM:
3651 case WINED3DFMT_B2G3R3_UNORM:
3652 case WINED3DFMT_A8_UNORM:
3653 case WINED3DFMT_B2G3R3A8_UNORM:
3654 case WINED3DFMT_B4G4R4X4_UNORM:
3655 case WINED3DFMT_R10G10B10A2_UNORM:
3656 case WINED3DFMT_R8G8B8A8_UNORM:
3657 case WINED3DFMT_R8G8B8X8_UNORM:
3658 case WINED3DFMT_R16G16_UNORM:
3659 case WINED3DFMT_B10G10R10A2_UNORM:
3660 case WINED3DFMT_R16G16B16A16_UNORM:
3661 case WINED3DFMT_P8_UINT:
3662 TRACE_(d3d_caps)("[OK]\n");
3663 return TRUE;
3664 default:
3665 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3666 return FALSE;
3667 }
3668 }
3669
3670 /* All format that are supported for textures are supported for surfaces as well */
3671 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3672 /* All depth stencil formats are supported on surfaces */
3673 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3674
3675 /* If opengl can't process the format natively, the blitter may be able to convert it */
3676 if (adapter->blitter->blit_supported(&adapter->gl_info, BLIT_OP_BLIT,
3677 NULL, WINED3DPOOL_DEFAULT, 0, check_format_desc,
3678 NULL, WINED3DPOOL_DEFAULT, 0, adapter_format_desc))
3679 {
3680 TRACE_(d3d_caps)("[OK]\n");
3681 return TRUE;
3682 }
3683
3684 /* Reject other formats */
3685 TRACE_(d3d_caps)("[FAILED]\n");
3686 return FALSE;
3687}
3688
3689static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter,
3690 const struct wined3d_format_desc *format_desc)
3691{
3692 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3693
3694 if (!gl_info->limits.vertex_samplers)
3695 {
3696 TRACE_(d3d_caps)("[FAILED]\n");
3697 return FALSE;
3698 }
3699
3700 switch (format_desc->format)
3701 {
3702 case WINED3DFMT_R32G32B32A32_FLOAT:
3703 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
3704 {
3705 TRACE_(d3d_caps)("[FAILED]\n");
3706 return FALSE;
3707 }
3708 TRACE_(d3d_caps)("[OK]\n");
3709 return TRUE;
3710
3711 default:
3712 TRACE_(d3d_caps)("[FAILED]\n");
3713 return FALSE;
3714 }
3715 return FALSE;
3716}
3717
3718static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3719 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3720 WINED3DSURFTYPE SurfaceType)
3721{
3722 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3723 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3724 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3725 const struct wined3d_format_desc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3726 const struct wined3d_format_desc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3727 DWORD UsageCaps = 0;
3728
3729 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3730 This,
3731 Adapter,
3732 DeviceType, debug_d3ddevicetype(DeviceType),
3733 AdapterFormat, debug_d3dformat(AdapterFormat),
3734 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3735 RType, debug_d3dresourcetype(RType),
3736 CheckFormat, debug_d3dformat(CheckFormat));
3737
3738 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3739 return WINED3DERR_INVALIDCALL;
3740 }
3741
3742 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3743
3744 if(SurfaceType != SURFACE_OPENGL) {
3745 TRACE("[FAILED]\n");
3746 return WINED3DERR_NOTAVAILABLE;
3747 }
3748
3749 /* Cubetexture allows:
3750 * - D3DUSAGE_AUTOGENMIPMAP
3751 * - D3DUSAGE_DEPTHSTENCIL
3752 * - D3DUSAGE_DYNAMIC
3753 * - D3DUSAGE_NONSECURE (d3d9ex)
3754 * - D3DUSAGE_RENDERTARGET
3755 * - D3DUSAGE_SOFTWAREPROCESSING
3756 * - D3DUSAGE_QUERY_WRAPANDMIP
3757 */
3758 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3759 {
3760 /* Check if the texture format is around */
3761 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3762 {
3763 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3764 /* Check for automatic mipmap generation support */
3765 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3766 {
3767 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3768 } else {
3769 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3770 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3771 }
3772 }
3773
3774 /* Always report dynamic locking */
3775 if(Usage & WINED3DUSAGE_DYNAMIC)
3776 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3777
3778 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3779 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3780 {
3781 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3782 } else {
3783 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3784 return WINED3DERR_NOTAVAILABLE;
3785 }
3786 }
3787
3788 /* Always report software processing */
3789 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3790 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3791
3792 /* Check QUERY_FILTER support */
3793 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3794 if (CheckFilterCapability(adapter, format_desc))
3795 {
3796 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3797 } else {
3798 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3799 return WINED3DERR_NOTAVAILABLE;
3800 }
3801 }
3802
3803 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3804 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3805 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3806 {
3807 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3808 } else {
3809 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3810 return WINED3DERR_NOTAVAILABLE;
3811 }
3812 }
3813
3814 /* Check QUERY_SRGBREAD support */
3815 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3816 if (CheckSrgbReadCapability(adapter, format_desc))
3817 {
3818 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3819 } else {
3820 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3821 return WINED3DERR_NOTAVAILABLE;
3822 }
3823 }
3824
3825 /* Check QUERY_SRGBWRITE support */
3826 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3827 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3828 {
3829 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3830 } else {
3831 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3832 return WINED3DERR_NOTAVAILABLE;
3833 }
3834 }
3835
3836 /* Check QUERY_VERTEXTEXTURE support */
3837 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3838 if (CheckVertexTextureCapability(adapter, format_desc))
3839 {
3840 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3841 } else {
3842 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3843 return WINED3DERR_NOTAVAILABLE;
3844 }
3845 }
3846
3847 /* Check QUERY_WRAPANDMIP support */
3848 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3849 if (CheckWrapAndMipCapability(adapter, format_desc))
3850 {
3851 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3852 } else {
3853 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3854 return WINED3DERR_NOTAVAILABLE;
3855 }
3856 }
3857 } else {
3858 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3859 return WINED3DERR_NOTAVAILABLE;
3860 }
3861 } else {
3862 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3863 return WINED3DERR_NOTAVAILABLE;
3864 }
3865 } else if(RType == WINED3DRTYPE_SURFACE) {
3866 /* Surface allows:
3867 * - D3DUSAGE_DEPTHSTENCIL
3868 * - D3DUSAGE_NONSECURE (d3d9ex)
3869 * - D3DUSAGE_RENDERTARGET
3870 */
3871
3872 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3873 {
3874 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3875 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3876 {
3877 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3878 } else {
3879 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3880 return WINED3DERR_NOTAVAILABLE;
3881 }
3882 }
3883
3884 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3885 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3886 {
3887 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3888 } else {
3889 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3890 return WINED3DERR_NOTAVAILABLE;
3891 }
3892 }
3893
3894 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3895 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3896 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3897 {
3898 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3899 } else {
3900 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3901 return WINED3DERR_NOTAVAILABLE;
3902 }
3903 }
3904 } else {
3905 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3906 return WINED3DERR_NOTAVAILABLE;
3907 }
3908
3909 } else if(RType == WINED3DRTYPE_TEXTURE) {
3910 /* Texture allows:
3911 * - D3DUSAGE_AUTOGENMIPMAP
3912 * - D3DUSAGE_DEPTHSTENCIL
3913 * - D3DUSAGE_DMAP
3914 * - D3DUSAGE_DYNAMIC
3915 * - D3DUSAGE_NONSECURE (d3d9ex)
3916 * - D3DUSAGE_RENDERTARGET
3917 * - D3DUSAGE_SOFTWAREPROCESSING
3918 * - D3DUSAGE_TEXTAPI (d3d9ex)
3919 * - D3DUSAGE_QUERY_WRAPANDMIP
3920 */
3921
3922 if(SurfaceType != SURFACE_OPENGL) {
3923 TRACE("[FAILED]\n");
3924 return WINED3DERR_NOTAVAILABLE;
3925 }
3926
3927 /* Check if the texture format is around */
3928 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3929 {
3930 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3931 /* Check for automatic mipmap generation support */
3932 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3933 {
3934 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3935 } else {
3936 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3937 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3938 }
3939 }
3940
3941 /* Always report dynamic locking */
3942 if(Usage & WINED3DUSAGE_DYNAMIC)
3943 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3944
3945 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3946 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3947 {
3948 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3949 } else {
3950 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3951 return WINED3DERR_NOTAVAILABLE;
3952 }
3953 }
3954
3955 /* Always report software processing */
3956 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3957 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3958
3959 /* Check QUERY_FILTER support */
3960 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3961 if (CheckFilterCapability(adapter, format_desc))
3962 {
3963 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3964 } else {
3965 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3966 return WINED3DERR_NOTAVAILABLE;
3967 }
3968 }
3969
3970 /* Check QUERY_LEGACYBUMPMAP support */
3971 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3972 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3973 {
3974 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3975 } else {
3976 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3977 return WINED3DERR_NOTAVAILABLE;
3978 }
3979 }
3980
3981 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3982 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3983 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3984 {
3985 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3986 } else {
3987 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3988 return WINED3DERR_NOTAVAILABLE;
3989 }
3990 }
3991
3992 /* Check QUERY_SRGBREAD support */
3993 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3994 if (CheckSrgbReadCapability(adapter, format_desc))
3995 {
3996 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3997 } else {
3998 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3999 return WINED3DERR_NOTAVAILABLE;
4000 }
4001 }
4002
4003 /* Check QUERY_SRGBWRITE support */
4004 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
4005 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
4006 {
4007 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
4008 } else {
4009 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
4010 return WINED3DERR_NOTAVAILABLE;
4011 }
4012 }
4013
4014 /* Check QUERY_VERTEXTEXTURE support */
4015 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
4016 if (CheckVertexTextureCapability(adapter, format_desc))
4017 {
4018 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
4019 } else {
4020 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
4021 return WINED3DERR_NOTAVAILABLE;
4022 }
4023 }
4024
4025 /* Check QUERY_WRAPANDMIP support */
4026 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
4027 if (CheckWrapAndMipCapability(adapter, format_desc))
4028 {
4029 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
4030 } else {
4031 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
4032 return WINED3DERR_NOTAVAILABLE;
4033 }
4034 }
4035
4036 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
4037 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
4038 {
4039 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
4040 } else {
4041 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
4042 return WINED3DERR_NOTAVAILABLE;
4043 }
4044 }
4045 } else {
4046 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
4047 return WINED3DERR_NOTAVAILABLE;
4048 }
4049 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
4050 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
4051 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
4052 *
4053 * Volumetexture allows:
4054 * - D3DUSAGE_DYNAMIC
4055 * - D3DUSAGE_NONSECURE (d3d9ex)
4056 * - D3DUSAGE_SOFTWAREPROCESSING
4057 * - D3DUSAGE_QUERY_WRAPANDMIP
4058 */
4059
4060 if(SurfaceType != SURFACE_OPENGL) {
4061 TRACE("[FAILED]\n");
4062 return WINED3DERR_NOTAVAILABLE;
4063 }
4064
4065 /* Check volume texture and volume usage caps */
4066 if (gl_info->supported[EXT_TEXTURE3D])
4067 {
4068 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
4069 {
4070 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
4071 return WINED3DERR_NOTAVAILABLE;
4072 }
4073
4074 /* Always report dynamic locking */
4075 if(Usage & WINED3DUSAGE_DYNAMIC)
4076 UsageCaps |= WINED3DUSAGE_DYNAMIC;
4077
4078 /* Always report software processing */
4079 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
4080 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
4081
4082 /* Check QUERY_FILTER support */
4083 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
4084 if (CheckFilterCapability(adapter, format_desc))
4085 {
4086 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
4087 } else {
4088 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
4089 return WINED3DERR_NOTAVAILABLE;
4090 }
4091 }
4092
4093 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
4094 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
4095 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
4096 {
4097 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
4098 } else {
4099 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
4100 return WINED3DERR_NOTAVAILABLE;
4101 }
4102 }
4103
4104 /* Check QUERY_SRGBREAD support */
4105 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
4106 if (CheckSrgbReadCapability(adapter, format_desc))
4107 {
4108 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
4109 } else {
4110 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
4111 return WINED3DERR_NOTAVAILABLE;
4112 }
4113 }
4114
4115 /* Check QUERY_SRGBWRITE support */
4116 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
4117 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
4118 {
4119 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
4120 } else {
4121 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
4122 return WINED3DERR_NOTAVAILABLE;
4123 }
4124 }
4125
4126 /* Check QUERY_VERTEXTEXTURE support */
4127 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
4128 if (CheckVertexTextureCapability(adapter, format_desc))
4129 {
4130 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
4131 } else {
4132 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
4133 return WINED3DERR_NOTAVAILABLE;
4134 }
4135 }
4136
4137 /* Check QUERY_WRAPANDMIP support */
4138 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
4139 if (CheckWrapAndMipCapability(adapter, format_desc))
4140 {
4141 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
4142 } else {
4143 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
4144 return WINED3DERR_NOTAVAILABLE;
4145 }
4146 }
4147 } else {
4148 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
4149 return WINED3DERR_NOTAVAILABLE;
4150 }
4151
4152 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
4153 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
4154 * app needing one of those formats, don't advertize them to avoid leading apps into
4155 * temptation. The windows drivers don't support most of those formats on volumes anyway,
4156 * except of R32F.
4157 */
4158 switch(CheckFormat) {
4159 case WINED3DFMT_P8_UINT:
4160 case WINED3DFMT_L4A4_UNORM:
4161 case WINED3DFMT_R32_FLOAT:
4162 case WINED3DFMT_R16_FLOAT:
4163 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
4164 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
4165 case WINED3DFMT_R16G16_UNORM:
4166 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4167 return WINED3DERR_NOTAVAILABLE;
4168
4169 case WINED3DFMT_R8G8B8A8_SNORM:
4170 case WINED3DFMT_R16G16_SNORM:
4171 if (!gl_info->supported[NV_TEXTURE_SHADER])
4172 {
4173 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4174 return WINED3DERR_NOTAVAILABLE;
4175 }
4176 break;
4177
4178 case WINED3DFMT_R8G8_SNORM:
4179 if (!gl_info->supported[NV_TEXTURE_SHADER])
4180 {
4181 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
4182 return WINED3DERR_NOTAVAILABLE;
4183 }
4184 break;
4185
4186 case WINED3DFMT_DXT1:
4187 case WINED3DFMT_DXT2:
4188 case WINED3DFMT_DXT3:
4189 case WINED3DFMT_DXT4:
4190 case WINED3DFMT_DXT5:
4191 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
4192 * compressed texture results in an error. While the D3D refrast does
4193 * support s3tc volumes, at least the nvidia windows driver does not, so
4194 * we're free not to support this format.
4195 */
4196 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
4197 return WINED3DERR_NOTAVAILABLE;
4198
4199 default:
4200 /* Do nothing, continue with checking the format below */
4201 break;
4202 }
4203 } else if(RType == WINED3DRTYPE_BUFFER){
4204 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
4205 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
4206 return WINED3DERR_NOTAVAILABLE;
4207 }
4208
4209 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
4210 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
4211 * usage flags match. */
4212 if(UsageCaps == Usage) {
4213 return WINED3D_OK;
4214 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
4215 return WINED3DOK_NOAUTOGEN;
4216 } else {
4217 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);
4218 return WINED3DERR_NOTAVAILABLE;
4219 }
4220}
4221
4222static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT adapter_idx,
4223 WINED3DDEVTYPE device_type, WINED3DFORMAT src_format, WINED3DFORMAT dst_format)
4224{
4225 FIXME("iface %p, adapter_idx %u, device_type %s, src_format %s, dst_format %s stub!\n",
4226 iface, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(src_format),
4227 debug_d3dformat(dst_format));
4228
4229 return WINED3D_OK;
4230}
4231
4232/* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
4233 subset of a D3DCAPS9 structure. However, it has to come via a void *
4234 as the d3d8 interface cannot import the d3d9 header */
4235static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
4236
4237 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4238 struct wined3d_adapter *adapter = &This->adapters[Adapter];
4239 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4240 int vs_selected_mode;
4241 int ps_selected_mode;
4242 struct shader_caps shader_caps;
4243 struct fragment_caps fragment_caps;
4244 DWORD ckey_caps, blit_caps, fx_caps;
4245
4246 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
4247
4248 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
4249 return WINED3DERR_INVALIDCALL;
4250 }
4251
4252 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
4253
4254 /* ------------------------------------------------
4255 The following fields apply to both d3d8 and d3d9
4256 ------------------------------------------------ */
4257 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
4258 pCaps->AdapterOrdinal = Adapter;
4259
4260 pCaps->Caps = 0;
4261 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
4262 WINED3DCAPS2_FULLSCREENGAMMA |
4263 WINED3DCAPS2_DYNAMICTEXTURES;
4264 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
4265 {
4266 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
4267 }
4268
4269 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
4270 WINED3DCAPS3_COPY_TO_VIDMEM |
4271 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
4272
4273 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
4274 WINED3DPRESENT_INTERVAL_ONE;
4275
4276 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
4277 WINED3DCURSORCAPS_LOWRES;
4278
4279 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
4280 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
4281 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
4282 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4283 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
4284 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
4285 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
4286 WINED3DDEVCAPS_PUREDEVICE |
4287 WINED3DDEVCAPS_HWRASTERIZATION |
4288 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
4289 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
4290 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
4291 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
4292 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
4293 WINED3DDEVCAPS_RTPATCHES;
4294
4295 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
4296 WINED3DPMISCCAPS_CULLCCW |
4297 WINED3DPMISCCAPS_CULLCW |
4298 WINED3DPMISCCAPS_COLORWRITEENABLE |
4299 WINED3DPMISCCAPS_CLIPTLVERTS |
4300 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
4301 WINED3DPMISCCAPS_MASKZ |
4302 WINED3DPMISCCAPS_BLENDOP |
4303 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
4304 /* TODO:
4305 WINED3DPMISCCAPS_NULLREFERENCE
4306 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
4307 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
4308 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
4309
4310 if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
4311 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
4312 if (gl_info->supported[EXT_DRAW_BUFFERS2])
4313 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS;
4314
4315 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
4316 WINED3DPRASTERCAPS_PAT |
4317 WINED3DPRASTERCAPS_WFOG |
4318 WINED3DPRASTERCAPS_ZFOG |
4319 WINED3DPRASTERCAPS_FOGVERTEX |
4320 WINED3DPRASTERCAPS_FOGTABLE |
4321 WINED3DPRASTERCAPS_STIPPLE |
4322 WINED3DPRASTERCAPS_SUBPIXEL |
4323 WINED3DPRASTERCAPS_ZTEST |
4324 WINED3DPRASTERCAPS_SCISSORTEST |
4325 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
4326 WINED3DPRASTERCAPS_DEPTHBIAS;
4327
4328 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4329 {
4330 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
4331 WINED3DPRASTERCAPS_ZBIAS |
4332 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
4333 }
4334 if (gl_info->supported[NV_FOG_DISTANCE])
4335 {
4336 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
4337 }
4338 /* FIXME Add:
4339 WINED3DPRASTERCAPS_COLORPERSPECTIVE
4340 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
4341 WINED3DPRASTERCAPS_ANTIALIASEDGES
4342 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
4343 WINED3DPRASTERCAPS_WBUFFER */
4344
4345 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
4346 WINED3DPCMPCAPS_EQUAL |
4347 WINED3DPCMPCAPS_GREATER |
4348 WINED3DPCMPCAPS_GREATEREQUAL |
4349 WINED3DPCMPCAPS_LESS |
4350 WINED3DPCMPCAPS_LESSEQUAL |
4351 WINED3DPCMPCAPS_NEVER |
4352 WINED3DPCMPCAPS_NOTEQUAL;
4353
4354 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
4355 WINED3DPBLENDCAPS_BOTHSRCALPHA |
4356 WINED3DPBLENDCAPS_DESTALPHA |
4357 WINED3DPBLENDCAPS_DESTCOLOR |
4358 WINED3DPBLENDCAPS_INVDESTALPHA |
4359 WINED3DPBLENDCAPS_INVDESTCOLOR |
4360 WINED3DPBLENDCAPS_INVSRCALPHA |
4361 WINED3DPBLENDCAPS_INVSRCCOLOR |
4362 WINED3DPBLENDCAPS_ONE |
4363 WINED3DPBLENDCAPS_SRCALPHA |
4364 WINED3DPBLENDCAPS_SRCALPHASAT |
4365 WINED3DPBLENDCAPS_SRCCOLOR |
4366 WINED3DPBLENDCAPS_ZERO;
4367
4368 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
4369 WINED3DPBLENDCAPS_DESTCOLOR |
4370 WINED3DPBLENDCAPS_INVDESTALPHA |
4371 WINED3DPBLENDCAPS_INVDESTCOLOR |
4372 WINED3DPBLENDCAPS_INVSRCALPHA |
4373 WINED3DPBLENDCAPS_INVSRCCOLOR |
4374 WINED3DPBLENDCAPS_ONE |
4375 WINED3DPBLENDCAPS_SRCALPHA |
4376 WINED3DPBLENDCAPS_SRCCOLOR |
4377 WINED3DPBLENDCAPS_ZERO;
4378 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
4379 * according to the glBlendFunc manpage
4380 *
4381 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
4382 * legacy settings for srcblend only
4383 */
4384
4385 if (gl_info->supported[EXT_BLEND_COLOR])
4386 {
4387 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
4388 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
4389 }
4390
4391
4392 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
4393 WINED3DPCMPCAPS_EQUAL |
4394 WINED3DPCMPCAPS_GREATER |
4395 WINED3DPCMPCAPS_GREATEREQUAL |
4396 WINED3DPCMPCAPS_LESS |
4397 WINED3DPCMPCAPS_LESSEQUAL |
4398 WINED3DPCMPCAPS_NEVER |
4399 WINED3DPCMPCAPS_NOTEQUAL;
4400
4401 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
4402 WINED3DPSHADECAPS_COLORGOURAUDRGB |
4403 WINED3DPSHADECAPS_ALPHAFLATBLEND |
4404 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
4405 WINED3DPSHADECAPS_COLORFLATRGB |
4406 WINED3DPSHADECAPS_FOGFLAT |
4407 WINED3DPSHADECAPS_FOGGOURAUD |
4408 WINED3DPSHADECAPS_SPECULARFLATRGB;
4409
4410 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
4411 WINED3DPTEXTURECAPS_ALPHAPALETTE |
4412 WINED3DPTEXTURECAPS_TRANSPARENCY |
4413 WINED3DPTEXTURECAPS_BORDER |
4414 WINED3DPTEXTURECAPS_MIPMAP |
4415 WINED3DPTEXTURECAPS_PROJECTED |
4416 WINED3DPTEXTURECAPS_PERSPECTIVE;
4417
4418 if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
4419 {
4420 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
4421 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
4422 }
4423
4424 if (gl_info->supported[EXT_TEXTURE3D])
4425 {
4426 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
4427 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
4428 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
4429 }
4430
4431 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4432 {
4433 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
4434 WINED3DPTEXTURECAPS_MIPCUBEMAP |
4435 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
4436
4437 }
4438
4439 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4440 WINED3DPTFILTERCAPS_MAGFPOINT |
4441 WINED3DPTFILTERCAPS_MINFLINEAR |
4442 WINED3DPTFILTERCAPS_MINFPOINT |
4443 WINED3DPTFILTERCAPS_MIPFLINEAR |
4444 WINED3DPTFILTERCAPS_MIPFPOINT |
4445 WINED3DPTFILTERCAPS_LINEAR |
4446 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4447 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4448 WINED3DPTFILTERCAPS_MIPLINEAR |
4449 WINED3DPTFILTERCAPS_MIPNEAREST |
4450 WINED3DPTFILTERCAPS_NEAREST;
4451
4452 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4453 {
4454 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4455 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4456 }
4457
4458 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4459 {
4460 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4461 WINED3DPTFILTERCAPS_MAGFPOINT |
4462 WINED3DPTFILTERCAPS_MINFLINEAR |
4463 WINED3DPTFILTERCAPS_MINFPOINT |
4464 WINED3DPTFILTERCAPS_MIPFLINEAR |
4465 WINED3DPTFILTERCAPS_MIPFPOINT |
4466 WINED3DPTFILTERCAPS_LINEAR |
4467 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4468 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4469 WINED3DPTFILTERCAPS_MIPLINEAR |
4470 WINED3DPTFILTERCAPS_MIPNEAREST |
4471 WINED3DPTFILTERCAPS_NEAREST;
4472
4473 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4474 {
4475 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4476 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4477 }
4478 } else
4479 pCaps->CubeTextureFilterCaps = 0;
4480
4481 if (gl_info->supported[EXT_TEXTURE3D])
4482 {
4483 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4484 WINED3DPTFILTERCAPS_MAGFPOINT |
4485 WINED3DPTFILTERCAPS_MINFLINEAR |
4486 WINED3DPTFILTERCAPS_MINFPOINT |
4487 WINED3DPTFILTERCAPS_MIPFLINEAR |
4488 WINED3DPTFILTERCAPS_MIPFPOINT |
4489 WINED3DPTFILTERCAPS_LINEAR |
4490 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4491 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4492 WINED3DPTFILTERCAPS_MIPLINEAR |
4493 WINED3DPTFILTERCAPS_MIPNEAREST |
4494 WINED3DPTFILTERCAPS_NEAREST;
4495 } else
4496 pCaps->VolumeTextureFilterCaps = 0;
4497
4498 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4499 WINED3DPTADDRESSCAPS_CLAMP |
4500 WINED3DPTADDRESSCAPS_WRAP;
4501
4502 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4503 {
4504 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4505 }
4506 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4507 {
4508 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4509 }
4510 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4511 {
4512 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4513 }
4514
4515 if (gl_info->supported[EXT_TEXTURE3D])
4516 {
4517 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4518 WINED3DPTADDRESSCAPS_CLAMP |
4519 WINED3DPTADDRESSCAPS_WRAP;
4520 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4521 {
4522 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4523 }
4524 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4525 {
4526 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4527 }
4528 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4529 {
4530 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4531 }
4532 } else
4533 pCaps->VolumeTextureAddressCaps = 0;
4534
4535 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4536 WINED3DLINECAPS_ZTEST |
4537 WINED3DLINECAPS_BLEND |
4538 WINED3DLINECAPS_ALPHACMP |
4539 WINED3DLINECAPS_FOG;
4540 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4541 * idea how generating the smoothing alpha values works; the result is different
4542 */
4543
4544 pCaps->MaxTextureWidth = gl_info->limits.texture_size;
4545 pCaps->MaxTextureHeight = gl_info->limits.texture_size;
4546
4547 if (gl_info->supported[EXT_TEXTURE3D])
4548 pCaps->MaxVolumeExtent = gl_info->limits.texture3d_size;
4549 else
4550 pCaps->MaxVolumeExtent = 0;
4551
4552 pCaps->MaxTextureRepeat = 32768;
4553 pCaps->MaxTextureAspectRatio = gl_info->limits.texture_size;
4554 pCaps->MaxVertexW = 1.0f;
4555
4556 pCaps->GuardBandLeft = 0.0f;
4557 pCaps->GuardBandTop = 0.0f;
4558 pCaps->GuardBandRight = 0.0f;
4559 pCaps->GuardBandBottom = 0.0f;
4560
4561 pCaps->ExtentsAdjust = 0.0f;
4562
4563 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4564 WINED3DSTENCILCAPS_INCRSAT |
4565 WINED3DSTENCILCAPS_INVERT |
4566 WINED3DSTENCILCAPS_KEEP |
4567 WINED3DSTENCILCAPS_REPLACE |
4568 WINED3DSTENCILCAPS_ZERO;
4569 if (gl_info->supported[EXT_STENCIL_WRAP])
4570 {
4571 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4572 WINED3DSTENCILCAPS_INCR;
4573 }
4574 if (gl_info->supported[EXT_STENCIL_TWO_SIDE] || gl_info->supported[ATI_SEPARATE_STENCIL])
4575 {
4576 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4577 }
4578
4579 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4580
4581 pCaps->MaxUserClipPlanes = gl_info->limits.clipplanes;
4582 pCaps->MaxActiveLights = gl_info->limits.lights;
4583
4584 pCaps->MaxVertexBlendMatrices = gl_info->limits.blends;
4585 pCaps->MaxVertexBlendMatrixIndex = 0;
4586
4587 pCaps->MaxAnisotropy = gl_info->limits.anisotropy;
4588 pCaps->MaxPointSize = gl_info->limits.pointsize_max;
4589
4590
4591 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4592 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4593 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4594 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4595 WINED3DVTXPCAPS_LOCALVIEWER |
4596 WINED3DVTXPCAPS_VERTEXFOG |
4597 WINED3DVTXPCAPS_TEXGEN;
4598
4599 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4600 pCaps->MaxVertexIndex = 0xFFFFF;
4601 pCaps->MaxStreams = MAX_STREAMS;
4602 pCaps->MaxStreamStride = 1024;
4603
4604 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4605 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4606 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4607 pCaps->MaxNpatchTessellationLevel = 0;
4608 pCaps->MasterAdapterOrdinal = 0;
4609 pCaps->AdapterOrdinalInGroup = 0;
4610 pCaps->NumberOfAdaptersInGroup = 1;
4611
4612 pCaps->NumSimultaneousRTs = gl_info->limits.buffers;
4613
4614 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4615 WINED3DPTFILTERCAPS_MAGFPOINT |
4616 WINED3DPTFILTERCAPS_MINFLINEAR |
4617 WINED3DPTFILTERCAPS_MAGFLINEAR;
4618 pCaps->VertexTextureFilterCaps = 0;
4619
4620 memset(&shader_caps, 0, sizeof(shader_caps));
4621 adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
4622
4623 memset(&fragment_caps, 0, sizeof(fragment_caps));
4624 adapter->fragment_pipe->get_caps(&adapter->gl_info, &fragment_caps);
4625
4626 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4627 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4628
4629 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4630 * Ignore shader model capabilities if disabled in config
4631 */
4632 if(vs_selected_mode == SHADER_NONE) {
4633 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4634 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4635 pCaps->MaxVertexShaderConst = 0;
4636 } else {
4637 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4638 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4639 }
4640
4641 if(ps_selected_mode == SHADER_NONE) {
4642 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4643 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4644 pCaps->PixelShader1xMaxValue = 0.0f;
4645 } else {
4646 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4647 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4648 }
4649
4650 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4651 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4652 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4653
4654 pCaps->VS20Caps = shader_caps.VS20Caps;
4655 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4656 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4657 pCaps->PS20Caps = shader_caps.PS20Caps;
4658 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4659 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4660
4661 /* The following caps are shader specific, but they are things we cannot detect, or which
4662 * are the same among all shader models. So to avoid code duplication set the shader version
4663 * specific, but otherwise constant caps here
4664 */
4665 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4666 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4667 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4668 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4669 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4670 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_vs_temps);
4671 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4672
4673 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4674 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
4675 }
4676 else if (pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0))
4677 {
4678 pCaps->VS20Caps.Caps = 0;
4679 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4680 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_vs_temps);
4681 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4682
4683 pCaps->MaxVShaderInstructionsExecuted = 65535;
4684 pCaps->MaxVertexShader30InstructionSlots = 0;
4685 } else { /* VS 1.x */
4686 pCaps->VS20Caps.Caps = 0;
4687 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4688 pCaps->VS20Caps.NumTemps = 0;
4689 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4690
4691 pCaps->MaxVShaderInstructionsExecuted = 0;
4692 pCaps->MaxVertexShader30InstructionSlots = 0;
4693 }
4694
4695 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4696 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4697 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4698
4699 /* 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 */
4700 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4701 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4702 WINED3DPS20CAPS_PREDICATION |
4703 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4704 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4705 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4706 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_ps_temps);
4707 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4708 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4709
4710 pCaps->MaxPShaderInstructionsExecuted = 65535;
4711 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS,
4712 adapter->gl_info.limits.arb_ps_instructions);
4713 }
4714 else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0))
4715 {
4716 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4717 pCaps->PS20Caps.Caps = 0;
4718 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4719 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_ps_temps);
4720 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4721 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4722
4723 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4724 pCaps->MaxPixelShader30InstructionSlots = 0;
4725 } else { /* PS 1.x */
4726 pCaps->PS20Caps.Caps = 0;
4727 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4728 pCaps->PS20Caps.NumTemps = 0;
4729 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4730 pCaps->PS20Caps.NumInstructionSlots = 0;
4731
4732 pCaps->MaxPShaderInstructionsExecuted = 0;
4733 pCaps->MaxPixelShader30InstructionSlots = 0;
4734 }
4735
4736 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4737 /* OpenGL supports all the formats below, perhaps not always
4738 * without conversion, but it supports them.
4739 * Further GLSL doesn't seem to have an official unsigned type so
4740 * don't advertise it yet as I'm not sure how we handle it.
4741 * We might need to add some clamping in the shader engine to
4742 * support it.
4743 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4744 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4745 WINED3DDTCAPS_UBYTE4N |
4746 WINED3DDTCAPS_SHORT2N |
4747 WINED3DDTCAPS_SHORT4N;
4748 if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
4749 {
4750 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4751 WINED3DDTCAPS_FLOAT16_4;
4752 }
4753 } else
4754 pCaps->DeclTypes = 0;
4755
4756 /* Set DirectDraw helper Caps */
4757 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4758 WINEDDCKEYCAPS_SRCBLT;
4759 fx_caps = WINEDDFXCAPS_BLTALPHA |
4760 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4761 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4762 WINEDDFXCAPS_BLTROTATION90 |
4763 WINEDDFXCAPS_BLTSHRINKX |
4764 WINEDDFXCAPS_BLTSHRINKXN |
4765 WINEDDFXCAPS_BLTSHRINKY |
4766 WINEDDFXCAPS_BLTSHRINKXN |
4767 WINEDDFXCAPS_BLTSTRETCHX |
4768 WINEDDFXCAPS_BLTSTRETCHXN |
4769 WINEDDFXCAPS_BLTSTRETCHY |
4770 WINEDDFXCAPS_BLTSTRETCHYN;
4771 blit_caps = WINEDDCAPS_BLT |
4772 WINEDDCAPS_BLTCOLORFILL |
4773 WINEDDCAPS_BLTDEPTHFILL |
4774 WINEDDCAPS_BLTSTRETCH |
4775 WINEDDCAPS_CANBLTSYSMEM |
4776 WINEDDCAPS_CANCLIP |
4777 WINEDDCAPS_CANCLIPSTRETCHED |
4778 WINEDDCAPS_COLORKEY |
4779 WINEDDCAPS_COLORKEYHWASSIST |
4780 WINEDDCAPS_ALIGNBOUNDARYSRC;
4781
4782 /* Fill the ddraw caps structure */
4783 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4784 WINEDDCAPS_PALETTE |
4785 blit_caps;
4786 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4787 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4788 WINEDDCAPS2_PRIMARYGAMMA |
4789 WINEDDCAPS2_WIDESURFACES |
4790 WINEDDCAPS2_CANRENDERWINDOWED;
4791 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4792 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4793 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4794 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4795 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4796 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4797 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4798 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4799 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4800
4801 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4802 WINEDDSCAPS_BACKBUFFER |
4803 WINEDDSCAPS_FLIP |
4804 WINEDDSCAPS_FRONTBUFFER |
4805 WINEDDSCAPS_OFFSCREENPLAIN |
4806 WINEDDSCAPS_PALETTE |
4807 WINEDDSCAPS_PRIMARYSURFACE |
4808 WINEDDSCAPS_SYSTEMMEMORY |
4809 WINEDDSCAPS_VIDEOMEMORY |
4810 WINEDDSCAPS_VISIBLE;
4811 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4812
4813 /* Set D3D caps if OpenGL is available. */
4814 if (adapter->opengl)
4815 {
4816 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4817 WINEDDSCAPS_MIPMAP |
4818 WINEDDSCAPS_TEXTURE |
4819 WINEDDSCAPS_ZBUFFER;
4820 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4821 }
4822
4823 return WINED3D_OK;
4824}
4825
4826static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT adapter_idx,
4827 WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, IUnknown *parent,
4828 IWineD3DDeviceParent *device_parent, IWineD3DDevice **device)
4829{
4830 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4831 IWineD3DDeviceImpl *object;
4832 HRESULT hr;
4833
4834 TRACE("iface %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x.\n"
4835 "parent %p, device_parent %p, device %p.\n",
4836 iface, adapter_idx, device_type, focus_window, flags,
4837 parent, device_parent, device);
4838
4839 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4840 * number and create a device without a 3D adapter for 2D only operation. */
4841 if (IWineD3D_GetAdapterCount(iface) && adapter_idx >= IWineD3D_GetAdapterCount(iface))
4842 {
4843 return WINED3DERR_INVALIDCALL;
4844 }
4845
4846 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4847 if (!object)
4848 {
4849 ERR("Failed to allocate device memory.\n");
4850 return E_OUTOFMEMORY;
4851 }
4852
4853 hr = device_init(object, This, adapter_idx, device_type, focus_window, flags, parent, device_parent);
4854 if (FAILED(hr))
4855 {
4856 WARN("Failed to initialize device, hr %#x.\n", hr);
4857 HeapFree(GetProcessHeap(), 0, object);
4858 return hr;
4859 }
4860
4861 TRACE("Created device %p.\n", object);
4862 *device = (IWineD3DDevice *)object;
4863
4864 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *device);
4865
4866 return WINED3D_OK;
4867}
4868
4869static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4870 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4871 IUnknown_AddRef(This->parent);
4872 *pParent = This->parent;
4873 return WINED3D_OK;
4874}
4875
4876static void WINE_GLAPI invalid_func(const void *data)
4877{
4878 ERR("Invalid vertex attribute function called\n");
4879 DebugBreak();
4880}
4881
4882static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4883{
4884 ERR("Invalid texcoord function called\n");
4885 DebugBreak();
4886}
4887
4888/* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4889 * the extension detection and are used in drawStridedSlow
4890 */
4891static void WINE_GLAPI position_d3dcolor(const void *data)
4892{
4893 DWORD pos = *((const DWORD *)data);
4894
4895 FIXME("Add a test for fixed function position from d3dcolor type\n");
4896 glVertex4s(D3DCOLOR_B_R(pos),
4897 D3DCOLOR_B_G(pos),
4898 D3DCOLOR_B_B(pos),
4899 D3DCOLOR_B_A(pos));
4900}
4901
4902static void WINE_GLAPI position_float4(const void *data)
4903{
4904 const GLfloat *pos = data;
4905
4906 if (pos[3] != 0.0f && pos[3] != 1.0f)
4907 {
4908 float w = 1.0f / pos[3];
4909
4910 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4911 }
4912 else
4913 {
4914 glVertex3fv(pos);
4915 }
4916}
4917
4918static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4919{
4920 DWORD diffuseColor = *((const DWORD *)data);
4921
4922 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4923 D3DCOLOR_B_G(diffuseColor),
4924 D3DCOLOR_B_B(diffuseColor),
4925 D3DCOLOR_B_A(diffuseColor));
4926}
4927
4928static void WINE_GLAPI specular_d3dcolor(const void *data)
4929{
4930 DWORD specularColor = *((const DWORD *)data);
4931 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4932 D3DCOLOR_B_G(specularColor),
4933 D3DCOLOR_B_B(specularColor)};
4934
4935 specular_func_3ubv(d);
4936}
4937
4938static void WINE_GLAPI warn_no_specular_func(const void *data)
4939{
4940 WARN("GL_EXT_secondary_color not supported\n");
4941}
4942
4943static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4944{
4945 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4946 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4947 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4948 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4949 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4950 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4951 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4952 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4953 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4954 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4955 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4956 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4957 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4958 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4959 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4960 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4961 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4962
4963 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4964 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4965 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4966 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4967 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4968 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4969 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4970 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4971 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4972 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4973 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4974 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4975 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4976 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4977 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4978 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4979 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4980
4981 /* No 4 component entry points here */
4982 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4983 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4984 if (gl_info->supported[EXT_SECONDARY_COLOR])
4985 {
4986 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4987 }
4988 else
4989 {
4990 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4991 }
4992 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4993 if (gl_info->supported[EXT_SECONDARY_COLOR])
4994 {
4995 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4996 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4997 }
4998 else
4999 {
5000 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
5001 }
5002 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
5003 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
5004 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
5005 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
5006 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
5007 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
5008 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
5009 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
5010 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
5011 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
5012 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
5013 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
5014
5015 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
5016 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
5017 */
5018 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
5019 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
5020 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
5021 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
5022 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
5023 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
5024 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
5025 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
5026 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
5027 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
5028 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
5029 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
5030 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
5031 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
5032 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
5033 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
5034 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
5035
5036 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
5037 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
5038 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
5039 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
5040 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
5041 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
5042 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
5043 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
5044 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
5045 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
5046 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
5047 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
5048 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
5049 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
5050 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
5051 if (gl_info->supported[NV_HALF_FLOAT])
5052 {
5053 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
5054 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
5055 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
5056 } else {
5057 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
5058 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
5059 }
5060}
5061
5062static BOOL InitAdapters(IWineD3DImpl *This)
5063{
5064 static HMODULE mod_gl;
5065 BOOL ret;
5066 int ps_selected_mode, vs_selected_mode;
5067
5068 /* No need to hold any lock. The calling library makes sure only one thread calls
5069 * wined3d simultaneously
5070 */
5071
5072 TRACE("Initializing adapters\n");
5073
5074 if(!mod_gl) {
5075#ifdef USE_WIN32_OPENGL
5076#define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
5077#ifdef VBOXWDDM
5078 BOOL (APIENTRY *pDrvValidateVersion)(DWORD) DECLSPEC_HIDDEN;
5079 mod_gl = LoadLibraryA("VBoxOGL.dll");
5080#else
5081 mod_gl = LoadLibraryA("opengl32.dll");
5082#endif
5083 if(!mod_gl) {
5084 ERR("Can't load opengl32.dll!\n");
5085 goto nogl_adapter;
5086 }
5087#ifdef VBOXWDDM
5088 /* init properly */
5089 pDrvValidateVersion = (void*)GetProcAddress(mod_gl, "DrvValidateVersion");
5090 if(!pDrvValidateVersion) {
5091 ERR("Can't get DrvValidateVersion\n");
5092 goto nogl_adapter;
5093 }
5094 if(!pDrvValidateVersion(1)) {
5095 ERR("DrvValidateVersion FAILED\n");
5096 goto nogl_adapter;
5097 }
5098#endif
5099#else
5100#define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
5101 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
5102 mod_gl = GetModuleHandleA("gdi32.dll");
5103#endif
5104 }
5105
5106/* Load WGL core functions from opengl32.dll */
5107#define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
5108 WGL_FUNCS_GEN;
5109#undef USE_WGL_FUNC
5110
5111 if(!pwglGetProcAddress) {
5112 ERR("Unable to load wglGetProcAddress!\n");
5113 goto nogl_adapter;
5114 }
5115
5116/* Dynamically load all GL core functions */
5117 GL_FUNCS_GEN;
5118#undef USE_GL_FUNC
5119
5120 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
5121 * otherwise because we have to use winex11.drv's override
5122 */
5123#ifdef USE_WIN32_OPENGL
5124 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
5125 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
5126#else
5127 wglFinish = (void*)pwglGetProcAddress("wglFinish");
5128 wglFlush = (void*)pwglGetProcAddress("wglFlush");
5129#endif
5130
5131 glEnableWINE = glEnable;
5132 glDisableWINE = glDisable;
5133
5134 /* For now only one default adapter */
5135 {
5136 struct wined3d_adapter *adapter = &This->adapters[0];
5137 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
5138 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
5139 int iPixelFormat;
5140 int res;
5141 int i;
5142 WineD3D_PixelFormat *cfgs;
5143 DISPLAY_DEVICEW DisplayDevice;
5144 HDC hdc;
5145
5146 TRACE("Initializing default adapter\n");
5147 adapter->ordinal = 0;
5148 adapter->monitorPoint.x = -1;
5149 adapter->monitorPoint.y = -1;
5150
5151 if (!AllocateLocallyUniqueId(&adapter->luid))
5152 {
5153 DWORD err = GetLastError();
5154 ERR("Failed to set adapter LUID (%#x).\n", err);
5155 goto nogl_adapter;
5156 }
5157 TRACE("Allocated LUID %08x:%08x for adapter.\n",
5158 adapter->luid.HighPart, adapter->luid.LowPart);
5159
5160 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
5161 {
5162 ERR("Failed to get a gl context for default adapter\n");
5163 goto nogl_adapter;
5164 }
5165
5166 ret = IWineD3DImpl_FillGLCaps(adapter);
5167 if(!ret) {
5168 ERR("Failed to initialize gl caps for default adapter\n");
5169 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5170 goto nogl_adapter;
5171 }
5172 ret = initPixelFormats(&adapter->gl_info, adapter->driver_info.vendor);
5173 if(!ret) {
5174 ERR("Failed to init gl formats\n");
5175 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5176 goto nogl_adapter;
5177 }
5178
5179 hdc = fake_gl_ctx.dc;
5180
5181 /* Use the VideoRamSize registry setting when set */
5182 if(wined3d_settings.emulated_textureram)
5183 adapter->TextureRam = wined3d_settings.emulated_textureram;
5184 else
5185 adapter->TextureRam = adapter->gl_info.vidmem;
5186 adapter->UsedTextureRam = 0;
5187 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
5188
5189 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
5190 DisplayDevice.cb = sizeof(DisplayDevice);
5191 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
5192 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
5193 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
5194
5195 if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
5196 {
5197 int attribute;
5198 int attribs[11];
5199 int values[11];
5200 int nAttribs = 0;
5201
5202 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
5203 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
5204
5205 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
5206 cfgs = adapter->cfgs;
5207 attribs[nAttribs++] = WGL_RED_BITS_ARB;
5208 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
5209 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
5210 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
5211 attribs[nAttribs++] = WGL_COLOR_BITS_ARB;
5212 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
5213 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
5214 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
5215 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
5216 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
5217 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
5218
5219 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
5220 {
5221 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
5222
5223 if(!res)
5224 continue;
5225
5226 /* Cache the pixel format */
5227 cfgs->iPixelFormat = iPixelFormat;
5228 cfgs->redSize = values[0];
5229 cfgs->greenSize = values[1];
5230 cfgs->blueSize = values[2];
5231 cfgs->alphaSize = values[3];
5232 cfgs->colorSize = values[4];
5233 cfgs->depthSize = values[5];
5234 cfgs->stencilSize = values[6];
5235 cfgs->windowDrawable = values[7];
5236 cfgs->iPixelType = values[8];
5237 cfgs->doubleBuffer = values[9];
5238 cfgs->auxBuffers = values[10];
5239
5240 cfgs->numSamples = 0;
5241 /* Check multisample support */
5242 if (gl_info->supported[ARB_MULTISAMPLE])
5243 {
5244 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
5245 int value[2];
5246 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
5247 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
5248 * value[1] = number of multi sample buffers*/
5249 if(value[0])
5250 cfgs->numSamples = value[1];
5251 }
5252 }
5253
5254 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
5255 "depth=%d, stencil=%d, samples=%d, windowDrawable=%d\n",
5256 cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer,
5257 cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize,
5258 cfgs->depthSize, cfgs->stencilSize, cfgs->numSamples, cfgs->windowDrawable);
5259 cfgs++;
5260 }
5261 }
5262 else
5263 {
5264 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
5265 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
5266 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
5267
5268 cfgs = adapter->cfgs;
5269 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
5270 {
5271 PIXELFORMATDESCRIPTOR ppfd;
5272
5273 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
5274 if(!res)
5275 continue;
5276
5277 /* We only want HW acceleration using an OpenGL ICD driver.
5278 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
5279 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
5280 */
5281 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
5282 {
5283 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
5284 continue;
5285 }
5286
5287 cfgs->iPixelFormat = iPixelFormat;
5288 cfgs->redSize = ppfd.cRedBits;
5289 cfgs->greenSize = ppfd.cGreenBits;
5290 cfgs->blueSize = ppfd.cBlueBits;
5291 cfgs->alphaSize = ppfd.cAlphaBits;
5292 cfgs->colorSize = ppfd.cColorBits;
5293 cfgs->depthSize = ppfd.cDepthBits;
5294 cfgs->stencilSize = ppfd.cStencilBits;
5295 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
5296 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
5297 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
5298 cfgs->auxBuffers = ppfd.cAuxBuffers;
5299 cfgs->numSamples = 0;
5300
5301 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
5302 "depth=%d, stencil=%d, windowDrawable=%d\n",
5303 cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer,
5304 cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize,
5305 cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable);
5306 cfgs++;
5307 adapter->nCfgs++;
5308 }
5309
5310 /* 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 */
5311 if(!adapter->nCfgs)
5312 {
5313 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
5314
5315 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5316 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
5317 goto nogl_adapter;
5318 }
5319 }
5320
5321 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
5322 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
5323 * but just fake it using D24(X8?) which is fine. D3D also allows that.
5324 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
5325 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
5326 * driver is allowed to consume more bits EXCEPT for stencil bits.
5327 *
5328 * Mark an adapter with this broken stencil behavior.
5329 */
5330 adapter->brokenStencil = TRUE;
5331 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
5332 {
5333 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
5334 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
5335 adapter->brokenStencil = FALSE;
5336 break;
5337 }
5338 }
5339
5340 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
5341
5342 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
5343 fillGLAttribFuncs(&adapter->gl_info);
5344 adapter->opengl = TRUE;
5345 }
5346 This->adapter_count = 1;
5347 TRACE("%u adapters successfully initialized\n", This->adapter_count);
5348
5349 return TRUE;
5350
5351nogl_adapter:
5352 /* Initialize an adapter for ddraw-only memory counting */
5353 memset(This->adapters, 0, sizeof(This->adapters));
5354 This->adapters[0].ordinal = 0;
5355 This->adapters[0].opengl = FALSE;
5356 This->adapters[0].monitorPoint.x = -1;
5357 This->adapters[0].monitorPoint.y = -1;
5358
5359 This->adapters[0].driver_info.name = "Display";
5360 This->adapters[0].driver_info.description = "WineD3D DirectDraw Emulation";
5361 if(wined3d_settings.emulated_textureram) {
5362 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
5363 } else {
5364 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
5365 }
5366
5367 initPixelFormatsNoGL(&This->adapters[0].gl_info);
5368
5369 This->adapter_count = 1;
5370 return FALSE;
5371}
5372
5373/**********************************************************
5374 * IWineD3D VTbl follows
5375 **********************************************************/
5376
5377static const struct IWineD3DVtbl IWineD3D_Vtbl =
5378{
5379 /* IUnknown */
5380 IWineD3DImpl_QueryInterface,
5381 IWineD3DImpl_AddRef,
5382 IWineD3DImpl_Release,
5383 /* IWineD3D */
5384 IWineD3DImpl_GetParent,
5385 IWineD3DImpl_GetAdapterCount,
5386 IWineD3DImpl_RegisterSoftwareDevice,
5387 IWineD3DImpl_GetAdapterMonitor,
5388 IWineD3DImpl_GetAdapterModeCount,
5389 IWineD3DImpl_EnumAdapterModes,
5390 IWineD3DImpl_GetAdapterDisplayMode,
5391 IWineD3DImpl_GetAdapterIdentifier,
5392 IWineD3DImpl_CheckDeviceMultiSampleType,
5393 IWineD3DImpl_CheckDepthStencilMatch,
5394 IWineD3DImpl_CheckDeviceType,
5395 IWineD3DImpl_CheckDeviceFormat,
5396 IWineD3DImpl_CheckDeviceFormatConversion,
5397 IWineD3DImpl_GetDeviceCaps,
5398 IWineD3DImpl_CreateDevice
5399};
5400
5401static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
5402
5403const struct wined3d_parent_ops wined3d_null_parent_ops =
5404{
5405 wined3d_null_wined3d_object_destroyed,
5406};
5407
5408HRESULT wined3d_init(IWineD3DImpl *wined3d, UINT version, IUnknown *parent)
5409{
5410 wined3d->lpVtbl = &IWineD3D_Vtbl;
5411 wined3d->dxVersion = version;
5412 wined3d->ref = 1;
5413 wined3d->parent = parent;
5414
5415 if (!InitAdapters(wined3d))
5416 {
5417 WARN("Failed to initialize adapters.\n");
5418 if (version > 7)
5419 {
5420 MESSAGE("Direct3D%u is not available without OpenGL.\n", version);
5421 return E_FAIL;
5422 }
5423 }
5424
5425 return WINED3D_OK;
5426}
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