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