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