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