adding the last hack we need for wined3d. This bug is wine, not our or windows fault
[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 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24 /* Compile time diagnostics: */
25
26 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
29 #endif
30
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 /* Extension detection */
40 static const struct {
41 const char *extension_string;
42 GL_SupportedExt extension;
43 DWORD version;
44 } EXTENSION_MAP[] = {
45 /* APPLE */
46 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
47 {"GL_APPLE_fence", APPLE_FENCE, 0 },
48 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
49 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
50
51 /* ATI */
52 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
53 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
54 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
55 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP, 0 },
56
57 /* ARB */
58 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
59 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
60 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
61 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
62 {"GL_ARB_imaging", ARB_IMAGING, 0 },
63 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
64 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
65 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
66 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
67 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
68 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
69 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
70 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
71 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
72 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
73 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
74 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
75 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
76 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
77 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, 0 },
78 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
79 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
80 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
81 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
82 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
83
84 /* EXT */
85 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
86 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
87 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
88 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
89 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
90 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
91 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
92 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
93 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
94 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
95 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
96 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
97 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
98 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
99 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
100 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
101 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
102 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
103 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
104 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
105
106 /* NV */
107 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
108 {"GL_NV_fence", NV_FENCE, 0 },
109 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
110 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
111 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
112 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
113 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
114 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
115 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
116 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
117 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
118 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
119 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
120 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
121 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
122 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
123 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
124 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
125
126 /* SGI */
127 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
128 };
129
130 /**********************************************************
131 * Utility functions follow
132 **********************************************************/
133
134 /* Adapters */
135 static int numAdapters = 0;
136 static struct WineD3DAdapter Adapters[1];
137
138 /* lookup tables */
139 int minLookup[MAX_LOOKUPS];
140 int maxLookup[MAX_LOOKUPS];
141 DWORD *stateLookup[MAX_LOOKUPS];
142
143 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
144
145
146 /**
147 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
148 * ie there is no GL Context - Get a default rendering context to enable the
149 * function query some info from GL
150 */
151
152 static int wined3d_fake_gl_context_ref = 0;
153 static BOOL wined3d_fake_gl_context_foreign;
154 static BOOL wined3d_fake_gl_context_available = FALSE;
155 static HDC wined3d_fake_gl_context_hdc = NULL;
156 static HWND wined3d_fake_gl_context_hwnd = NULL;
157
158 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
159 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
160 {
161 0, 0, &wined3d_fake_gl_context_cs,
162 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
163 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
164 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
165 };
166 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
167
168 static void WineD3D_ReleaseFakeGLContext(void) {
169 HGLRC glCtx;
170
171 EnterCriticalSection(&wined3d_fake_gl_context_cs);
172
173 if(!wined3d_fake_gl_context_available) {
174 TRACE_(d3d_caps)("context not available\n");
175 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
176 return;
177 }
178
179 glCtx = pwglGetCurrentContext();
180
181 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
182 if (0 == (--wined3d_fake_gl_context_ref) ) {
183 if(!wined3d_fake_gl_context_foreign && glCtx) {
184 TRACE_(d3d_caps)("destroying fake GL context\n");
185 pwglMakeCurrent(NULL, NULL);
186 //ros hack, this line does destire the real icd interface in windows and reactos
187 // pwglDeleteContext(glCtx);
188 }
189 if(wined3d_fake_gl_context_hdc)
190 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
191 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
192 if(wined3d_fake_gl_context_hwnd)
193 DestroyWindow(wined3d_fake_gl_context_hwnd);
194 wined3d_fake_gl_context_hwnd = NULL;
195 wined3d_fake_gl_context_available = FALSE;
196 }
197 assert(wined3d_fake_gl_context_ref >= 0);
198
199 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
200 }
201
202 static BOOL WineD3D_CreateFakeGLContext(void) {
203 HGLRC glCtx = NULL;
204
205 EnterCriticalSection(&wined3d_fake_gl_context_cs);
206
207 TRACE("getting context...\n");
208 if(wined3d_fake_gl_context_ref > 0) goto ret;
209 assert(0 == wined3d_fake_gl_context_ref);
210
211 wined3d_fake_gl_context_foreign = TRUE;
212
213 glCtx = pwglGetCurrentContext();
214 if (!glCtx) {
215 PIXELFORMATDESCRIPTOR pfd;
216 int iPixelFormat;
217
218 wined3d_fake_gl_context_foreign = FALSE;
219
220 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
221 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
222 if(!wined3d_fake_gl_context_hwnd) {
223 ERR("HWND creation failed!\n");
224 goto fail;
225 }
226 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
227 if(!wined3d_fake_gl_context_hdc) {
228 ERR("GetDC failed!\n");
229 goto fail;
230 }
231
232 /* PixelFormat selection */
233 ZeroMemory(&pfd, sizeof(pfd));
234 pfd.nSize = sizeof(pfd);
235 pfd.nVersion = 1;
236 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
237 pfd.iPixelType = PFD_TYPE_RGBA;
238 pfd.cColorBits = 32;
239 pfd.iLayerType = PFD_MAIN_PLANE;
240
241 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
242 if(!iPixelFormat) {
243 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
244 ERR("Can't find a suitable iPixelFormat\n");
245 goto fail;
246 }
247 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
248 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
249
250 /* Create a GL context */
251 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
252 if (!glCtx) {
253 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
254 goto fail;
255 }
256
257 /* Make it the current GL context */
258 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
259 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
260 goto fail;
261 }
262 }
263
264 ret:
265 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
266 wined3d_fake_gl_context_ref++;
267 wined3d_fake_gl_context_available = TRUE;
268 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
269 return TRUE;
270 fail:
271 if(wined3d_fake_gl_context_hdc)
272 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
273 wined3d_fake_gl_context_hdc = NULL;
274 if(wined3d_fake_gl_context_hwnd)
275 DestroyWindow(wined3d_fake_gl_context_hwnd);
276 wined3d_fake_gl_context_hwnd = NULL;
277 if(glCtx) pwglDeleteContext(glCtx);
278 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
279 return FALSE;
280 }
281
282 /* Adjust the amount of used texture memory */
283 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
284 UINT Adapter = D3DDevice->adapterNo;
285
286 Adapters[Adapter].UsedTextureRam += glram;
287 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
288 return Adapters[Adapter].UsedTextureRam;
289 }
290
291 /**********************************************************
292 * IUnknown parts follows
293 **********************************************************/
294
295 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
296 {
297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
298
299 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
300 if (IsEqualGUID(riid, &IID_IUnknown)
301 || IsEqualGUID(riid, &IID_IWineD3DBase)
302 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
303 IUnknown_AddRef(iface);
304 *ppobj = This;
305 return S_OK;
306 }
307 *ppobj = NULL;
308 return E_NOINTERFACE;
309 }
310
311 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
312 IWineD3DImpl *This = (IWineD3DImpl *)iface;
313 ULONG refCount = InterlockedIncrement(&This->ref);
314
315 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
316 return refCount;
317 }
318
319 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
320 IWineD3DImpl *This = (IWineD3DImpl *)iface;
321 ULONG ref;
322 TRACE("(%p) : Releasing from %d\n", This, This->ref);
323 ref = InterlockedDecrement(&This->ref);
324 if (ref == 0) {
325 HeapFree(GetProcessHeap(), 0, This);
326 }
327
328 return ref;
329 }
330
331 /* Set the shader type for this device, depending on the given capabilities,
332 * the device type, and the user preferences in wined3d_settings */
333
334 static void select_shader_mode(
335 WineD3D_GL_Info *gl_info,
336 WINED3DDEVTYPE DeviceType,
337 int* ps_selected,
338 int* vs_selected) {
339
340 if (wined3d_settings.vs_mode == VS_NONE) {
341 *vs_selected = SHADER_NONE;
342 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
343 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
344 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
345 * shaders only on this card. */
346 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
347 *vs_selected = SHADER_ARB;
348 else
349 *vs_selected = SHADER_GLSL;
350 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
351 *vs_selected = SHADER_ARB;
352 } else {
353 *vs_selected = SHADER_NONE;
354 }
355
356 if (wined3d_settings.ps_mode == PS_NONE) {
357 *ps_selected = SHADER_NONE;
358 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
359 *ps_selected = SHADER_GLSL;
360 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
361 *ps_selected = SHADER_ARB;
362 } else {
363 *ps_selected = SHADER_NONE;
364 }
365 }
366
367 /** Select the number of report maximum shader constants based on the selected shader modes */
368 static void select_shader_max_constants(
369 int ps_selected_mode,
370 int vs_selected_mode,
371 WineD3D_GL_Info *gl_info) {
372
373 switch (vs_selected_mode) {
374 case SHADER_GLSL:
375 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
376 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
377 break;
378 case SHADER_ARB:
379 /* We have to subtract any other PARAMs that we might use in our shader programs.
380 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
381 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
382 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
383 break;
384 default:
385 gl_info->max_vshader_constantsF = 0;
386 break;
387 }
388
389 switch (ps_selected_mode) {
390 case SHADER_GLSL:
391 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
392 * In theory the texbem instruction may need one more shader constant too. But lets assume
393 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
394 * and lets not take away a uniform needlessly from all other shaders.
395 */
396 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
397 break;
398 case SHADER_ARB:
399 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
400 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
401 */
402 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
403 break;
404 default:
405 gl_info->max_pshader_constantsF = 0;
406 break;
407 }
408 }
409
410 /**********************************************************
411 * IWineD3D parts follows
412 **********************************************************/
413
414 #define GLINFO_LOCATION (*gl_info)
415 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
416 GLuint prog;
417 BOOL ret = FALSE;
418 const char *testcode =
419 "!!ARBvp1.0\n"
420 "PARAM C[66] = { program.env[0..65] };\n"
421 "ADDRESS A0;"
422 "ARL A0.x, 0.0;\n"
423 "MOV result.position, C[A0.x + 65];\n"
424 "END\n";
425
426 while(glGetError());
427 GL_EXTCALL(glGenProgramsARB(1, &prog));
428 if(!prog) {
429 ERR("Failed to create an ARB offset limit test program\n");
430 }
431 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
432 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
433 strlen(testcode), testcode));
434 if(glGetError() != 0) {
435 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
436 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
437 ret = TRUE;
438 } else TRACE("OpenGL implementation allows offsets > 63\n");
439
440 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
441 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
442 checkGLcall("ARB vp offset limit test cleanup\n");
443
444 return ret;
445 }
446
447 static DWORD ver_for_ext(GL_SupportedExt ext)
448 {
449 unsigned int i;
450 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
451 if(EXTENSION_MAP[i].extension == ext) {
452 return EXTENSION_MAP[i].version;
453 }
454 }
455 return 0;
456 }
457
458 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
459 const char *GL_Extensions = NULL;
460 const char *WGL_Extensions = NULL;
461 const char *gl_string = NULL;
462 const char *gl_string_cursor = NULL;
463 GLint gl_max;
464 GLfloat gl_floatv[2];
465 int major = 1, minor = 0;
466 BOOL return_value = TRUE;
467 int i;
468 HDC hdc;
469 unsigned int vidmem=0;
470
471 TRACE_(d3d_caps)("(%p)\n", gl_info);
472
473 ENTER_GL();
474
475 gl_string = (const char *) glGetString(GL_RENDERER);
476 if (NULL == gl_string)
477 gl_string = "None";
478 strcpy(gl_info->gl_renderer, gl_string);
479
480 gl_string = (const char *) glGetString(GL_VENDOR);
481 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
482 if (gl_string != NULL) {
483 /* Fill in the GL vendor */
484 if (strstr(gl_string, "NVIDIA")) {
485 gl_info->gl_vendor = VENDOR_NVIDIA;
486 } else if (strstr(gl_string, "ATI")) {
487 gl_info->gl_vendor = VENDOR_ATI;
488 } else if (strstr(gl_string, "Intel(R)") ||
489 strstr(gl_info->gl_renderer, "Intel(R)")) {
490 gl_info->gl_vendor = VENDOR_INTEL;
491 } else if (strstr(gl_string, "Mesa")) {
492 gl_info->gl_vendor = VENDOR_MESA;
493 } else {
494 gl_info->gl_vendor = VENDOR_WINE;
495 }
496 } else {
497 gl_info->gl_vendor = VENDOR_WINE;
498 }
499
500
501 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
502
503 /* Parse the GL_VERSION field into major and minor information */
504 gl_string = (const char *) glGetString(GL_VERSION);
505 if (gl_string != NULL) {
506
507 switch (gl_info->gl_vendor) {
508 case VENDOR_NVIDIA:
509 gl_string_cursor = strstr(gl_string, "NVIDIA");
510 if (!gl_string_cursor) {
511 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
512 break;
513 }
514
515 gl_string_cursor = strstr(gl_string_cursor, " ");
516 if (!gl_string_cursor) {
517 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
518 break;
519 }
520
521 while (*gl_string_cursor == ' ') {
522 ++gl_string_cursor;
523 }
524
525 if (!*gl_string_cursor) {
526 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
527 break;
528 }
529
530 major = atoi(gl_string_cursor);
531 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
532 ++gl_string_cursor;
533 }
534
535 if (*gl_string_cursor++ != '.') {
536 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
537 break;
538 }
539
540 minor = atoi(gl_string_cursor);
541 minor = major*100+minor;
542 major = 10;
543
544 break;
545
546 case VENDOR_ATI:
547 major = minor = 0;
548 gl_string_cursor = strchr(gl_string, '-');
549 if (gl_string_cursor) {
550 int error = 0;
551 gl_string_cursor++;
552
553 /* Check if version number is of the form x.y.z */
554 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
555 error = 1;
556 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
557 error = 1;
558 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
559 error = 1;
560 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
561 error = 1;
562
563 /* Mark version number as malformed */
564 if (error)
565 gl_string_cursor = 0;
566 }
567
568 if (!gl_string_cursor)
569 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
570 else {
571 major = *gl_string_cursor - '0';
572 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
573 }
574 break;
575
576 case VENDOR_INTEL:
577 case VENDOR_MESA:
578 gl_string_cursor = strstr(gl_string, "Mesa");
579 gl_string_cursor = strstr(gl_string_cursor, " ");
580 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
581 if (*gl_string_cursor) {
582 char tmp[16];
583 int cursor = 0;
584
585 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
586 tmp[cursor++] = *gl_string_cursor;
587 ++gl_string_cursor;
588 }
589 tmp[cursor] = 0;
590 major = atoi(tmp);
591
592 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
593 ++gl_string_cursor;
594
595 cursor = 0;
596 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
597 tmp[cursor++] = *gl_string_cursor;
598 ++gl_string_cursor;
599 }
600 tmp[cursor] = 0;
601 minor = atoi(tmp);
602 }
603 break;
604
605 default:
606 major = 0;
607 minor = 9;
608 }
609 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
610 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
611 }
612
613 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
614
615 /*
616 * Initialize openGL extension related variables
617 * with Default values
618 */
619 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
620 gl_info->max_buffers = 1;
621 gl_info->max_textures = 1;
622 gl_info->max_texture_stages = 1;
623 gl_info->max_fragment_samplers = 1;
624 gl_info->max_vertex_samplers = 0;
625 gl_info->max_combined_samplers = 0;
626 gl_info->max_sampler_stages = 1;
627 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
628 gl_info->ps_arb_max_temps = 0;
629 gl_info->ps_arb_max_instructions = 0;
630 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
631 gl_info->vs_arb_max_temps = 0;
632 gl_info->vs_arb_max_instructions = 0;
633 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
634 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
635 gl_info->vs_glsl_constantsF = 0;
636 gl_info->ps_glsl_constantsF = 0;
637 gl_info->vs_arb_constantsF = 0;
638 gl_info->ps_arb_constantsF = 0;
639
640 /* Retrieve opengl defaults */
641 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
642 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
643 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
644
645 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
646 gl_info->max_lights = gl_max;
647 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
648
649 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
650 gl_info->max_texture_size = gl_max;
651 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
652
653 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
654 gl_info->max_pointsizemin = gl_floatv[0];
655 gl_info->max_pointsize = gl_floatv[1];
656 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
657
658 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
659 gl_info->max_aux_buffers = gl_max;
660 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
661
662 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
663 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
664 TRACE_(d3d_caps)("GL_Extensions reported:\n");
665
666 if (NULL == GL_Extensions) {
667 ERR(" GL_Extensions returns NULL\n");
668 } else {
669 while (*GL_Extensions != 0x00) {
670 const char *Start;
671 char ThisExtn[256];
672 size_t len;
673
674 while (isspace(*GL_Extensions)) GL_Extensions++;
675 Start = GL_Extensions;
676 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
677 GL_Extensions++;
678 }
679
680 len = GL_Extensions - Start;
681 if (len == 0 || len >= sizeof(ThisExtn))
682 continue;
683
684 memcpy(ThisExtn, Start, len);
685 ThisExtn[len] = '\0';
686 TRACE_(d3d_caps)("- %s\n", ThisExtn);
687
688 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
689 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
690 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
691 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
692 break;
693 }
694 }
695 }
696 /* Now work out what GL support this card really has */
697 #define USE_GL_FUNC(type, pfn, ext, replace) { \
698 DWORD ver = ver_for_ext(ext); \
699 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
700 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
701 else gl_info->pfn = NULL; \
702 }
703 GL_EXT_FUNCS_GEN;
704 #undef USE_GL_FUNC
705
706 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
707 WGL_EXT_FUNCS_GEN;
708 #undef USE_GL_FUNC
709
710 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
711 * loading the functions, otherwise the code above will load the extension entry points instead of the
712 * core functions, which may not work
713 */
714 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
715 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
716 EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
717 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
718 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
719 }
720 }
721
722 if (gl_info->supported[APPLE_FENCE]) {
723 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
724 * The apple extension interacts with some other apple exts. Disable the NV
725 * extension if the apple one is support to prevent confusion in other parts
726 * of the code
727 */
728 gl_info->supported[NV_FENCE] = FALSE;
729 }
730 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
731 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
732 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
733 }
734 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
735 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
736 * Won't occur in any real world situation though
737 */
738 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
739 }
740 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
741 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
742 gl_info->max_buffers = gl_max;
743 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
744 }
745 if (gl_info->supported[ARB_MULTITEXTURE]) {
746 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
747 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
748 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
749
750 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
751 GLint tmp;
752 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
753 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
754 } else {
755 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
756 }
757 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
758
759 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
760 GLint tmp;
761 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
762 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
763 } else {
764 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
765 }
766 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
767
768 if (gl_info->supported[ARB_VERTEX_SHADER]) {
769 GLint tmp;
770 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
771 gl_info->max_vertex_samplers = tmp;
772 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
773 gl_info->max_combined_samplers = tmp;
774
775 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
776 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
777 * an issue because then the sampler setup only depends on the two shaders. If a pixel
778 * shader is used with fixed function vertex processing we're fine too because fixed function
779 * vertex processing doesn't use any samplers. If fixed function fragment processing is
780 * used we have to make sure that all vertex sampler setups are valid together with all
781 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
782 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
783 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
784 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
785 * a fixed function pipeline anymore.
786 *
787 * So this is just a check to check that our assumption holds true. If not, write a warning
788 * and reduce the number of vertex samplers or propably disable vertex texture fetch.
789 */
790 if(gl_info->max_vertex_samplers &&
791 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
792 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
793 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
794 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
795 gl_info->max_vertex_samplers = max(0, gl_info->max_combined_samplers - MAX_TEXTURES);
796 }
797 } else {
798 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
799 }
800 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
801 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
802 }
803 if (gl_info->supported[ARB_VERTEX_BLEND]) {
804 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
805 gl_info->max_blends = gl_max;
806 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
807 }
808 if (gl_info->supported[EXT_TEXTURE3D]) {
809 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
810 gl_info->max_texture3d_size = gl_max;
811 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
812 }
813 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
814 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
815 gl_info->max_anisotropy = gl_max;
816 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
817 }
818 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
819 gl_info->ps_arb_version = PS_VERSION_11;
820 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
821 gl_info->ps_arb_constantsF = gl_max;
822 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
823 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
824 gl_info->ps_arb_max_temps = gl_max;
825 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
826 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
827 gl_info->ps_arb_max_instructions = gl_max;
828 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
829 }
830 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
831 gl_info->vs_arb_version = VS_VERSION_11;
832 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
833 gl_info->vs_arb_constantsF = gl_max;
834 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
835 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
836 gl_info->vs_arb_max_temps = gl_max;
837 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
838 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
839 gl_info->vs_arb_max_instructions = gl_max;
840 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
841
842 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
843 }
844 if (gl_info->supported[ARB_VERTEX_SHADER]) {
845 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
846 gl_info->vs_glsl_constantsF = gl_max / 4;
847 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
848 }
849 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
850 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
851 gl_info->ps_glsl_constantsF = gl_max / 4;
852 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
853 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
854 gl_info->max_glsl_varyings = gl_max;
855 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
856 }
857 if (gl_info->supported[EXT_VERTEX_SHADER]) {
858 gl_info->vs_ati_version = VS_VERSION_11;
859 }
860 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
861 gl_info->vs_nv_version = VS_VERSION_30;
862 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
863 gl_info->vs_nv_version = VS_VERSION_20;
864 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
865 gl_info->vs_nv_version = VS_VERSION_11;
866 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
867 gl_info->vs_nv_version = VS_VERSION_10;
868 }
869 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
870 gl_info->ps_nv_version = PS_VERSION_30;
871 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
872 gl_info->ps_nv_version = PS_VERSION_20;
873 }
874
875 }
876 checkGLcall("extension detection\n");
877
878 /* In some cases the number of texture stages can be larger than the number
879 * of samplers. The GF4 for example can use only 2 samplers (no fragment
880 * shaders), but 8 texture stages (register combiners). */
881 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
882
883 /* We can only use ORM_FBO when the hardware supports it. */
884 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
885 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
886 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
887 }
888
889 /* MRTs are currently only supported when FBOs are used. */
890 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
891 gl_info->max_buffers = 1;
892 }
893
894 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
895 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
896 * in case of the latest videocards in the number of pixel/vertex pipelines.
897 *
898 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
899 * rendering. Various games use this information to get a rough estimation of the features of the card
900 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
901 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
902 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
903 * not the PCI id.
904 *
905 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
906 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
907 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
908 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
909 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
910 * is used for rendering which is not always the case). This would work but it is not very portable. Second
911 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
912 * is limited.
913 *
914 * As said most games only use the PCI id to get an indication of the capabilities of the card.
915 * It doesn't really matter if the given id is the correct one if we return the id of a card with
916 * similar 3d features.
917 *
918 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
919 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
920 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
921 * won't pass we return a default card. This way is better than maintaining a full card database as even
922 * without a full database we can return a card with similar features. Second the size of the database
923 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
924 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
925 * to distinguishes between different models from that family.
926 *
927 * The code also selects a default amount of video memory which we will use for an estimation of the amount
928 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
929 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
930 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
931 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
932 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
933 * memory behind our backs if really needed.
934 * Note that the amout of video memory can be overruled using a registry setting.
935 */
936 switch (gl_info->gl_vendor) {
937 case VENDOR_NVIDIA:
938 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
939 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
940 */
941 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
942 /* Geforce8 - highend */
943 if (strstr(gl_info->gl_renderer, "8800")) {
944 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
945 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
946 }
947 /* Geforce8 - midend */
948 else if(strstr(gl_info->gl_renderer, "8600") ||
949 strstr(gl_info->gl_renderer, "8700"))
950 {
951 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
952 vidmem = 256;
953 }
954 /* Geforce8 - lowend */
955 else if(strstr(gl_info->gl_renderer, "8300") ||
956 strstr(gl_info->gl_renderer, "8400") ||
957 strstr(gl_info->gl_renderer, "8500"))
958 {
959 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
960 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
961 }
962 /* Geforce7 - highend */
963 else if(strstr(gl_info->gl_renderer, "7800") ||
964 strstr(gl_info->gl_renderer, "7900") ||
965 strstr(gl_info->gl_renderer, "7950") ||
966 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
967 strstr(gl_info->gl_renderer, "Quadro FX 5"))
968 {
969 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
970 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
971 }
972 /* Geforce7 midend / Geforce6 highend */
973 else if(strstr(gl_info->gl_renderer, "6800") ||
974 strstr(gl_info->gl_renderer, "7600") ||
975 strstr(gl_info->gl_renderer, "7700"))
976 {
977 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
978 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
979 }
980 /* Geforce6 - midend */
981 else if(strstr(gl_info->gl_renderer, "6600") ||
982 strstr(gl_info->gl_renderer, "6610") ||
983 strstr(gl_info->gl_renderer, "6700"))
984 {
985 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
986 vidmem = 128; /* A 6600GT has 128-256MB */
987 }
988 /* Geforce6/7 lowend */
989 else {
990 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
991 vidmem = 64; /* */
992 }
993 } else if(WINE_D3D9_CAPABLE(gl_info)) {
994 /* GeforceFX - highend */
995 if (strstr(gl_info->gl_renderer, "5800") ||
996 strstr(gl_info->gl_renderer, "5900") ||
997 strstr(gl_info->gl_renderer, "5950") ||
998 strstr(gl_info->gl_renderer, "Quadro FX"))
999 {
1000 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1001 vidmem = 256; /* 5800-5900 cards use 256MB */
1002 }
1003 /* GeforceFX - midend */
1004 else if(strstr(gl_info->gl_renderer, "5600") ||
1005 strstr(gl_info->gl_renderer, "5650") ||
1006 strstr(gl_info->gl_renderer, "5700") ||
1007 strstr(gl_info->gl_renderer, "5750"))
1008 {
1009 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1010 vidmem = 128; /* A 5600 uses 128-256MB */
1011 }
1012 /* GeforceFX - lowend */
1013 else {
1014 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1015 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1016 }
1017 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1018 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1019 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1020 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1021 }
1022 else {
1023 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1024 vidmem = 64; /* Geforce3 cards have 64-128MB */
1025 }
1026 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1027 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1028 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1029 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1030 }
1031 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1032 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1033 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1034 }
1035 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1036 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1037 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1038 }
1039 else {
1040 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1041 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1042 }
1043 } else {
1044 if (strstr(gl_info->gl_renderer, "TNT2")) {
1045 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1046 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1047 }
1048 else {
1049 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1050 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1051 }
1052 }
1053 break;
1054 case VENDOR_ATI:
1055 if(WINE_D3D9_CAPABLE(gl_info)) {
1056 /* Radeon R6xx HD2900 - highend */
1057 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1058 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1059 vidmem = 512; /* HD2900 uses 512-1024MB */
1060 }
1061 /* Radeon R6xx HD2600- midend */
1062 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1063 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1064 vidmem = 256; /* HD2600 uses 256-512MB */
1065 }
1066 /* Radeon R6xx HD2300/HD2400 - lowend */
1067 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1068 strstr(gl_info->gl_renderer, "HD 2400"))
1069 {
1070 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1071 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1072 }
1073 /* Radeon R5xx */
1074 else if (strstr(gl_info->gl_renderer, "X1600") ||
1075 strstr(gl_info->gl_renderer, "X1650") ||
1076 strstr(gl_info->gl_renderer, "X1800") ||
1077 strstr(gl_info->gl_renderer, "X1900") ||
1078 strstr(gl_info->gl_renderer, "X1950"))
1079 {
1080 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1081 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1082 }
1083 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1084 else if(strstr(gl_info->gl_renderer, "X700") ||
1085 strstr(gl_info->gl_renderer, "X800") ||
1086 strstr(gl_info->gl_renderer, "X850") ||
1087 strstr(gl_info->gl_renderer, "X1300") ||
1088 strstr(gl_info->gl_renderer, "X1400") ||
1089 strstr(gl_info->gl_renderer, "X1450") ||
1090 strstr(gl_info->gl_renderer, "X1550"))
1091 {
1092 gl_info->gl_card = CARD_ATI_RADEON_X700;
1093 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1094 }
1095 /* Radeon R3xx */
1096 else {
1097 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1098 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1099 }
1100 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1101 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1102 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1103 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1104 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1105 vidmem = 32; /* There are models with up to 64MB */
1106 } else {
1107 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1108 vidmem = 16; /* There are 16-32MB models */
1109 }
1110 break;
1111 case VENDOR_INTEL:
1112 if (strstr(gl_info->gl_renderer, "915GM")) {
1113 gl_info->gl_card = CARD_INTEL_I915GM;
1114 } else if (strstr(gl_info->gl_renderer, "915G")) {
1115 gl_info->gl_card = CARD_INTEL_I915G;
1116 } else if (strstr(gl_info->gl_renderer, "865G")) {
1117 gl_info->gl_card = CARD_INTEL_I865G;
1118 } else if (strstr(gl_info->gl_renderer, "855G")) {
1119 gl_info->gl_card = CARD_INTEL_I855G;
1120 } else if (strstr(gl_info->gl_renderer, "830G")) {
1121 gl_info->gl_card = CARD_INTEL_I830G;
1122 } else {
1123 gl_info->gl_card = CARD_INTEL_I915G;
1124 }
1125 break;
1126 case VENDOR_MESA:
1127 case VENDOR_WINE:
1128 default:
1129 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1130 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1131 * them a good generic choice.
1132 */
1133 gl_info->gl_vendor = VENDOR_NVIDIA;
1134 if(WINE_D3D9_CAPABLE(gl_info))
1135 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1136 else if(WINE_D3D8_CAPABLE(gl_info))
1137 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1138 else if(WINE_D3D7_CAPABLE(gl_info))
1139 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1140 else if(WINE_D3D6_CAPABLE(gl_info))
1141 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1142 else
1143 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1144 }
1145 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1146
1147 /* If we have an estimate use it, else default to 64MB; */
1148 if(vidmem)
1149 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1150 else
1151 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1152
1153 /* Load all the lookup tables
1154 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1155 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1156 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1157
1158 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1159 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1160
1161
1162 for (i = 0; i < MAX_LOOKUPS; i++) {
1163 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1164 }
1165
1166 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1167 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1168 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1169 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1170 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1171 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1172 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1173 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1174 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1175 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1176
1177 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1178 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1179 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1180 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1181 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1182
1183
1184 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1185 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1186 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1187 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1188 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1189 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1190 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1191 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1192 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1193 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1194 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1195 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1196 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1197
1198 /* TODO: config lookups */
1199
1200 /* Make sure there's an active HDC else the WGL extensions will fail */
1201 hdc = pwglGetCurrentDC();
1202 if (hdc) {
1203 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1204 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1205
1206 if (NULL == WGL_Extensions) {
1207 ERR(" WGL_Extensions returns NULL\n");
1208 } else {
1209 while (*WGL_Extensions != 0x00) {
1210 const char *Start;
1211 char ThisExtn[256];
1212 size_t len;
1213
1214 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1215 Start = WGL_Extensions;
1216 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1217 WGL_Extensions++;
1218 }
1219
1220 len = WGL_Extensions - Start;
1221 if (len == 0 || len >= sizeof(ThisExtn))
1222 continue;
1223
1224 memcpy(ThisExtn, Start, len);
1225 ThisExtn[len] = '\0';
1226 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1227
1228 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1229 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1230 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1231 }
1232 }
1233 }
1234 }
1235 LEAVE_GL();
1236
1237 return return_value;
1238 }
1239 #undef GLINFO_LOCATION
1240
1241 /**********************************************************
1242 * IWineD3D implementation follows
1243 **********************************************************/
1244
1245 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1246 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1247
1248 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1249 return numAdapters;
1250 }
1251
1252 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1253 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1254 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1255 return WINED3D_OK;
1256 }
1257
1258 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1259 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1260
1261 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1262 return NULL;
1263 }
1264
1265 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1266 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1267 }
1268
1269 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1270 of the same bpp but different resolutions */
1271
1272 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1273 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1274 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1275 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1276
1277 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1278 return 0;
1279 }
1280
1281 /* TODO: Store modes per adapter and read it from the adapter structure */
1282 if (Adapter == 0) { /* Display */
1283 int i = 0;
1284 int j = 0;
1285
1286 if (!DEBUG_SINGLE_MODE) {
1287 DEVMODEW DevModeW;
1288
1289 ZeroMemory(&DevModeW, sizeof(DevModeW));
1290 DevModeW.dmSize = sizeof(DevModeW);
1291 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1292 j++;
1293 switch (Format)
1294 {
1295 case WINED3DFMT_UNKNOWN:
1296 /* This is for D3D8, do not enumerate P8 here */
1297 if (DevModeW.dmBitsPerPel == 32 ||
1298 DevModeW.dmBitsPerPel == 16) i++;
1299 break;
1300 case WINED3DFMT_X8R8G8B8:
1301 if (DevModeW.dmBitsPerPel == 32) i++;
1302 break;
1303 case WINED3DFMT_R5G6B5:
1304 if (DevModeW.dmBitsPerPel == 16) i++;
1305 break;
1306 case WINED3DFMT_P8:
1307 if (DevModeW.dmBitsPerPel == 8) i++;
1308 break;
1309 default:
1310 /* Skip other modes as they do not match the requested format */
1311 break;
1312 }
1313 }
1314 } else {
1315 i = 1;
1316 j = 1;
1317 }
1318
1319 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1320 return i;
1321 } else {
1322 FIXME_(d3d_caps)("Adapter not primary display\n");
1323 }
1324 return 0;
1325 }
1326
1327 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1328 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1329 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1330 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1331
1332 /* Validate the parameters as much as possible */
1333 if (NULL == pMode ||
1334 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1335 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1336 return WINED3DERR_INVALIDCALL;
1337 }
1338
1339 /* TODO: Store modes per adapter and read it from the adapter structure */
1340 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1341 DEVMODEW DevModeW;
1342 int ModeIdx = 0;
1343 int i = 0;
1344 int j = 0;
1345
1346 ZeroMemory(&DevModeW, sizeof(DevModeW));
1347 DevModeW.dmSize = sizeof(DevModeW);
1348
1349 /* If we are filtering to a specific format (D3D9), then need to skip
1350 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1351 just count through the ones with valid bit depths */
1352 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1353 switch (Format)
1354 {
1355 case WINED3DFMT_UNKNOWN:
1356 /* This is D3D8. Do not enumerate P8 here */
1357 if (DevModeW.dmBitsPerPel == 32 ||
1358 DevModeW.dmBitsPerPel == 16) i++;
1359 break;
1360 case WINED3DFMT_X8R8G8B8:
1361 if (DevModeW.dmBitsPerPel == 32) i++;
1362 break;
1363 case WINED3DFMT_R5G6B5:
1364 if (DevModeW.dmBitsPerPel == 16) i++;
1365 break;
1366 case WINED3DFMT_P8:
1367 if (DevModeW.dmBitsPerPel == 8) i++;
1368 break;
1369 default:
1370 /* Modes that don't match what we support can get an early-out */
1371 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1372 return WINED3DERR_INVALIDCALL;
1373 }
1374 }
1375
1376 if (i == 0) {
1377 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1378 return WINED3DERR_INVALIDCALL;
1379 }
1380 ModeIdx = j - 1;
1381
1382 /* Now get the display mode via the calculated index */
1383 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1384 pMode->Width = DevModeW.dmPelsWidth;
1385 pMode->Height = DevModeW.dmPelsHeight;
1386 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1387 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1388 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1389
1390 if (Format == WINED3DFMT_UNKNOWN)
1391 {
1392 switch (DevModeW.dmBitsPerPel)
1393 {
1394 case 8:
1395 pMode->Format = WINED3DFMT_P8;
1396 break;
1397 case 16:
1398 pMode->Format = WINED3DFMT_R5G6B5;
1399 break;
1400 case 32:
1401 pMode->Format = WINED3DFMT_X8R8G8B8;
1402 break;
1403 default:
1404 pMode->Format = WINED3DFMT_UNKNOWN;
1405 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1406 }
1407 } else {
1408 pMode->Format = Format;
1409 }
1410 } else {
1411 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1412 return WINED3DERR_INVALIDCALL;
1413 }
1414
1415 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1416 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1417 DevModeW.dmBitsPerPel);
1418
1419 } else if (DEBUG_SINGLE_MODE) {
1420 /* Return one setting of the format requested */
1421 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1422 pMode->Width = 800;
1423 pMode->Height = 600;
1424 pMode->RefreshRate = 60;
1425 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1426 } else {
1427 FIXME_(d3d_caps)("Adapter not primary display\n");
1428 }
1429
1430 return WINED3D_OK;
1431 }
1432
1433 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1434 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1435 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1436
1437 if (NULL == pMode ||
1438 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1439 return WINED3DERR_INVALIDCALL;
1440 }
1441
1442 if (Adapter == 0) { /* Display */
1443 int bpp = 0;
1444 DEVMODEW DevModeW;
1445
1446 ZeroMemory(&DevModeW, sizeof(DevModeW));
1447 DevModeW.dmSize = sizeof(DevModeW);
1448
1449 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1450 pMode->Width = DevModeW.dmPelsWidth;
1451 pMode->Height = DevModeW.dmPelsHeight;
1452 bpp = DevModeW.dmBitsPerPel;
1453 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1454 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1455 {
1456 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1457 }
1458
1459 switch (bpp) {
1460 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1461 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1462 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1463 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1464 default: pMode->Format = WINED3DFMT_UNKNOWN;
1465 }
1466
1467 } else {
1468 FIXME_(d3d_caps)("Adapter not primary display\n");
1469 }
1470
1471 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1472 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1473 return WINED3D_OK;
1474 }
1475
1476 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1477 and fields being inserted in the middle, a new structure is used in place */
1478 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1479 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1480 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1481
1482 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1483
1484 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1485 return WINED3DERR_INVALIDCALL;
1486 }
1487
1488 /* Return the information requested */
1489 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1490 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1491 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1492
1493 /* Note dx8 doesn't supply a DeviceName */
1494 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1495 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1496 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1497 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1498 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1499 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1500 *(pIdentifier->SubSysId) = 0;
1501 *(pIdentifier->Revision) = 0;
1502
1503 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1504 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1505 *(pIdentifier->WHQLLevel) = 0;
1506 } else {
1507 *(pIdentifier->WHQLLevel) = 1;
1508 }
1509
1510 return WINED3D_OK;
1511 }
1512
1513 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1514 short redSize, greenSize, blueSize, alphaSize, colorBits;
1515
1516 if(!cfg)
1517 return FALSE;
1518
1519 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1520 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1521 return FALSE;
1522 }
1523
1524 if(cfg->redSize < redSize)
1525 return FALSE;
1526
1527 if(cfg->greenSize < greenSize)
1528 return FALSE;
1529
1530 if(cfg->blueSize < blueSize)
1531 return FALSE;
1532
1533 if(cfg->alphaSize < alphaSize)
1534 return FALSE;
1535
1536 return TRUE;
1537 }
1538
1539 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1540 short depthSize, stencilSize;
1541
1542 if(!cfg)
1543 return FALSE;
1544
1545 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1546 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1547 return FALSE;
1548 }
1549
1550 if(cfg->depthSize < depthSize)
1551 return FALSE;
1552
1553 if(cfg->stencilSize < stencilSize)
1554 return FALSE;
1555
1556 return TRUE;
1557 }
1558
1559 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1560 WINED3DFORMAT AdapterFormat,
1561 WINED3DFORMAT RenderTargetFormat,
1562 WINED3DFORMAT DepthStencilFormat) {
1563 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1564 int nCfgs;
1565 WineD3D_PixelFormat *cfgs;
1566 int it;
1567
1568 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1569 This, Adapter,
1570 DeviceType, debug_d3ddevicetype(DeviceType),
1571 AdapterFormat, debug_d3dformat(AdapterFormat),
1572 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1573 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1574
1575 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1576 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1577 return WINED3DERR_INVALIDCALL;
1578 }
1579
1580 cfgs = Adapters[Adapter].cfgs;
1581 nCfgs = Adapters[Adapter].nCfgs;
1582 for (it = 0; it < nCfgs; ++it) {
1583 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1584 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1585 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1586 return WINED3D_OK;
1587 }
1588 }
1589 }
1590 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1591
1592 return WINED3DERR_NOTAVAILABLE;
1593 }
1594
1595 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1596 WINED3DFORMAT SurfaceFormat,
1597 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1598
1599 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1600 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1601 This,
1602 Adapter,
1603 DeviceType, debug_d3ddevicetype(DeviceType),
1604 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1605 Windowed,
1606 MultiSampleType,
1607 pQualityLevels);
1608
1609 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1610 return WINED3DERR_INVALIDCALL;
1611 }
1612
1613 /* TODO: Store in Adapter structure */
1614 if (pQualityLevels != NULL) {
1615 static int s_single_shot = 0;
1616 if (!s_single_shot) {
1617 FIXME("Quality levels unsupported at present\n");
1618 s_single_shot = 1;
1619 }
1620 *pQualityLevels = 1; /* Guess at a value! */
1621 }
1622
1623 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1624 return WINED3DERR_NOTAVAILABLE;
1625 }
1626
1627 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1628 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1629
1630 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1631 int nCfgs = 0;
1632 WineD3D_PixelFormat *cfgs;
1633 int it;
1634 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1635
1636 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1637 This,
1638 Adapter,
1639 CheckType, debug_d3ddevicetype(CheckType),
1640 DisplayFormat, debug_d3dformat(DisplayFormat),
1641 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1642 Windowed);
1643
1644 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1645 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1646 return WINED3DERR_INVALIDCALL;
1647 }
1648
1649 cfgs = Adapters[Adapter].cfgs;
1650 nCfgs = Adapters[Adapter].nCfgs;
1651 for (it = 0; it < nCfgs; ++it) {
1652 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1653 hr = WINED3D_OK;
1654 TRACE_(d3d_caps)("OK\n");
1655 break ;
1656 }
1657 }
1658
1659 if(hr != WINED3D_OK)
1660 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1661
1662 if(hr != WINED3D_OK)
1663 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1664
1665 return hr;
1666 }
1667
1668 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1669 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1670 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1671 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1672 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1673 This,
1674 Adapter,
1675 DeviceType, debug_d3ddevicetype(DeviceType),
1676 AdapterFormat, debug_d3dformat(AdapterFormat),
1677 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1678 RType, debug_d3dresourcetype(RType),
1679 CheckFormat, debug_d3dformat(CheckFormat));
1680
1681 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1682 return WINED3DERR_INVALIDCALL;
1683 }
1684
1685 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1686 switch (CheckFormat) {
1687 /* Filtering not supported */
1688 case WINED3DFMT_R32F:
1689 case WINED3DFMT_A32B32G32R32F:
1690 TRACE_(d3d_caps)("[FAILED]\n");
1691 return WINED3DERR_NOTAVAILABLE;
1692 default:
1693 break;
1694 }
1695 }
1696
1697 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1698 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1699 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1700 return WINED3DERR_NOTAVAILABLE;
1701 }
1702 }
1703
1704 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1705 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1706 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1707 return WINED3DERR_NOTAVAILABLE;
1708 }
1709 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1710 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1711 * app needing one of those formats, don't advertize them to avoid leading apps into
1712 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1713 * except of R32F.
1714 */
1715 switch(CheckFormat) {
1716 case WINED3DFMT_P8:
1717 case WINED3DFMT_A4L4:
1718 case WINED3DFMT_R32F:
1719 case WINED3DFMT_R16F:
1720 case WINED3DFMT_X8L8V8U8:
1721 case WINED3DFMT_L6V5U5:
1722 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1723 return WINED3DERR_NOTAVAILABLE;
1724
1725 case WINED3DFMT_Q8W8V8U8:
1726 case WINED3DFMT_V16U16:
1727 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1728 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1729 return WINED3DERR_NOTAVAILABLE;
1730 }
1731 break;
1732
1733 case WINED3DFMT_V8U8:
1734 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1735 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1736 return WINED3DERR_NOTAVAILABLE;
1737 }
1738 break;
1739
1740 case WINED3DFMT_DXT1:
1741 case WINED3DFMT_DXT2:
1742 case WINED3DFMT_DXT3:
1743 case WINED3DFMT_DXT4:
1744 case WINED3DFMT_DXT5:
1745 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1746 * compressed texture results in an error. While the D3D refrast does
1747 * support s3tc volumes, at least the nvidia windows driver does not, so
1748 * we're free not to support this format.
1749 */
1750 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1751 return WINED3DERR_NOTAVAILABLE;
1752
1753 default:
1754 /* Do nothing, continue with checking the format below */
1755 break;
1756 }
1757 }
1758 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1759 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1760 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1761 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1762 if (!GL_LIMITS(vertex_samplers)) {
1763 TRACE_(d3d_caps)("[FAILED]\n");
1764 return WINED3DERR_NOTAVAILABLE;
1765 }
1766
1767 switch (CheckFormat) {
1768 case WINED3DFMT_A32B32G32R32F:
1769 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1770 TRACE_(d3d_caps)("[FAILED]\n");
1771 return WINED3DERR_NOTAVAILABLE;
1772 }
1773 TRACE_(d3d_caps)("[OK]\n");
1774 return WINED3D_OK;
1775
1776 default:
1777 TRACE_(d3d_caps)("[FAILED]\n");
1778 return WINED3DERR_NOTAVAILABLE;
1779 }
1780 }
1781
1782 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1783 switch (CheckFormat) {
1784 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1785 * Windows supports only those 3, and enumerating the other formats confuses applications
1786 */
1787 case WINED3DFMT_D24S8:
1788 case WINED3DFMT_D24X8:
1789 case WINED3DFMT_D16:
1790 TRACE_(d3d_caps)("[OK]\n");
1791 return WINED3D_OK;
1792 case WINED3DFMT_D16_LOCKABLE:
1793 case WINED3DFMT_D24FS8:
1794 case WINED3DFMT_D32F_LOCKABLE:
1795 case WINED3DFMT_D24X4S4:
1796 case WINED3DFMT_D15S1:
1797 case WINED3DFMT_D32:
1798 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1799 return WINED3DERR_NOTAVAILABLE;
1800 default:
1801 TRACE_(d3d_caps)("[FAILED]\n");
1802 return WINED3DERR_NOTAVAILABLE;
1803 }
1804 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1805 switch (CheckFormat) {
1806 case WINED3DFMT_R8G8B8:
1807 case WINED3DFMT_A8R8G8B8:
1808 case WINED3DFMT_X8R8G8B8:
1809 case WINED3DFMT_R5G6B5:
1810 case WINED3DFMT_X1R5G5B5:
1811 case WINED3DFMT_A1R5G5B5:
1812 case WINED3DFMT_A4R4G4B4:
1813 case WINED3DFMT_R3G3B2:
1814 case WINED3DFMT_X4R4G4B4:
1815 case WINED3DFMT_A8B8G8R8:
1816 case WINED3DFMT_X8B8G8R8:
1817 case WINED3DFMT_P8:
1818 TRACE_(d3d_caps)("[OK]\n");
1819 return WINED3D_OK;
1820 case WINED3DFMT_R16F:
1821 case WINED3DFMT_A16B16G16R16F:
1822 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1823 TRACE_(d3d_caps)("[FAILED]\n");
1824 return WINED3DERR_NOTAVAILABLE;
1825 }
1826 TRACE_(d3d_caps)("[OK]\n");
1827 return WINED3D_OK;
1828 case WINED3DFMT_A32B32G32R32F:
1829 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1830 TRACE_(d3d_caps)("[FAILED]\n");
1831 return WINED3DERR_NOTAVAILABLE;
1832 }
1833 TRACE_(d3d_caps)("[OK]\n");
1834 return WINED3D_OK;
1835 default:
1836 TRACE_(d3d_caps)("[FAILED]\n");
1837 return WINED3DERR_NOTAVAILABLE;
1838 }
1839 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1840 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1841 switch (CheckFormat) {
1842 case WINED3DFMT_V8U8:
1843 TRACE_(d3d_caps)("[OK]\n");
1844 return WINED3D_OK;
1845 /* TODO: Other bump map formats */
1846 default:
1847 TRACE_(d3d_caps)("[FAILED]\n");
1848 return WINED3DERR_NOTAVAILABLE;
1849 }
1850 }
1851 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1852 switch (CheckFormat) {
1853 case WINED3DFMT_V8U8:
1854 TRACE_(d3d_caps)("[OK]\n");
1855 return WINED3D_OK;
1856 default:
1857 TRACE_(d3d_caps)("[FAILED]\n");
1858 return WINED3DERR_NOTAVAILABLE;
1859 }
1860 }
1861 TRACE_(d3d_caps)("[FAILED]\n");
1862 return WINED3DERR_NOTAVAILABLE;
1863 }
1864
1865 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1866 switch (CheckFormat) {
1867 case WINED3DFMT_DXT1:
1868 case WINED3DFMT_DXT2:
1869 case WINED3DFMT_DXT3:
1870 case WINED3DFMT_DXT4:
1871 case WINED3DFMT_DXT5:
1872 TRACE_(d3d_caps)("[OK]\n");
1873 return WINED3D_OK;
1874 default:
1875 break; /* Avoid compiler warnings */
1876 }
1877 }
1878
1879 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1880 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1881 switch (CheckFormat) {
1882 case WINED3DFMT_A8R8G8B8:
1883 case WINED3DFMT_X8R8G8B8:
1884 case WINED3DFMT_A4R4G4B4:
1885 case WINED3DFMT_L8:
1886 case WINED3DFMT_A8L8:
1887 case WINED3DFMT_DXT1:
1888 case WINED3DFMT_DXT2:
1889 case WINED3DFMT_DXT3:
1890 case WINED3DFMT_DXT4:
1891 case WINED3DFMT_DXT5:
1892 TRACE_(d3d_caps)("[OK]\n");
1893 return WINED3D_OK;
1894
1895 default:
1896 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1897 return WINED3DERR_NOTAVAILABLE;
1898 }
1899 }
1900
1901 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1902
1903 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1904
1905 switch (CheckFormat) {
1906 case WINED3DFMT_R16F:
1907 case WINED3DFMT_A16B16G16R16F:
1908 if (!half_pixel_support) break;
1909 case WINED3DFMT_R32F:
1910 case WINED3DFMT_A32B32G32R32F:
1911 TRACE_(d3d_caps)("[OK]\n");
1912 return WINED3D_OK;
1913 default:
1914 break; /* Avoid compiler warnings */
1915 }
1916 }
1917
1918 /* This format is nothing special and it is supported perfectly.
1919 * However, ati and nvidia driver on windows do not mark this format as
1920 * supported (tested with the dxCapsViewer) and pretending to
1921 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1922 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1923 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1924 */
1925 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1926 TRACE_(d3d_caps)("[FAILED]\n");
1927 return WINED3DERR_NOTAVAILABLE;
1928 }
1929
1930 switch (CheckFormat) {
1931
1932 /*****
1933 * supported: RGB(A) formats
1934 */
1935 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1936 case WINED3DFMT_A8R8G8B8:
1937 case WINED3DFMT_X8R8G8B8:
1938 case WINED3DFMT_R5G6B5:
1939 case WINED3DFMT_X1R5G5B5:
1940 case WINED3DFMT_A1R5G5B5:
1941 case WINED3DFMT_A4R4G4B4:
1942 case WINED3DFMT_R3G3B2:
1943 case WINED3DFMT_A8:
1944 case WINED3DFMT_X4R4G4B4:
1945 case WINED3DFMT_A8B8G8R8:
1946 case WINED3DFMT_X8B8G8R8:
1947 case WINED3DFMT_A2R10G10B10:
1948 case WINED3DFMT_A2B10G10R10:
1949 TRACE_(d3d_caps)("[OK]\n");
1950 return WINED3D_OK;
1951
1952 /*****
1953 * supported: Palettized
1954 */
1955 case WINED3DFMT_P8:
1956 TRACE_(d3d_caps)("[OK]\n");
1957 return WINED3D_OK;
1958
1959 /*****
1960 * Supported: (Alpha)-Luminance
1961 */
1962 case WINED3DFMT_L8:
1963 case WINED3DFMT_A8L8:
1964 case WINED3DFMT_A4L4:
1965 TRACE_(d3d_caps)("[OK]\n");
1966 return WINED3D_OK;
1967
1968 /*****
1969 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1970 * GL_NV_texture_shader), but advertized to make apps happy.
1971 * Enable some because games often fail when they are not available
1972 * and are still playable even without bump mapping
1973 */
1974 case WINED3DFMT_V8U8:
1975 case WINED3DFMT_V16U16:
1976 case WINED3DFMT_L6V5U5:
1977 case WINED3DFMT_X8L8V8U8:
1978 case WINED3DFMT_Q8W8V8U8:
1979 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1980 return WINED3D_OK;
1981
1982 /* Those are not advertized by the nvidia windows driver, and not
1983 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1984 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1985 * ARGB format if needed
1986 */
1987 case WINED3DFMT_W11V11U10:
1988 case WINED3DFMT_A2W10V10U10:
1989 WARN_(d3d_caps)("[FAILED]\n");
1990 return WINED3DERR_NOTAVAILABLE;
1991
1992 /*****
1993 * DXTN Formats: Handled above
1994 * WINED3DFMT_DXT1
1995 * WINED3DFMT_DXT2
1996 * WINED3DFMT_DXT3
1997 * WINED3DFMT_DXT4
1998 * WINED3DFMT_DXT5
1999 */
2000
2001 /*****
2002 * Odd formats - not supported
2003 */
2004 case WINED3DFMT_VERTEXDATA:
2005 case WINED3DFMT_INDEX16:
2006 case WINED3DFMT_INDEX32:
2007 case WINED3DFMT_Q16W16V16U16:
2008 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2009 return WINED3DERR_NOTAVAILABLE;
2010
2011 /*****
2012 * Float formats: Not supported right now
2013 */
2014 case WINED3DFMT_G16R16F:
2015 case WINED3DFMT_G32R32F:
2016 case WINED3DFMT_CxV8U8:
2017 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2018 return WINED3DERR_NOTAVAILABLE;
2019
2020 /* Not supported */
2021 case WINED3DFMT_G16R16:
2022 case WINED3DFMT_A16B16G16R16:
2023 case WINED3DFMT_A8R3G3B2:
2024 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2025 return WINED3DERR_NOTAVAILABLE;
2026
2027 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2028 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2029 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2030 * We can do instancing with all shader versions, but we need vertex shaders.
2031 *
2032 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2033 * to enable instancing. WineD3D doesn't need that and just ignores it.
2034 *
2035 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2036 */
2037 case WINEMAKEFOURCC('I','N','S','T'):
2038 TRACE("ATI Instancing check hack\n");
2039 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2040 TRACE_(d3d_caps)("[OK]\n");
2041 return WINED3D_OK;
2042 } else {
2043 TRACE_(d3d_caps)("[FAILED]\n");
2044 return WINED3DERR_NOTAVAILABLE;
2045 }
2046
2047 default:
2048 break;
2049 }
2050
2051 TRACE_(d3d_caps)("[FAILED]\n");
2052 return WINED3DERR_NOTAVAILABLE;
2053 }
2054
2055 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2056 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2057 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2058
2059 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2060 This,
2061 Adapter,
2062 DeviceType, debug_d3ddevicetype(DeviceType),
2063 SourceFormat, debug_d3dformat(SourceFormat),
2064 TargetFormat, debug_d3dformat(TargetFormat));
2065 return WINED3D_OK;
2066 }
2067
2068 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2069 subset of a D3DCAPS9 structure. However, it has to come via a void *
2070 as the d3d8 interface cannot import the d3d9 header */
2071 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2072
2073 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2074 int vs_selected_mode;
2075 int ps_selected_mode;
2076
2077 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2078
2079 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2080 return WINED3DERR_INVALIDCALL;
2081 }
2082
2083 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2084
2085 /* This function should *not* be modifying GL caps
2086 * TODO: move the functionality where it belongs */
2087 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2088
2089 /* ------------------------------------------------
2090 The following fields apply to both d3d8 and d3d9
2091 ------------------------------------------------ */
2092 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2093 *pCaps->AdapterOrdinal = Adapter;
2094
2095 *pCaps->Caps = 0;
2096 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2097 WINED3DCAPS2_FULLSCREENGAMMA |
2098 WINED3DCAPS2_DYNAMICTEXTURES;
2099 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2100 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2101 }
2102 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2103 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2104 WINED3DPRESENT_INTERVAL_ONE;
2105
2106 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2107 WINED3DCURSORCAPS_LOWRES;
2108
2109 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2110 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2111 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2112 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2113 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2114 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2115 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2116 WINED3DDEVCAPS_PUREDEVICE |
2117 WINED3DDEVCAPS_HWRASTERIZATION |
2118 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2119 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2120 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2121 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2122 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2123 WINED3DDEVCAPS_RTPATCHES;
2124
2125 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2126 WINED3DPMISCCAPS_CULLCCW |
2127 WINED3DPMISCCAPS_CULLCW |
2128 WINED3DPMISCCAPS_COLORWRITEENABLE |
2129 WINED3DPMISCCAPS_CLIPTLVERTS |
2130 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2131 WINED3DPMISCCAPS_MASKZ |
2132 WINED3DPMISCCAPS_BLENDOP;
2133 /* TODO:
2134 WINED3DPMISCCAPS_NULLREFERENCE
2135 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2136 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2137 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2138 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2139 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2140 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2141
2142 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2143 #if 0
2144 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2145 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2146 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2147 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2148 #endif
2149
2150 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2151 WINED3DPRASTERCAPS_PAT |
2152 WINED3DPRASTERCAPS_WFOG |
2153 WINED3DPRASTERCAPS_ZFOG |
2154 WINED3DPRASTERCAPS_FOGVERTEX |
2155 WINED3DPRASTERCAPS_FOGTABLE |
2156 WINED3DPRASTERCAPS_STIPPLE |
2157 WINED3DPRASTERCAPS_SUBPIXEL |
2158 WINED3DPRASTERCAPS_ZTEST |
2159 WINED3DPRASTERCAPS_SCISSORTEST |
2160 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2161 WINED3DPRASTERCAPS_DEPTHBIAS;
2162
2163 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2164 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2165 WINED3DPRASTERCAPS_ZBIAS |
2166 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2167 }
2168 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2169 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2170 }
2171 /* FIXME Add:
2172 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2173 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2174 WINED3DPRASTERCAPS_ANTIALIASEDGES
2175 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2176 WINED3DPRASTERCAPS_WBUFFER */
2177
2178 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2179 WINED3DPCMPCAPS_EQUAL |
2180 WINED3DPCMPCAPS_GREATER |
2181 WINED3DPCMPCAPS_GREATEREQUAL |
2182 WINED3DPCMPCAPS_LESS |
2183 WINED3DPCMPCAPS_LESSEQUAL |
2184 WINED3DPCMPCAPS_NEVER |
2185 WINED3DPCMPCAPS_NOTEQUAL;
2186
2187 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2188 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2189 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2190 WINED3DPBLENDCAPS_DESTALPHA |
2191 WINED3DPBLENDCAPS_DESTCOLOR |
2192 WINED3DPBLENDCAPS_INVDESTALPHA |
2193 WINED3DPBLENDCAPS_INVDESTCOLOR |
2194 WINED3DPBLENDCAPS_INVSRCALPHA |
2195 WINED3DPBLENDCAPS_INVSRCCOLOR |
2196 WINED3DPBLENDCAPS_ONE |
2197 WINED3DPBLENDCAPS_SRCALPHA |
2198 WINED3DPBLENDCAPS_SRCALPHASAT |
2199 WINED3DPBLENDCAPS_SRCCOLOR |
2200 WINED3DPBLENDCAPS_ZERO;
2201
2202 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2203 WINED3DPBLENDCAPS_DESTALPHA |
2204 WINED3DPBLENDCAPS_DESTCOLOR |
2205 WINED3DPBLENDCAPS_INVDESTALPHA |
2206 WINED3DPBLENDCAPS_INVDESTCOLOR |
2207 WINED3DPBLENDCAPS_INVSRCALPHA |
2208 WINED3DPBLENDCAPS_INVSRCCOLOR |
2209 WINED3DPBLENDCAPS_ONE |
2210 WINED3DPBLENDCAPS_SRCALPHA |
2211 WINED3DPBLENDCAPS_SRCCOLOR |
2212 WINED3DPBLENDCAPS_ZERO;
2213 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2214 * according to the glBlendFunc manpage
2215 *
2216 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2217 * legacy settings for srcblend only
2218 */
2219
2220 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2221 WINED3DPCMPCAPS_EQUAL |
2222 WINED3DPCMPCAPS_GREATER |
2223 WINED3DPCMPCAPS_GREATEREQUAL |
2224 WINED3DPCMPCAPS_LESS |
2225 WINED3DPCMPCAPS_LESSEQUAL |
2226 WINED3DPCMPCAPS_NEVER |
2227 WINED3DPCMPCAPS_NOTEQUAL;
2228
2229 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2230 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2231 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2232 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2233 WINED3DPSHADECAPS_COLORFLATRGB |
2234 WINED3DPSHADECAPS_FOGFLAT |
2235 WINED3DPSHADECAPS_FOGGOURAUD |
2236 WINED3DPSHADECAPS_SPECULARFLATRGB;
2237
2238 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2239 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2240 WINED3DPTEXTURECAPS_BORDER |
2241 WINED3DPTEXTURECAPS_MIPMAP |
2242 WINED3DPTEXTURECAPS_PROJECTED |
2243 WINED3DPTEXTURECAPS_PERSPECTIVE;
2244
2245 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2246 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2247 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2248 }
2249
2250 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2251 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2252 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2253 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2254 }
2255
2256 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2257 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2258 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2259 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2260
2261 }
2262
2263 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2264 WINED3DPTFILTERCAPS_MAGFPOINT |
2265 WINED3DPTFILTERCAPS_MINFLINEAR |
2266 WINED3DPTFILTERCAPS_MINFPOINT |
2267 WINED3DPTFILTERCAPS_MIPFLINEAR |
2268 WINED3DPTFILTERCAPS_MIPFPOINT |
2269 WINED3DPTFILTERCAPS_LINEAR |
2270 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2271 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2272 WINED3DPTFILTERCAPS_MIPLINEAR |
2273 WINED3DPTFILTERCAPS_MIPNEAREST |
2274 WINED3DPTFILTERCAPS_NEAREST;
2275
2276 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2277 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2278 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2279 }
2280
2281 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2282 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2283 WINED3DPTFILTERCAPS_MAGFPOINT |
2284 WINED3DPTFILTERCAPS_MINFLINEAR |
2285 WINED3DPTFILTERCAPS_MINFPOINT |
2286 WINED3DPTFILTERCAPS_MIPFLINEAR |
2287 WINED3DPTFILTERCAPS_MIPFPOINT |
2288 WINED3DPTFILTERCAPS_LINEAR |
2289 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2290 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2291 WINED3DPTFILTERCAPS_MIPLINEAR |
2292 WINED3DPTFILTERCAPS_MIPNEAREST |
2293 WINED3DPTFILTERCAPS_NEAREST;
2294
2295 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2296 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2297 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2298 }
2299 } else
2300 *pCaps->CubeTextureFilterCaps = 0;
2301
2302 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2303 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2304 WINED3DPTFILTERCAPS_MAGFPOINT |
2305 WINED3DPTFILTERCAPS_MINFLINEAR |
2306 WINED3DPTFILTERCAPS_MINFPOINT |
2307 WINED3DPTFILTERCAPS_MIPFLINEAR |
2308 WINED3DPTFILTERCAPS_MIPFPOINT |
2309 WINED3DPTFILTERCAPS_LINEAR |
2310 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2311 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2312 WINED3DPTFILTERCAPS_MIPLINEAR |
2313 WINED3DPTFILTERCAPS_MIPNEAREST |
2314 WINED3DPTFILTERCAPS_NEAREST;
2315 } else
2316 *pCaps->VolumeTextureFilterCaps = 0;
2317
2318 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2319 WINED3DPTADDRESSCAPS_CLAMP |
2320 WINED3DPTADDRESSCAPS_WRAP;
2321
2322 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2323 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2324 }
2325 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2326 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2327 }
2328 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2329 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2330 }
2331
2332 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2333 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2334 WINED3DPTADDRESSCAPS_CLAMP |
2335 WINED3DPTADDRESSCAPS_WRAP;
2336 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2337 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2338 }
2339 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2340 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2341 }
2342 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2343 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2344 }
2345 } else
2346 *pCaps->VolumeTextureAddressCaps = 0;
2347
2348 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2349 WINED3DLINECAPS_ZTEST;
2350 /* FIXME: Add
2351 WINED3DLINECAPS_BLEND
2352 WINED3DLINECAPS_ALPHACMP
2353 WINED3DLINECAPS_FOG */
2354
2355 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2356 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2357
2358 if(GL_SUPPORT(EXT_TEXTURE3D))
2359 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2360 else
2361 *pCaps->MaxVolumeExtent = 0;
2362
2363 *pCaps->MaxTextureRepeat = 32768;
2364 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2365 *pCaps->MaxVertexW = 1.0;
2366
2367 *pCaps->GuardBandLeft = 0;
2368 *pCaps->GuardBandTop = 0;
2369 *pCaps->GuardBandRight = 0;
2370 *pCaps->GuardBandBottom = 0;
2371
2372 *pCaps->ExtentsAdjust = 0;
2373
2374 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2375 WINED3DSTENCILCAPS_INCRSAT |
2376 WINED3DSTENCILCAPS_INVERT |
2377 WINED3DSTENCILCAPS_KEEP |
2378 WINED3DSTENCILCAPS_REPLACE |
2379 WINED3DSTENCILCAPS_ZERO;
2380 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2381 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2382 WINED3DSTENCILCAPS_INCR;
2383 }
2384 if ( This->dxVersion > 8 &&
2385 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2386 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2387 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2388 }
2389
2390 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2391
2392 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2393 WINED3DTEXOPCAPS_ADDSIGNED |
2394 WINED3DTEXOPCAPS_ADDSIGNED2X |
2395 WINED3DTEXOPCAPS_MODULATE |
2396 WINED3DTEXOPCAPS_MODULATE2X |
2397 WINED3DTEXOPCAPS_MODULATE4X |
2398 WINED3DTEXOPCAPS_SELECTARG1 |
2399 WINED3DTEXOPCAPS_SELECTARG2 |
2400 WINED3DTEXOPCAPS_DISABLE;
2401
2402 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2403 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2404 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2405 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2406 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2407 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2408 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2409 WINED3DTEXOPCAPS_LERP |
2410 WINED3DTEXOPCAPS_SUBTRACT;
2411 }
2412 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2413 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2414 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2415 WINED3DTEXOPCAPS_MULTIPLYADD |
2416 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2417 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2418 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2419 }
2420 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2421 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2422
2423 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2424 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2425 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2426 }
2427
2428 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2429 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2430 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2431 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2432 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2433 * and 3D textures. It also allows us to keep the code simpler by having texture
2434 * shaders constantly enabled.
2435 */
2436 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2437 /* TODO: Luminance bump map? */
2438 }
2439 #if 0
2440 /* FIXME: Add
2441 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2442 WINED3DTEXOPCAPS_PREMODULATE */
2443 #endif
2444
2445 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2446 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2447 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2448 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2449
2450 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2451 *pCaps->MaxVertexBlendMatrixIndex = 0;
2452
2453 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2454 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2455
2456
2457 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2458 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2459 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2460 WINED3DVTXPCAPS_LOCALVIEWER |
2461 WINED3DVTXPCAPS_VERTEXFOG |
2462 WINED3DVTXPCAPS_TEXGEN;
2463 /* FIXME: Add
2464 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2465
2466 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2467 *pCaps->MaxVertexIndex = 0xFFFFF;
2468 *pCaps->MaxStreams = MAX_STREAMS;
2469 *pCaps->MaxStreamStride = 1024;
2470
2471 if (vs_selected_mode == SHADER_GLSL) {
2472 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2473 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2474 * vs_nv_version which is based on NV_vertex_program.
2475 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2476 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2477 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2478 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2479 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2480 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2481 else
2482 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2483 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2484 } else if (vs_selected_mode == SHADER_ARB) {
2485 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2486 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2487 } else {
2488 *pCaps->VertexShaderVersion = 0;
2489 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2490 }
2491
2492 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2493
2494 if (ps_selected_mode == SHADER_GLSL) {
2495 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2496 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2497 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2498 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2499 * in max native instructions. Intel and others also offer the info in this extension but they
2500 * don't support GLSL (at least on Windows).
2501 *
2502 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number
2503 * of instructions is 512 or less we have to do with ps2.0 hardware.
2504 * NOTE: ps3.0 hardware requires 512 or more instructions but ati and nvidia offer 'enough' (1024 vs 4096) on their most basic ps3.0 hardware.
2505 */
2506 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2507 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2508 else
2509 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2510 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2511 * Direct3D minimum requirement.
2512 *
2513 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2514 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2515 *
2516 * The problem is that the refrast clamps temporary results in the shader to
2517 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2518 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2519 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2520 * offer a way to query this.
2521 */
2522 *pCaps->PixelShader1xMaxValue = 8.0;
2523 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2524 } else if (ps_selected_mode == SHADER_ARB) {
2525 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2526 *pCaps->PixelShader1xMaxValue = 8.0;
2527 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2528 } else {
2529 *pCaps->PixelShaderVersion = 0;
2530 *pCaps->PixelShader1xMaxValue = 0.0;
2531 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2532 }
2533
2534 /* ------------------------------------------------
2535 The following fields apply to d3d9 only
2536 ------------------------------------------------ */
2537 if (This->dxVersion > 8) {
2538 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2539 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2540 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2541 *pCaps->MaxNpatchTessellationLevel = 0;
2542 *pCaps->MasterAdapterOrdinal = 0;
2543 *pCaps->AdapterOrdinalInGroup = 0;
2544 *pCaps->NumberOfAdaptersInGroup = 1;
2545
2546 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2547 /* OpenGL supports all the formats below, perhaps not always
2548 * without conversion, but it supports them.
2549 * Further GLSL doesn't seem to have an official unsigned type so
2550 * don't advertise it yet as I'm not sure how we handle it.
2551 * We might need to add some clamping in the shader engine to
2552 * support it.
2553 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2554 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2555 WINED3DDTCAPS_UBYTE4N |
2556 WINED3DDTCAPS_SHORT2N |
2557 WINED3DDTCAPS_SHORT4N;
2558 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2559 *pCaps->DeclTypes |=
2560 WINED3DDTCAPS_FLOAT16_2 |
2561 WINED3DDTCAPS_FLOAT16_4;
2562 }
2563 } else
2564 *pCaps->DeclTypes = 0;
2565
2566 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2567
2568
2569 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2570 WINED3DPTFILTERCAPS_MAGFPOINT |
2571 WINED3DPTFILTERCAPS_MINFLINEAR |
2572 WINED3DPTFILTERCAPS_MAGFLINEAR;
2573 *pCaps->VertexTextureFilterCaps = 0;
2574
2575 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2576 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2577 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2578 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2579 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2580 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2581 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2582
2583 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2584 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2585 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2586 *pCaps->VS20Caps.Caps = 0;
2587 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2588 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2589 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2590
2591 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2592 *pCaps->MaxVertexShader30InstructionSlots = 0;
2593 } else { /* VS 1.x */
2594 *pCaps->VS20Caps.Caps = 0;
2595 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2596 *pCaps->VS20Caps.NumTemps = 0;
2597 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2598
2599 *pCaps->MaxVShaderInstructionsExecuted = 0;
2600 *pCaps->MaxVertexShader30InstructionSlots = 0;
2601 }
2602
2603 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2604 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2605 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2606
2607 /* 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 */
2608 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2609 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2610 WINED3DPS20CAPS_PREDICATION |
2611 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2612 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2613 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2614 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2615 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2616 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2617
2618 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2619 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2620 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2621 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2622 *pCaps->PS20Caps.Caps = 0;
2623 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2624 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2625 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2626 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2627
2628 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2629 *pCaps->MaxPixelShader30InstructionSlots = 0;
2630 } else { /* PS 1.x */
2631 *pCaps->PS20Caps.Caps = 0;
2632 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2633 *pCaps->PS20Caps.NumTemps = 0;
2634 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2635 *pCaps->PS20Caps.NumInstructionSlots = 0;
2636
2637 *pCaps->MaxPShaderInstructionsExecuted = 0;
2638 *pCaps->MaxPixelShader30InstructionSlots = 0;
2639 }
2640 }
2641
2642 return WINED3D_OK;
2643 }
2644
2645 static unsigned int glsl_program_key_hash(void *key) {
2646 glsl_program_key_t *k = (glsl_program_key_t *)key;
2647
2648 unsigned int hash = k->vshader | k->pshader << 16;
2649 hash += ~(hash << 15);
2650 hash ^= (hash >> 10);
2651 hash += (hash << 3);
2652 hash ^= (hash >> 6);
2653 hash += ~(hash << 11);
2654 hash ^= (hash >> 16);
2655
2656 return hash;
2657 }
2658
2659 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2660 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2661 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2662
2663 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2664 }
2665
2666 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2667 and fields being inserted in the middle, a new structure is used in place */
2668 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2669 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2670 IUnknown *parent) {
2671
2672 IWineD3DDeviceImpl *object = NULL;
2673 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2674 HDC hDC;
2675 int i;
2676
2677 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2678 * number and create a device without a 3D adapter for 2D only operation.
2679 */
2680 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2681 return WINED3DERR_INVALIDCALL;
2682 }
2683
2684 /* Create a WineD3DDevice object */
2685 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2686 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2687 TRACE("Created WineD3DDevice object @ %p\n", object);
2688 if (NULL == object) {
2689 return WINED3DERR_OUTOFVIDEOMEMORY;
2690 }
2691
2692 /* Set up initial COM information */
2693 object->lpVtbl = &IWineD3DDevice_Vtbl;
2694 object->ref = 1;
2695 object->wineD3D = iface;
2696 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2697 IWineD3D_AddRef(object->wineD3D);
2698 object->parent = parent;
2699 list_init(&object->resources);
2700
2701 if(This->dxVersion == 7) {
2702 object->surface_alignment = 8;
2703 } else {
2704 object->surface_alignment = 4;
2705 }
2706 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2707
2708 /* Set the state up as invalid until the device is fully created */
2709 object->state = WINED3DERR_DRIVERINTERNALERROR;
2710
2711 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2712 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2713
2714 /* Save the creation parameters */
2715 object->createParms.AdapterOrdinal = Adapter;
2716 object->createParms.DeviceType = DeviceType;
2717 object->createParms.hFocusWindow = hFocusWindow;
2718 object->createParms.BehaviorFlags = BehaviourFlags;
2719
2720 /* Initialize other useful values */
2721 object->adapterNo = Adapter;
2722 object->devType = DeviceType;
2723
2724 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2725 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2726 object->shader_backend = &glsl_shader_backend;
2727 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2728 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2729 object->shader_backend = &arb_program_shader_backend;
2730 } else {
2731 object->shader_backend = &none_shader_backend;
2732 }
2733
2734 /* set the state of the device to valid */
2735 object->state = WINED3D_OK;
2736
2737 /* Get the initial screen setup for ddraw */
2738 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2739 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2740 hDC = GetDC(0);
2741 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2742 ReleaseDC(0, hDC);
2743
2744 for(i = 0; i < PATCHMAP_SIZE; i++) {
2745 list_init(&object->patches[i]);
2746 }
2747 return WINED3D_OK;
2748 }
2749 #undef GLINFO_LOCATION
2750
2751 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2752 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2753 IUnknown_AddRef(This->parent);
2754 *pParent = This->parent;
2755 return WINED3D_OK;
2756 }
2757
2758 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2759 IUnknown* surfaceParent;
2760 TRACE("(%p) call back\n", pSurface);
2761
2762 /* Now, release the parent, which will take care of cleaning up the surface for us */
2763 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2764 IUnknown_Release(surfaceParent);
2765 return IUnknown_Release(surfaceParent);
2766 }
2767
2768 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2769 IUnknown* volumeParent;
2770 TRACE("(%p) call back\n", pVolume);
2771
2772 /* Now, release the parent, which will take care of cleaning up the volume for us */
2773 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2774 IUnknown_Release(volumeParent);
2775 return IUnknown_Release(volumeParent);
2776 }
2777
2778 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2779 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2780 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2781 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2782 *
2783 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2784 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2785 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2786 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2787 * is specific to the MacOS window management, and GL_APPLE_ycbcr_422 is a Quicktime specific, so
2788 * it the chance that other implementations support it is rather rare since Win32 Quicktime uses
2789 * DirectDraw, not OpenGL.
2790 */
2791 if(gl_info->supported[APPLE_FENCE] &&
2792 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2793 gl_info->supported[APPLE_FLUSH_RENDER] &&
2794 gl_info->supported[APPLE_YCBCR_422]) {
2795 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2796 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2797 return TRUE;
2798 } else {
2799 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2800 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2801 return FALSE;
2802 }
2803 }
2804
2805 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2806 if(implementation_is_apple(gl_info)) {
2807 /* MacOS advertises more GLSL vertex shader uniforms than support on hardware, and if more are
2808 * used it falls back to software. While the compiler can detect if the shader uses all declared
2809 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2810 * using relative addressing falls back to software.
2811 *
2812 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2813 */
2814 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2815 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2816 } else {
2817 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2818 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
2819 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
2820 }
2821
2822 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2823 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2824 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2825 * flag for this extension
2826 */
2827 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
2828 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
2829 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
2830 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
2831 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2832 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
2833 }
2834 }
2835 }
2836 }
2837
2838 #define PUSH1(att) attribs[nAttribs++] = (att);
2839 #define GLINFO_LOCATION (Adapters[0].gl_info)
2840 BOOL InitAdapters(void) {
2841 static HMODULE mod_gl;
2842 BOOL ret;
2843 int ps_selected_mode, vs_selected_mode;
2844
2845 /* No need to hold any lock. The calling library makes sure only one thread calls
2846 * wined3d simultaneously
2847 */
2848 if(numAdapters > 0) return TRUE;
2849
2850 TRACE("Initializing adapters\n");
2851
2852 if(!mod_gl) {
2853 #ifdef USE_WIN32_OPENGL
2854 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2855 mod_gl = LoadLibraryA("opengl32.dll");
2856 if(!mod_gl) {
2857 ERR("Can't load opengl32.dll!\n");
2858 return FALSE;
2859 }
2860 #else
2861 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2862 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2863 mod_gl = GetModuleHandleA("opengl32.dll");
2864 #endif
2865 }
2866
2867 /* Load WGL core functions from opengl32.dll */
2868 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2869 WGL_FUNCS_GEN;
2870 #undef USE_WGL_FUNC
2871
2872 if(!pwglGetProcAddress) {
2873 ERR("Unable to load wglGetProcAddress!\n");
2874 return FALSE;
2875 }
2876
2877 /* Dynamically load all GL core functions */
2878 GL_FUNCS_GEN;
2879 #undef USE_GL_FUNC
2880
2881 /* For now only one default adapter */
2882 {
2883 int iPixelFormat;
2884 int attribs[8];
2885 int values[8];
2886 int nAttribs = 0;
2887 int res;
2888 WineD3D_PixelFormat *cfgs;
2889 int attribute;
2890 DISPLAY_DEVICEW DisplayDevice;
2891 HDC hdc;
2892
2893 TRACE("Initializing default adapter\n");
2894 Adapters[0].monitorPoint.x = -1;
2895 Adapters[0].monitorPoint.y = -1;
2896
2897 if (!WineD3D_CreateFakeGLContext()) {
2898 ERR("Failed to get a gl context for default adapter\n");
2899 HeapFree(GetProcessHeap(), 0, Adapters);
2900 WineD3D_ReleaseFakeGLContext();
2901 return FALSE;
2902 }
2903
2904 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2905 if(!ret) {
2906 ERR("Failed to initialize gl caps for default adapter\n");
2907 HeapFree(GetProcessHeap(), 0, Adapters);
2908 WineD3D_ReleaseFakeGLContext();
2909 return FALSE;
2910 }
2911 ret = initPixelFormats(&Adapters[0].gl_info);
2912 if(!ret) {
2913 ERR("Failed to init gl formats\n");
2914 HeapFree(GetProcessHeap(), 0, Adapters);
2915 WineD3D_ReleaseFakeGLContext();
2916 return FALSE;
2917 }
2918
2919 hdc = pwglGetCurrentDC();
2920 if(!hdc) {
2921 ERR("Failed to get gl HDC\n");
2922 HeapFree(GetProcessHeap(), 0, Adapters);
2923 WineD3D_ReleaseFakeGLContext();
2924 return FALSE;
2925 }
2926
2927 Adapters[0].driver = "Display";
2928 Adapters[0].description = "Direct3D HAL";
2929
2930 /* Use the VideoRamSize registry setting when set */
2931 if(wined3d_settings.emulated_textureram)
2932 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
2933 else
2934 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
2935 Adapters[0].UsedTextureRam = 0;
2936 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
2937
2938 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2939 DisplayDevice.cb = sizeof(DisplayDevice);
2940 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2941 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2942 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2943
2944 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2945 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2946
2947 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2948 cfgs = Adapters[0].cfgs;
2949 PUSH1(WGL_RED_BITS_ARB)
2950 PUSH1(WGL_GREEN_BITS_ARB)
2951 PUSH1(WGL_BLUE_BITS_ARB)
2952 PUSH1(WGL_ALPHA_BITS_ARB)
2953 PUSH1(WGL_DEPTH_BITS_ARB)
2954 PUSH1(WGL_STENCIL_BITS_ARB)
2955
2956 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2957 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
2958
2959 if(!res)
2960 continue;
2961
2962 /* Cache the pixel format */
2963 cfgs->iPixelFormat = iPixelFormat;
2964 cfgs->redSize = values[0];
2965 cfgs->greenSize = values[1];
2966 cfgs->blueSize = values[2];
2967 cfgs->alphaSize = values[3];
2968 cfgs->depthSize = values[4];
2969 cfgs->stencilSize = values[5];
2970
2971 TRACE("iPixelFormat=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d\n", cfgs->iPixelFormat, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize);
2972 cfgs++;
2973 }
2974 WineD3D_ReleaseFakeGLContext();
2975
2976 fixup_extensions(&Adapters[0].gl_info);
2977
2978 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2979 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2980
2981 }
2982 numAdapters = 1;
2983 TRACE("%d adapters successfully initialized\n", numAdapters);
2984
2985 return TRUE;
2986 }
2987 #undef PUSH1
2988 #undef GLINFO_LOCATION
2989
2990 /**********************************************************
2991 * IWineD3D VTbl follows
2992 **********************************************************/
2993
2994 const IWineD3DVtbl IWineD3D_Vtbl =
2995 {
2996 /* IUnknown */
2997 IWineD3DImpl_QueryInterface,
2998 IWineD3DImpl_AddRef,
2999 IWineD3DImpl_Release,
3000 /* IWineD3D */
3001 IWineD3DImpl_GetParent,
3002 IWineD3DImpl_GetAdapterCount,
3003 IWineD3DImpl_RegisterSoftwareDevice,
3004 IWineD3DImpl_GetAdapterMonitor,
3005 IWineD3DImpl_GetAdapterModeCount,
3006 IWineD3DImpl_EnumAdapterModes,
3007 IWineD3DImpl_GetAdapterDisplayMode,
3008 IWineD3DImpl_GetAdapterIdentifier,
3009 IWineD3DImpl_CheckDeviceMultiSampleType,
3010 IWineD3DImpl_CheckDepthStencilMatch,
3011 IWineD3DImpl_CheckDeviceType,
3012 IWineD3DImpl_CheckDeviceFormat,
3013 IWineD3DImpl_CheckDeviceFormatConversion,
3014 IWineD3DImpl_GetDeviceCaps,
3015 IWineD3DImpl_CreateDevice
3016 };