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