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
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 /* Extension detection */
41 const char *extension_string;
42 GL_SupportedExt extension;
45 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE},
46 {"GL_APPLE_fence", APPLE_FENCE},
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},
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},
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},
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},
123 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP},
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
131 static int numAdapters = 0;
132 static struct WineD3DAdapter Adapters[1];
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) {
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);
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) {
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();
210 PIXELFORMATDESCRIPTOR pfd;
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");
221 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
222 if(!wined3d_fake_gl_context_hdc) {
223 ERR("GetDC failed!\n");
227 /* PixelFormat selection */
228 ZeroMemory(&pfd, sizeof(pfd));
229 pfd.nSize = sizeof(pfd);
231 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
232 pfd.iPixelType = PFD_TYPE_RGBA;
234 pfd.iLayerType = PFD_MAIN_PLANE;
236 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
238 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
239 ERR("Can't find a suitable iPixelFormat\n");
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);
248 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
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");
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);
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);
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);
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);
314 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
315 IWineD3DImpl *This = (IWineD3DImpl *)iface;
317 TRACE("(%p) : Releasing from %d\n", This, This->ref);
318 ref = InterlockedDecrement(&This->ref);
320 HeapFree(GetProcessHeap(), 0, This);
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,
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 < VS_VERSION_20)
342 *vs_selected = SHADER_ARB;
344 *vs_selected = SHADER_GLSL;
345 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
346 *vs_selected = SHADER_ARB;
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;
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) {
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;
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;
380 gl_info->max_vshader_constantsF = 0;
384 switch (ps_selected_mode) {
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;
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;
400 gl_info->max_pshader_constantsF = 0;
405 /**********************************************************
406 * IWineD3D parts follows
407 **********************************************************/
409 #define GLINFO_LOCATION (*gl_info)
410 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
411 const char *GL_Extensions = NULL;
412 const char *WGL_Extensions = NULL;
413 const char *gl_string = NULL;
414 const char *gl_string_cursor = NULL;
416 GLfloat gl_floatv[2];
417 int major = 1, minor = 0;
418 BOOL return_value = TRUE;
421 unsigned int vidmem=0;
423 TRACE_(d3d_caps)("(%p)\n", gl_info);
427 gl_string = (const char *) glGetString(GL_RENDERER);
428 if (NULL == gl_string)
430 strcpy(gl_info->gl_renderer, gl_string);
432 gl_string = (const char *) glGetString(GL_VENDOR);
433 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
434 if (gl_string != NULL) {
435 /* Fill in the GL vendor */
436 if (strstr(gl_string, "NVIDIA")) {
437 gl_info->gl_vendor = VENDOR_NVIDIA;
438 } else if (strstr(gl_string, "ATI")) {
439 gl_info->gl_vendor = VENDOR_ATI;
440 } else if (strstr(gl_string, "Intel(R)") ||
441 strstr(gl_info->gl_renderer, "Intel(R)")) {
442 gl_info->gl_vendor = VENDOR_INTEL;
443 } else if (strstr(gl_string, "Mesa")) {
444 gl_info->gl_vendor = VENDOR_MESA;
446 gl_info->gl_vendor = VENDOR_WINE;
449 gl_info->gl_vendor = VENDOR_WINE;
453 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
455 /* Parse the GL_VERSION field into major and minor information */
456 gl_string = (const char *) glGetString(GL_VERSION);
457 if (gl_string != NULL) {
459 switch (gl_info->gl_vendor) {
461 gl_string_cursor = strstr(gl_string, "NVIDIA");
462 if (!gl_string_cursor) {
463 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
467 gl_string_cursor = strstr(gl_string_cursor, " ");
468 if (!gl_string_cursor) {
469 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
473 while (*gl_string_cursor == ' ') {
477 if (!*gl_string_cursor) {
478 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
482 major = atoi(gl_string_cursor);
483 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
487 if (*gl_string_cursor++ != '.') {
488 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
492 minor = atoi(gl_string_cursor);
493 minor = major*100+minor;
500 gl_string_cursor = strchr(gl_string, '-');
501 if (gl_string_cursor) {
505 /* Check if version number is of the form x.y.z */
506 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
508 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
510 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
512 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
515 /* Mark version number as malformed */
517 gl_string_cursor = 0;
520 if (!gl_string_cursor)
521 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
523 major = *gl_string_cursor - '0';
524 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
530 gl_string_cursor = strstr(gl_string, "Mesa");
531 gl_string_cursor = strstr(gl_string_cursor, " ");
532 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
533 if (*gl_string_cursor) {
537 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
538 tmp[cursor++] = *gl_string_cursor;
544 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
548 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
549 tmp[cursor++] = *gl_string_cursor;
561 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
562 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
565 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
568 * Initialize openGL extension related variables
569 * with Default values
571 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
572 gl_info->max_buffers = 1;
573 gl_info->max_textures = 1;
574 gl_info->max_texture_stages = 1;
575 gl_info->max_fragment_samplers = 1;
576 gl_info->max_vertex_samplers = 0;
577 gl_info->max_combined_samplers = 0;
578 gl_info->max_sampler_stages = 1;
579 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
580 gl_info->ps_arb_max_temps = 0;
581 gl_info->ps_arb_max_instructions = 0;
582 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
583 gl_info->vs_arb_max_temps = 0;
584 gl_info->vs_arb_max_instructions = 0;
585 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
586 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
587 gl_info->vs_glsl_constantsF = 0;
588 gl_info->ps_glsl_constantsF = 0;
589 gl_info->vs_arb_constantsF = 0;
590 gl_info->ps_arb_constantsF = 0;
592 /* Now work out what GL support this card really has */
593 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
598 /* Retrieve opengl defaults */
599 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
600 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
601 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
603 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
604 gl_info->max_lights = gl_max;
605 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
607 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
608 gl_info->max_texture_size = gl_max;
609 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
611 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
612 gl_info->max_pointsize = gl_floatv[1];
613 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
615 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
616 gl_info->max_aux_buffers = gl_max;
617 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
619 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
620 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
621 TRACE_(d3d_caps)("GL_Extensions reported:\n");
623 if (NULL == GL_Extensions) {
624 ERR(" GL_Extensions returns NULL\n");
626 while (*GL_Extensions != 0x00) {
631 while (isspace(*GL_Extensions)) GL_Extensions++;
632 Start = GL_Extensions;
633 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
637 len = GL_Extensions - Start;
638 if (len == 0 || len >= sizeof(ThisExtn))
641 memcpy(ThisExtn, Start, len);
642 ThisExtn[len] = '\0';
643 TRACE_(d3d_caps)("- %s\n", ThisExtn);
645 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
646 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
647 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
648 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
654 if (gl_info->supported[APPLE_FENCE]) {
655 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
656 * The apple extension interacts with some other apple exts. Disable the NV
657 * extension if the apple one is support to prevent confusion in other parts
660 gl_info->supported[NV_FENCE] = FALSE;
662 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
663 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
664 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
666 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
667 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
668 * Won't occur in any real world situation though
670 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
672 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
673 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
674 gl_info->max_buffers = gl_max;
675 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
677 if (gl_info->supported[ARB_MULTITEXTURE]) {
678 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
679 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
680 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
682 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
684 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
685 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
687 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
689 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
691 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
693 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
694 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
696 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
698 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
700 if (gl_info->supported[ARB_VERTEX_SHADER]) {
702 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
703 gl_info->max_vertex_samplers = tmp;
704 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
705 gl_info->max_combined_samplers = tmp;
707 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
709 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
710 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
712 if (gl_info->supported[ARB_VERTEX_BLEND]) {
713 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
714 gl_info->max_blends = gl_max;
715 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
717 if (gl_info->supported[EXT_TEXTURE3D]) {
718 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
719 gl_info->max_texture3d_size = gl_max;
720 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
722 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
723 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
724 gl_info->max_anisotropy = gl_max;
725 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
727 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
728 gl_info->ps_arb_version = PS_VERSION_11;
729 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
730 gl_info->ps_arb_constantsF = gl_max;
731 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
732 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
733 gl_info->ps_arb_max_temps = gl_max;
734 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
735 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
736 gl_info->ps_arb_max_instructions = gl_max;
737 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
739 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
740 gl_info->vs_arb_version = VS_VERSION_11;
741 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
742 gl_info->vs_arb_constantsF = gl_max;
743 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
744 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
745 gl_info->vs_arb_max_temps = gl_max;
746 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
747 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
748 gl_info->vs_arb_max_instructions = gl_max;
749 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
751 if (gl_info->supported[ARB_VERTEX_SHADER]) {
752 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
753 gl_info->vs_glsl_constantsF = gl_max / 4;
754 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
756 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
757 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
758 gl_info->ps_glsl_constantsF = gl_max / 4;
759 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
761 if (gl_info->supported[EXT_VERTEX_SHADER]) {
762 gl_info->vs_ati_version = VS_VERSION_11;
764 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
765 gl_info->vs_nv_version = VS_VERSION_30;
766 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
767 gl_info->vs_nv_version = VS_VERSION_20;
768 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
769 gl_info->vs_nv_version = VS_VERSION_11;
770 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
771 gl_info->vs_nv_version = VS_VERSION_10;
773 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
774 gl_info->ps_nv_version = PS_VERSION_30;
775 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
776 gl_info->ps_nv_version = PS_VERSION_20;
780 checkGLcall("extension detection\n");
782 /* In some cases the number of texture stages can be larger than the number
783 * of samplers. The GF4 for example can use only 2 samplers (no fragment
784 * shaders), but 8 texture stages (register combiners). */
785 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
787 /* We can only use ORM_FBO when the hardware supports it. */
788 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
789 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
790 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
793 /* MRTs are currently only supported when FBOs are used. */
794 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
795 gl_info->max_buffers = 1;
798 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
799 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
800 * in case of the latest videocards in the number of pixel/vertex pipelines.
802 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
803 * rendering. Various games use this information to get a rough estimation of the features of the card
804 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
805 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
806 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
809 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
810 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
811 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
812 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
813 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
814 * is used for rendering which is not always the case). This would work but it is not very portable. Second
815 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
818 * As said most games only use the PCI id to get an indication of the capabilities of the card.
819 * It doesn't really matter if the given id is the correct one if we return the id of a card with
820 * similar 3d features.
822 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
823 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
824 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
825 * won't pass we return a default card. This way is better than maintaining a full card database as even
826 * without a full database we can return a card with similar features. Second the size of the database
827 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
828 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
829 * to distinguishes between different models from that family.
831 * The code also selects a default amount of video memory which we will use for an estimation of the amount
832 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
833 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
834 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
835 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
836 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
837 * memory behind our backs if really needed.
838 * Note that the amout of video memory can be overruled using a registry setting.
840 switch (gl_info->gl_vendor) {
842 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
843 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
845 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
846 /* Geforce8 - highend */
847 if (strstr(gl_info->gl_renderer, "8800")) {
848 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
849 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
851 /* Geforce8 - midend */
852 else if(strstr(gl_info->gl_renderer, "8600") ||
853 strstr(gl_info->gl_renderer, "8700"))
855 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
858 /* Geforce8 - lowend */
859 else if(strstr(gl_info->gl_renderer, "8300") ||
860 strstr(gl_info->gl_renderer, "8400") ||
861 strstr(gl_info->gl_renderer, "8500"))
863 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
864 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
866 /* Geforce7 - highend */
867 else if(strstr(gl_info->gl_renderer, "7800") ||
868 strstr(gl_info->gl_renderer, "7900") ||
869 strstr(gl_info->gl_renderer, "7950") ||
870 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
871 strstr(gl_info->gl_renderer, "Quadro FX 5"))
873 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
874 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
876 /* Geforce7 midend / Geforce6 highend */
877 else if(strstr(gl_info->gl_renderer, "6800") ||
878 strstr(gl_info->gl_renderer, "7600") ||
879 strstr(gl_info->gl_renderer, "7700"))
881 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
882 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
884 /* Geforce6 - midend */
885 else if(strstr(gl_info->gl_renderer, "6600") ||
886 strstr(gl_info->gl_renderer, "6610") ||
887 strstr(gl_info->gl_renderer, "6700"))
889 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
890 vidmem = 128; /* A 6600GT has 128-256MB */
892 /* Geforce6/7 lowend */
894 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
897 } else if(WINE_D3D9_CAPABLE(gl_info)) {
898 /* GeforceFX - highend */
899 if (strstr(gl_info->gl_renderer, "5800") ||
900 strstr(gl_info->gl_renderer, "5900") ||
901 strstr(gl_info->gl_renderer, "5950") ||
902 strstr(gl_info->gl_renderer, "Quadro FX"))
904 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
905 vidmem = 256; /* 5800-5900 cards use 256MB */
907 /* GeforceFX - midend */
908 else if(strstr(gl_info->gl_renderer, "5600") ||
909 strstr(gl_info->gl_renderer, "5650") ||
910 strstr(gl_info->gl_renderer, "5700") ||
911 strstr(gl_info->gl_renderer, "5750"))
913 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
914 vidmem = 128; /* A 5600 uses 128-256MB */
916 /* GeforceFX - lowend */
918 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
919 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
921 } else if(WINE_D3D8_CAPABLE(gl_info)) {
922 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
923 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
924 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
927 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
928 vidmem = 64; /* Geforce3 cards have 64-128MB */
930 } else if(WINE_D3D7_CAPABLE(gl_info)) {
931 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
932 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
933 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
935 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
936 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
937 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
939 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
940 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
941 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
944 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
945 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
948 if (strstr(gl_info->gl_renderer, "TNT2")) {
949 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
950 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
953 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
954 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
959 if(WINE_D3D9_CAPABLE(gl_info)) {
960 /* Radeon R6xx HD2900 - highend */
961 if (strstr(gl_info->gl_renderer, "HD 2900")) {
962 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
963 vidmem = 512; /* HD2900 uses 512-1024MB */
965 /* Radeon R6xx HD2600- midend */
966 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
967 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
968 vidmem = 256; /* HD2600 uses 256-512MB */
970 /* Radeon R6xx HD2300/HD2400 - lowend */
971 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
972 strstr(gl_info->gl_renderer, "HD 2400"))
974 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
975 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
978 else if (strstr(gl_info->gl_renderer, "X1600") ||
979 strstr(gl_info->gl_renderer, "X1650") ||
980 strstr(gl_info->gl_renderer, "X1800") ||
981 strstr(gl_info->gl_renderer, "X1900") ||
982 strstr(gl_info->gl_renderer, "X1950"))
984 gl_info->gl_card = CARD_ATI_RADEON_X1600;
985 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
987 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
988 else if(strstr(gl_info->gl_renderer, "X700") ||
989 strstr(gl_info->gl_renderer, "X800") ||
990 strstr(gl_info->gl_renderer, "X850") ||
991 strstr(gl_info->gl_renderer, "X1300") ||
992 strstr(gl_info->gl_renderer, "X1400") ||
993 strstr(gl_info->gl_renderer, "X1450") ||
994 strstr(gl_info->gl_renderer, "X1550"))
996 gl_info->gl_card = CARD_ATI_RADEON_X700;
997 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1001 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1002 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1004 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1005 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1006 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1007 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1008 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1009 vidmem = 32; /* There are models with up to 64MB */
1011 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1012 vidmem = 16; /* There are 16-32MB models */
1015 if (strstr(gl_info->gl_renderer, "915GM")) {
1016 gl_info->gl_card = CARD_INTEL_I915GM;
1017 } else if (strstr(gl_info->gl_renderer, "915G")) {
1018 gl_info->gl_card = CARD_INTEL_I915G;
1019 } else if (strstr(gl_info->gl_renderer, "865G")) {
1020 gl_info->gl_card = CARD_INTEL_I865G;
1021 } else if (strstr(gl_info->gl_renderer, "855G")) {
1022 gl_info->gl_card = CARD_INTEL_I855G;
1023 } else if (strstr(gl_info->gl_renderer, "830G")) {
1024 gl_info->gl_card = CARD_INTEL_I830G;
1026 gl_info->gl_card = CARD_INTEL_I915G;
1032 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1033 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1034 * them a good generic choice.
1036 gl_info->gl_vendor = VENDOR_NVIDIA;
1037 if(WINE_D3D9_CAPABLE(gl_info))
1038 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1039 else if(WINE_D3D8_CAPABLE(gl_info))
1040 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1041 else if(WINE_D3D7_CAPABLE(gl_info))
1042 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1043 else if(WINE_D3D6_CAPABLE(gl_info))
1044 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1046 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1048 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1050 /* If we have an estimate use it, else default to 64MB; */
1052 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1054 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1056 /* Load all the lookup tables
1057 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1058 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1059 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1061 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1062 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1065 for (i = 0; i < MAX_LOOKUPS; i++) {
1066 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1069 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1070 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1071 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1072 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1073 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1074 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1075 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1076 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1077 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1078 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1080 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1081 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1082 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1083 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1084 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1087 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1088 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1089 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1090 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1091 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1092 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1093 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1094 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1095 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1096 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1097 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1098 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1099 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1101 /* TODO: config lookups */
1103 /* Make sure there's an active HDC else the WGL extensions will fail */
1104 hdc = pwglGetCurrentDC();
1106 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1107 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1109 if (NULL == WGL_Extensions) {
1110 ERR(" WGL_Extensions returns NULL\n");
1112 while (*WGL_Extensions != 0x00) {
1117 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1118 Start = WGL_Extensions;
1119 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1123 len = WGL_Extensions - Start;
1124 if (len == 0 || len >= sizeof(ThisExtn))
1127 memcpy(ThisExtn, Start, len);
1128 ThisExtn[len] = '\0';
1129 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1131 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1132 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1133 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1140 return return_value;
1142 #undef GLINFO_LOCATION
1144 /**********************************************************
1145 * IWineD3D implementation follows
1146 **********************************************************/
1148 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1149 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1151 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1155 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1156 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1157 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1161 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1162 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1164 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1168 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1169 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1172 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1173 of the same bpp but different resolutions */
1175 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1176 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1177 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1178 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1180 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1184 /* TODO: Store modes per adapter and read it from the adapter structure */
1185 if (Adapter == 0) { /* Display */
1189 if (!DEBUG_SINGLE_MODE) {
1192 ZeroMemory(&DevModeW, sizeof(DevModeW));
1193 DevModeW.dmSize = sizeof(DevModeW);
1194 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1198 case WINED3DFMT_UNKNOWN:
1199 /* This is for D3D8, do not enumerate P8 here */
1200 if (DevModeW.dmBitsPerPel == 32 ||
1201 DevModeW.dmBitsPerPel == 16) i++;
1203 case WINED3DFMT_X8R8G8B8:
1204 if (DevModeW.dmBitsPerPel == 32) i++;
1206 case WINED3DFMT_R5G6B5:
1207 if (DevModeW.dmBitsPerPel == 16) i++;
1210 if (DevModeW.dmBitsPerPel == 8) i++;
1213 /* Skip other modes as they do not match the requested format */
1222 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1225 FIXME_(d3d_caps)("Adapter not primary display\n");
1230 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1231 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1232 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1233 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1235 /* Validate the parameters as much as possible */
1236 if (NULL == pMode ||
1237 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1238 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1239 return WINED3DERR_INVALIDCALL;
1242 /* TODO: Store modes per adapter and read it from the adapter structure */
1243 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1249 ZeroMemory(&DevModeW, sizeof(DevModeW));
1250 DevModeW.dmSize = sizeof(DevModeW);
1252 /* If we are filtering to a specific format (D3D9), then need to skip
1253 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1254 just count through the ones with valid bit depths */
1255 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1258 case WINED3DFMT_UNKNOWN:
1259 /* This is D3D8. Do not enumerate P8 here */
1260 if (DevModeW.dmBitsPerPel == 32 ||
1261 DevModeW.dmBitsPerPel == 16) i++;
1263 case WINED3DFMT_X8R8G8B8:
1264 if (DevModeW.dmBitsPerPel == 32) i++;
1266 case WINED3DFMT_R5G6B5:
1267 if (DevModeW.dmBitsPerPel == 16) i++;
1270 if (DevModeW.dmBitsPerPel == 8) i++;
1273 /* Modes that don't match what we support can get an early-out */
1274 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1275 return WINED3DERR_INVALIDCALL;
1280 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1281 return WINED3DERR_INVALIDCALL;
1285 /* Now get the display mode via the calculated index */
1286 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1287 pMode->Width = DevModeW.dmPelsWidth;
1288 pMode->Height = DevModeW.dmPelsHeight;
1289 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1290 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1291 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1293 if (Format == WINED3DFMT_UNKNOWN)
1295 switch (DevModeW.dmBitsPerPel)
1298 pMode->Format = WINED3DFMT_P8;
1301 pMode->Format = WINED3DFMT_R5G6B5;
1304 pMode->Format = WINED3DFMT_X8R8G8B8;
1307 pMode->Format = WINED3DFMT_UNKNOWN;
1308 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1311 pMode->Format = Format;
1314 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1315 return WINED3DERR_INVALIDCALL;
1318 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1319 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1320 DevModeW.dmBitsPerPel);
1322 } else if (DEBUG_SINGLE_MODE) {
1323 /* Return one setting of the format requested */
1324 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1326 pMode->Height = 600;
1327 pMode->RefreshRate = 60;
1328 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1330 FIXME_(d3d_caps)("Adapter not primary display\n");
1336 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1337 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1338 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1340 if (NULL == pMode ||
1341 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1342 return WINED3DERR_INVALIDCALL;
1345 if (Adapter == 0) { /* Display */
1349 ZeroMemory(&DevModeW, sizeof(DevModeW));
1350 DevModeW.dmSize = sizeof(DevModeW);
1352 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1353 pMode->Width = DevModeW.dmPelsWidth;
1354 pMode->Height = DevModeW.dmPelsHeight;
1355 bpp = DevModeW.dmBitsPerPel;
1356 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1357 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1359 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1363 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1364 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1365 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1366 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1367 default: pMode->Format = WINED3DFMT_UNKNOWN;
1371 FIXME_(d3d_caps)("Adapter not primary display\n");
1374 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1375 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1379 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1380 and fields being inserted in the middle, a new structure is used in place */
1381 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1382 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1383 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1385 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1387 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1388 return WINED3DERR_INVALIDCALL;
1391 /* Return the information requested */
1392 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1393 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1394 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1396 /* Note dx8 doesn't supply a DeviceName */
1397 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1398 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1399 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1400 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1401 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1402 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1403 *(pIdentifier->SubSysId) = 0;
1404 *(pIdentifier->Revision) = 0;
1406 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1407 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1408 *(pIdentifier->WHQLLevel) = 0;
1410 *(pIdentifier->WHQLLevel) = 1;
1416 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1417 short redSize, greenSize, blueSize, alphaSize, colorBits;
1422 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1423 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1427 if(cfg->redSize < redSize)
1430 if(cfg->greenSize < greenSize)
1433 if(cfg->blueSize < blueSize)
1436 if(cfg->alphaSize < alphaSize)
1442 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1443 short depthSize, stencilSize;
1448 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1449 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1453 if(cfg->depthSize < depthSize)
1456 if(cfg->stencilSize < stencilSize)
1462 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1463 WINED3DFORMAT AdapterFormat,
1464 WINED3DFORMAT RenderTargetFormat,
1465 WINED3DFORMAT DepthStencilFormat) {
1466 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1468 WineD3D_PixelFormat *cfgs;
1471 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1473 DeviceType, debug_d3ddevicetype(DeviceType),
1474 AdapterFormat, debug_d3dformat(AdapterFormat),
1475 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1476 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1478 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1479 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1480 return WINED3DERR_INVALIDCALL;
1483 cfgs = Adapters[Adapter].cfgs;
1484 nCfgs = Adapters[Adapter].nCfgs;
1485 for (it = 0; it < nCfgs; ++it) {
1486 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1487 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1488 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1493 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1495 return WINED3DERR_NOTAVAILABLE;
1498 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1499 WINED3DFORMAT SurfaceFormat,
1500 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1502 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1503 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1506 DeviceType, debug_d3ddevicetype(DeviceType),
1507 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1512 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1513 return WINED3DERR_INVALIDCALL;
1516 /* TODO: Store in Adapter structure */
1517 if (pQualityLevels != NULL) {
1518 static int s_single_shot = 0;
1519 if (!s_single_shot) {
1520 FIXME("Quality levels unsupported at present\n");
1523 *pQualityLevels = 1; /* Guess at a value! */
1526 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1527 return WINED3DERR_NOTAVAILABLE;
1530 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1531 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1533 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1535 WineD3D_PixelFormat *cfgs;
1537 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1539 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1542 CheckType, debug_d3ddevicetype(CheckType),
1543 DisplayFormat, debug_d3dformat(DisplayFormat),
1544 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1547 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1548 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1549 return WINED3DERR_INVALIDCALL;
1552 cfgs = Adapters[Adapter].cfgs;
1553 nCfgs = Adapters[Adapter].nCfgs;
1554 for (it = 0; it < nCfgs; ++it) {
1555 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1557 TRACE_(d3d_caps)("OK\n");
1562 if(hr != WINED3D_OK)
1563 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1565 if(hr != WINED3D_OK)
1566 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1571 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1572 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1573 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1574 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1575 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1578 DeviceType, debug_d3ddevicetype(DeviceType),
1579 AdapterFormat, debug_d3dformat(AdapterFormat),
1580 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1581 RType, debug_d3dresourcetype(RType),
1582 CheckFormat, debug_d3dformat(CheckFormat));
1584 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1585 return WINED3DERR_INVALIDCALL;
1588 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1589 switch (CheckFormat) {
1590 /* Filtering not supported */
1591 case WINED3DFMT_R32F:
1592 case WINED3DFMT_A32B32G32R32F:
1593 TRACE_(d3d_caps)("[FAILED]\n");
1594 return WINED3DERR_NOTAVAILABLE;
1600 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1601 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1602 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1603 return WINED3DERR_NOTAVAILABLE;
1607 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1608 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1609 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1610 return WINED3DERR_NOTAVAILABLE;
1612 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1613 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1614 * app needing one of those formats, don't advertize them to avoid leading apps into
1615 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1618 switch(CheckFormat) {
1620 case WINED3DFMT_A4L4:
1621 case WINED3DFMT_R32F:
1622 case WINED3DFMT_R16F:
1623 case WINED3DFMT_X8L8V8U8:
1624 case WINED3DFMT_L6V5U5:
1625 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1626 return WINED3DERR_NOTAVAILABLE;
1628 case WINED3DFMT_Q8W8V8U8:
1629 case WINED3DFMT_V16U16:
1630 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1631 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1632 return WINED3DERR_NOTAVAILABLE;
1636 case WINED3DFMT_V8U8:
1637 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1638 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1639 return WINED3DERR_NOTAVAILABLE;
1643 case WINED3DFMT_DXT1:
1644 case WINED3DFMT_DXT2:
1645 case WINED3DFMT_DXT3:
1646 case WINED3DFMT_DXT4:
1647 case WINED3DFMT_DXT5:
1648 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1649 * compressed texture results in an error. While the D3D refrast does
1650 * support s3tc volumes, at least the nvidia windows driver does not, so
1651 * we're free not to support this format.
1653 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1654 return WINED3DERR_NOTAVAILABLE;
1657 /* Do nothing, continue with checking the format below */
1661 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1662 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1663 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1664 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1665 if (!GL_LIMITS(vertex_samplers)) {
1666 TRACE_(d3d_caps)("[FAILED]\n");
1667 return WINED3DERR_NOTAVAILABLE;
1670 switch (CheckFormat) {
1671 case WINED3DFMT_A32B32G32R32F:
1672 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1673 TRACE_(d3d_caps)("[FAILED]\n");
1674 return WINED3DERR_NOTAVAILABLE;
1676 TRACE_(d3d_caps)("[OK]\n");
1680 TRACE_(d3d_caps)("[FAILED]\n");
1681 return WINED3DERR_NOTAVAILABLE;
1685 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1686 switch (CheckFormat) {
1687 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1688 * Windows supports only those 3, and enumerating the other formats confuses applications
1690 case WINED3DFMT_D24S8:
1691 case WINED3DFMT_D24X8:
1692 case WINED3DFMT_D16:
1693 TRACE_(d3d_caps)("[OK]\n");
1695 case WINED3DFMT_D16_LOCKABLE:
1696 case WINED3DFMT_D24FS8:
1697 case WINED3DFMT_D32F_LOCKABLE:
1698 case WINED3DFMT_D24X4S4:
1699 case WINED3DFMT_D15S1:
1700 case WINED3DFMT_D32:
1701 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1702 return WINED3DERR_NOTAVAILABLE;
1704 TRACE_(d3d_caps)("[FAILED]\n");
1705 return WINED3DERR_NOTAVAILABLE;
1707 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1708 switch (CheckFormat) {
1709 case WINED3DFMT_R8G8B8:
1710 case WINED3DFMT_A8R8G8B8:
1711 case WINED3DFMT_X8R8G8B8:
1712 case WINED3DFMT_R5G6B5:
1713 case WINED3DFMT_X1R5G5B5:
1714 case WINED3DFMT_A1R5G5B5:
1715 case WINED3DFMT_A4R4G4B4:
1716 case WINED3DFMT_R3G3B2:
1717 case WINED3DFMT_X4R4G4B4:
1718 case WINED3DFMT_A8B8G8R8:
1719 case WINED3DFMT_X8B8G8R8:
1721 TRACE_(d3d_caps)("[OK]\n");
1723 case WINED3DFMT_R16F:
1724 case WINED3DFMT_A16B16G16R16F:
1725 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1726 TRACE_(d3d_caps)("[FAILED]\n");
1727 return WINED3DERR_NOTAVAILABLE;
1729 TRACE_(d3d_caps)("[OK]\n");
1731 case WINED3DFMT_A32B32G32R32F:
1732 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1733 TRACE_(d3d_caps)("[FAILED]\n");
1734 return WINED3DERR_NOTAVAILABLE;
1736 TRACE_(d3d_caps)("[OK]\n");
1739 TRACE_(d3d_caps)("[FAILED]\n");
1740 return WINED3DERR_NOTAVAILABLE;
1742 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1743 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1744 switch (CheckFormat) {
1745 case WINED3DFMT_V8U8:
1746 TRACE_(d3d_caps)("[OK]\n");
1748 /* TODO: Other bump map formats */
1750 TRACE_(d3d_caps)("[FAILED]\n");
1751 return WINED3DERR_NOTAVAILABLE;
1754 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1755 switch (CheckFormat) {
1756 case WINED3DFMT_V8U8:
1757 TRACE_(d3d_caps)("[OK]\n");
1760 TRACE_(d3d_caps)("[FAILED]\n");
1761 return WINED3DERR_NOTAVAILABLE;
1764 TRACE_(d3d_caps)("[FAILED]\n");
1765 return WINED3DERR_NOTAVAILABLE;
1768 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1769 switch (CheckFormat) {
1770 case WINED3DFMT_DXT1:
1771 case WINED3DFMT_DXT2:
1772 case WINED3DFMT_DXT3:
1773 case WINED3DFMT_DXT4:
1774 case WINED3DFMT_DXT5:
1775 TRACE_(d3d_caps)("[OK]\n");
1778 break; /* Avoid compiler warnings */
1782 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1783 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1784 switch (CheckFormat) {
1785 case WINED3DFMT_A8R8G8B8:
1786 case WINED3DFMT_X8R8G8B8:
1787 case WINED3DFMT_A4R4G4B4:
1789 case WINED3DFMT_A8L8:
1790 case WINED3DFMT_DXT1:
1791 case WINED3DFMT_DXT2:
1792 case WINED3DFMT_DXT3:
1793 case WINED3DFMT_DXT4:
1794 case WINED3DFMT_DXT5:
1795 TRACE_(d3d_caps)("[OK]\n");
1799 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1800 return WINED3DERR_NOTAVAILABLE;
1804 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1806 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1808 switch (CheckFormat) {
1809 case WINED3DFMT_R16F:
1810 case WINED3DFMT_A16B16G16R16F:
1811 if (!half_pixel_support) break;
1812 case WINED3DFMT_R32F:
1813 case WINED3DFMT_A32B32G32R32F:
1814 TRACE_(d3d_caps)("[OK]\n");
1817 break; /* Avoid compiler warnings */
1821 /* This format is nothing special and it is supported perfectly.
1822 * However, ati and nvidia driver on windows do not mark this format as
1823 * supported (tested with the dxCapsViewer) and pretending to
1824 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1825 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1826 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1828 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1829 TRACE_(d3d_caps)("[FAILED]\n");
1830 return WINED3DERR_NOTAVAILABLE;
1833 switch (CheckFormat) {
1836 * supported: RGB(A) formats
1838 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1839 case WINED3DFMT_A8R8G8B8:
1840 case WINED3DFMT_X8R8G8B8:
1841 case WINED3DFMT_R5G6B5:
1842 case WINED3DFMT_X1R5G5B5:
1843 case WINED3DFMT_A1R5G5B5:
1844 case WINED3DFMT_A4R4G4B4:
1845 case WINED3DFMT_R3G3B2:
1847 case WINED3DFMT_X4R4G4B4:
1848 case WINED3DFMT_A8B8G8R8:
1849 case WINED3DFMT_X8B8G8R8:
1850 case WINED3DFMT_A2R10G10B10:
1851 case WINED3DFMT_A2B10G10R10:
1852 TRACE_(d3d_caps)("[OK]\n");
1856 * supported: Palettized
1859 TRACE_(d3d_caps)("[OK]\n");
1863 * Supported: (Alpha)-Luminance
1866 case WINED3DFMT_A8L8:
1867 case WINED3DFMT_A4L4:
1868 TRACE_(d3d_caps)("[OK]\n");
1872 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1873 * GL_NV_texture_shader), but advertized to make apps happy.
1874 * Enable some because games often fail when they are not available
1875 * and are still playable even without bump mapping
1877 case WINED3DFMT_V8U8:
1878 case WINED3DFMT_V16U16:
1879 case WINED3DFMT_L6V5U5:
1880 case WINED3DFMT_X8L8V8U8:
1881 case WINED3DFMT_Q8W8V8U8:
1882 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1885 /* Those are not advertized by the nvidia windows driver, and not
1886 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1887 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1888 * ARGB format if needed
1890 case WINED3DFMT_W11V11U10:
1891 case WINED3DFMT_A2W10V10U10:
1892 WARN_(d3d_caps)("[FAILED]\n");
1893 return WINED3DERR_NOTAVAILABLE;
1896 * DXTN Formats: Handled above
1905 * Odd formats - not supported
1907 case WINED3DFMT_VERTEXDATA:
1908 case WINED3DFMT_INDEX16:
1909 case WINED3DFMT_INDEX32:
1910 case WINED3DFMT_Q16W16V16U16:
1911 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1912 return WINED3DERR_NOTAVAILABLE;
1915 * Float formats: Not supported right now
1917 case WINED3DFMT_G16R16F:
1918 case WINED3DFMT_G32R32F:
1919 case WINED3DFMT_CxV8U8:
1920 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1921 return WINED3DERR_NOTAVAILABLE;
1924 case WINED3DFMT_G16R16:
1925 case WINED3DFMT_A16B16G16R16:
1926 case WINED3DFMT_A8R3G3B2:
1927 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1928 return WINED3DERR_NOTAVAILABLE;
1930 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1931 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1932 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1933 * We can do instancing with all shader versions, but we need vertex shaders.
1935 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1936 * to enable instancing. WineD3D doesn't need that and just ignores it.
1938 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1940 case WINEMAKEFOURCC('I','N','S','T'):
1941 TRACE("ATI Instancing check hack\n");
1942 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1943 TRACE_(d3d_caps)("[OK]\n");
1946 TRACE_(d3d_caps)("[FAILED]\n");
1947 return WINED3DERR_NOTAVAILABLE;
1954 TRACE_(d3d_caps)("[FAILED]\n");
1955 return WINED3DERR_NOTAVAILABLE;
1958 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1959 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1960 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1962 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1965 DeviceType, debug_d3ddevicetype(DeviceType),
1966 SourceFormat, debug_d3dformat(SourceFormat),
1967 TargetFormat, debug_d3dformat(TargetFormat));
1971 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1972 subset of a D3DCAPS9 structure. However, it has to come via a void *
1973 as the d3d8 interface cannot import the d3d9 header */
1974 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1976 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1977 int vs_selected_mode;
1978 int ps_selected_mode;
1980 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1982 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1983 return WINED3DERR_INVALIDCALL;
1986 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1988 /* This function should *not* be modifying GL caps
1989 * TODO: move the functionality where it belongs */
1990 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1992 /* ------------------------------------------------
1993 The following fields apply to both d3d8 and d3d9
1994 ------------------------------------------------ */
1995 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1996 *pCaps->AdapterOrdinal = Adapter;
1999 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2000 WINED3DCAPS2_FULLSCREENGAMMA |
2001 WINED3DCAPS2_DYNAMICTEXTURES;
2002 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2003 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2005 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2006 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2007 WINED3DPRESENT_INTERVAL_ONE;
2009 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2010 WINED3DCURSORCAPS_LOWRES;
2012 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2013 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2014 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2015 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2016 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2017 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2018 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2019 WINED3DDEVCAPS_PUREDEVICE |
2020 WINED3DDEVCAPS_HWRASTERIZATION |
2021 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2022 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2023 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2024 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2025 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2026 WINED3DDEVCAPS_RTPATCHES;
2028 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2029 WINED3DPMISCCAPS_CULLCCW |
2030 WINED3DPMISCCAPS_CULLCW |
2031 WINED3DPMISCCAPS_COLORWRITEENABLE |
2032 WINED3DPMISCCAPS_CLIPTLVERTS |
2033 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2034 WINED3DPMISCCAPS_MASKZ |
2035 WINED3DPMISCCAPS_BLENDOP;
2037 WINED3DPMISCCAPS_NULLREFERENCE
2038 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2039 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2040 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2041 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2042 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2043 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2045 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2047 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2048 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2049 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2050 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2053 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2054 WINED3DPRASTERCAPS_PAT |
2055 WINED3DPRASTERCAPS_WFOG |
2056 WINED3DPRASTERCAPS_ZFOG |
2057 WINED3DPRASTERCAPS_FOGVERTEX |
2058 WINED3DPRASTERCAPS_FOGTABLE |
2059 WINED3DPRASTERCAPS_STIPPLE |
2060 WINED3DPRASTERCAPS_SUBPIXEL |
2061 WINED3DPRASTERCAPS_ZTEST |
2062 WINED3DPRASTERCAPS_SCISSORTEST |
2063 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2064 WINED3DPRASTERCAPS_DEPTHBIAS;
2066 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2067 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2068 WINED3DPRASTERCAPS_ZBIAS |
2069 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2071 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2072 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2075 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2076 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2077 WINED3DPRASTERCAPS_ANTIALIASEDGES
2078 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2079 WINED3DPRASTERCAPS_WBUFFER */
2081 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2082 WINED3DPCMPCAPS_EQUAL |
2083 WINED3DPCMPCAPS_GREATER |
2084 WINED3DPCMPCAPS_GREATEREQUAL |
2085 WINED3DPCMPCAPS_LESS |
2086 WINED3DPCMPCAPS_LESSEQUAL |
2087 WINED3DPCMPCAPS_NEVER |
2088 WINED3DPCMPCAPS_NOTEQUAL;
2090 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2091 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2092 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2093 WINED3DPBLENDCAPS_DESTALPHA |
2094 WINED3DPBLENDCAPS_DESTCOLOR |
2095 WINED3DPBLENDCAPS_INVDESTALPHA |
2096 WINED3DPBLENDCAPS_INVDESTCOLOR |
2097 WINED3DPBLENDCAPS_INVSRCALPHA |
2098 WINED3DPBLENDCAPS_INVSRCCOLOR |
2099 WINED3DPBLENDCAPS_ONE |
2100 WINED3DPBLENDCAPS_SRCALPHA |
2101 WINED3DPBLENDCAPS_SRCALPHASAT |
2102 WINED3DPBLENDCAPS_SRCCOLOR |
2103 WINED3DPBLENDCAPS_ZERO;
2105 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2106 WINED3DPBLENDCAPS_DESTALPHA |
2107 WINED3DPBLENDCAPS_DESTCOLOR |
2108 WINED3DPBLENDCAPS_INVDESTALPHA |
2109 WINED3DPBLENDCAPS_INVDESTCOLOR |
2110 WINED3DPBLENDCAPS_INVSRCALPHA |
2111 WINED3DPBLENDCAPS_INVSRCCOLOR |
2112 WINED3DPBLENDCAPS_ONE |
2113 WINED3DPBLENDCAPS_SRCALPHA |
2114 WINED3DPBLENDCAPS_SRCCOLOR |
2115 WINED3DPBLENDCAPS_ZERO;
2116 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2117 * according to the glBlendFunc manpage
2119 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2120 * legacy settings for srcblend only
2123 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2124 WINED3DPCMPCAPS_EQUAL |
2125 WINED3DPCMPCAPS_GREATER |
2126 WINED3DPCMPCAPS_GREATEREQUAL |
2127 WINED3DPCMPCAPS_LESS |
2128 WINED3DPCMPCAPS_LESSEQUAL |
2129 WINED3DPCMPCAPS_NEVER |
2130 WINED3DPCMPCAPS_NOTEQUAL;
2132 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2133 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2134 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2135 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2136 WINED3DPSHADECAPS_COLORFLATRGB |
2137 WINED3DPSHADECAPS_FOGFLAT |
2138 WINED3DPSHADECAPS_FOGGOURAUD |
2139 WINED3DPSHADECAPS_SPECULARFLATRGB;
2141 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2142 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2143 WINED3DPTEXTURECAPS_BORDER |
2144 WINED3DPTEXTURECAPS_MIPMAP |
2145 WINED3DPTEXTURECAPS_PROJECTED |
2146 WINED3DPTEXTURECAPS_PERSPECTIVE;
2148 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2149 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2150 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2153 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2154 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2155 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2156 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2159 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2160 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2161 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2162 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2166 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2167 WINED3DPTFILTERCAPS_MAGFPOINT |
2168 WINED3DPTFILTERCAPS_MINFLINEAR |
2169 WINED3DPTFILTERCAPS_MINFPOINT |
2170 WINED3DPTFILTERCAPS_MIPFLINEAR |
2171 WINED3DPTFILTERCAPS_MIPFPOINT |
2172 WINED3DPTFILTERCAPS_LINEAR |
2173 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2174 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2175 WINED3DPTFILTERCAPS_MIPLINEAR |
2176 WINED3DPTFILTERCAPS_MIPNEAREST |
2177 WINED3DPTFILTERCAPS_NEAREST;
2179 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2180 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2181 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2184 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2185 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2186 WINED3DPTFILTERCAPS_MAGFPOINT |
2187 WINED3DPTFILTERCAPS_MINFLINEAR |
2188 WINED3DPTFILTERCAPS_MINFPOINT |
2189 WINED3DPTFILTERCAPS_MIPFLINEAR |
2190 WINED3DPTFILTERCAPS_MIPFPOINT |
2191 WINED3DPTFILTERCAPS_LINEAR |
2192 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2193 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2194 WINED3DPTFILTERCAPS_MIPLINEAR |
2195 WINED3DPTFILTERCAPS_MIPNEAREST |
2196 WINED3DPTFILTERCAPS_NEAREST;
2198 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2199 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2200 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2203 *pCaps->CubeTextureFilterCaps = 0;
2205 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2206 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2207 WINED3DPTFILTERCAPS_MAGFPOINT |
2208 WINED3DPTFILTERCAPS_MINFLINEAR |
2209 WINED3DPTFILTERCAPS_MINFPOINT |
2210 WINED3DPTFILTERCAPS_MIPFLINEAR |
2211 WINED3DPTFILTERCAPS_MIPFPOINT |
2212 WINED3DPTFILTERCAPS_LINEAR |
2213 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2214 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2215 WINED3DPTFILTERCAPS_MIPLINEAR |
2216 WINED3DPTFILTERCAPS_MIPNEAREST |
2217 WINED3DPTFILTERCAPS_NEAREST;
2219 *pCaps->VolumeTextureFilterCaps = 0;
2221 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2222 WINED3DPTADDRESSCAPS_CLAMP |
2223 WINED3DPTADDRESSCAPS_WRAP;
2225 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2226 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2228 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2229 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2231 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2232 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2235 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2236 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2237 WINED3DPTADDRESSCAPS_CLAMP |
2238 WINED3DPTADDRESSCAPS_WRAP;
2239 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2240 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2242 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2243 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2245 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2246 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2249 *pCaps->VolumeTextureAddressCaps = 0;
2251 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2252 WINED3DLINECAPS_ZTEST;
2254 WINED3DLINECAPS_BLEND
2255 WINED3DLINECAPS_ALPHACMP
2256 WINED3DLINECAPS_FOG */
2258 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2259 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2261 if(GL_SUPPORT(EXT_TEXTURE3D))
2262 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2264 *pCaps->MaxVolumeExtent = 0;
2266 *pCaps->MaxTextureRepeat = 32768;
2267 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2268 *pCaps->MaxVertexW = 1.0;
2270 *pCaps->GuardBandLeft = 0;
2271 *pCaps->GuardBandTop = 0;
2272 *pCaps->GuardBandRight = 0;
2273 *pCaps->GuardBandBottom = 0;
2275 *pCaps->ExtentsAdjust = 0;
2277 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2278 WINED3DSTENCILCAPS_INCRSAT |
2279 WINED3DSTENCILCAPS_INVERT |
2280 WINED3DSTENCILCAPS_KEEP |
2281 WINED3DSTENCILCAPS_REPLACE |
2282 WINED3DSTENCILCAPS_ZERO;
2283 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2284 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2285 WINED3DSTENCILCAPS_INCR;
2287 if ( This->dxVersion > 8 &&
2288 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2289 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2290 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2293 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2295 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2296 WINED3DTEXOPCAPS_ADDSIGNED |
2297 WINED3DTEXOPCAPS_ADDSIGNED2X |
2298 WINED3DTEXOPCAPS_MODULATE |
2299 WINED3DTEXOPCAPS_MODULATE2X |
2300 WINED3DTEXOPCAPS_MODULATE4X |
2301 WINED3DTEXOPCAPS_SELECTARG1 |
2302 WINED3DTEXOPCAPS_SELECTARG2 |
2303 WINED3DTEXOPCAPS_DISABLE;
2305 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2306 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2307 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2308 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2309 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2310 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2311 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2312 WINED3DTEXOPCAPS_LERP |
2313 WINED3DTEXOPCAPS_SUBTRACT;
2315 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2316 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2317 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2318 WINED3DTEXOPCAPS_MULTIPLYADD |
2319 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2320 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2321 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2323 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2324 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2326 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2327 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2328 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2331 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2332 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2333 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2334 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2335 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2336 * and 3D textures. It also allows us to keep the code simpler by having texture
2337 * shaders constantly enabled.
2339 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2340 /* TODO: Luminance bump map? */
2344 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2345 WINED3DTEXOPCAPS_PREMODULATE */
2348 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2349 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2350 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2351 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2353 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2354 *pCaps->MaxVertexBlendMatrixIndex = 0;
2356 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2357 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2360 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2361 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2362 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2363 WINED3DVTXPCAPS_LOCALVIEWER |
2364 WINED3DVTXPCAPS_VERTEXFOG |
2365 WINED3DVTXPCAPS_TEXGEN;
2367 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2369 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2370 *pCaps->MaxVertexIndex = 0xFFFFF;
2371 *pCaps->MaxStreams = MAX_STREAMS;
2372 *pCaps->MaxStreamStride = 1024;
2374 if (vs_selected_mode == SHADER_GLSL) {
2375 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2376 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2377 * vs_nv_version which is based on NV_vertex_program.
2378 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2379 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2380 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2381 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2382 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2383 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2385 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2386 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2387 } else if (vs_selected_mode == SHADER_ARB) {
2388 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2389 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2391 *pCaps->VertexShaderVersion = 0;
2392 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2395 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2397 if (ps_selected_mode == SHADER_GLSL) {
2398 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2399 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2400 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2401 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2402 * in max native instructions. Intel and others also offer the info in this extension but they
2403 * don't support GLSL (at least on Windows).
2405 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number
2406 * of instructions is 512 or less we have to do with ps2.0 hardware.
2407 * 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.
2409 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2410 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2412 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2413 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2414 * Direct3D minimum requirement.
2416 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2417 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2419 * The problem is that the refrast clamps temporary results in the shader to
2420 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2421 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2422 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2423 * offer a way to query this.
2425 *pCaps->PixelShader1xMaxValue = 8.0;
2426 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2427 } else if (ps_selected_mode == SHADER_ARB) {
2428 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2429 *pCaps->PixelShader1xMaxValue = 8.0;
2430 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2432 *pCaps->PixelShaderVersion = 0;
2433 *pCaps->PixelShader1xMaxValue = 0.0;
2434 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2437 /* ------------------------------------------------
2438 The following fields apply to d3d9 only
2439 ------------------------------------------------ */
2440 if (This->dxVersion > 8) {
2441 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2442 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2443 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2444 *pCaps->MaxNpatchTessellationLevel = 0;
2445 *pCaps->MasterAdapterOrdinal = 0;
2446 *pCaps->AdapterOrdinalInGroup = 0;
2447 *pCaps->NumberOfAdaptersInGroup = 1;
2449 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2450 /* OpenGL supports all the formats below, perhaps not always
2451 * without conversion, but it supports them.
2452 * Further GLSL doesn't seem to have an official unsigned type so
2453 * don't advertise it yet as I'm not sure how we handle it.
2454 * We might need to add some clamping in the shader engine to
2456 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2457 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2458 WINED3DDTCAPS_UBYTE4N |
2459 WINED3DDTCAPS_SHORT2N |
2460 WINED3DDTCAPS_SHORT4N;
2461 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2462 *pCaps->DeclTypes |=
2463 WINED3DDTCAPS_FLOAT16_2 |
2464 WINED3DDTCAPS_FLOAT16_4;
2467 *pCaps->DeclTypes = 0;
2469 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2472 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2473 WINED3DPTFILTERCAPS_MAGFPOINT |
2474 WINED3DPTFILTERCAPS_MINFLINEAR |
2475 WINED3DPTFILTERCAPS_MAGFLINEAR;
2476 *pCaps->VertexTextureFilterCaps = 0;
2478 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2479 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2480 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2481 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2482 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2483 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2484 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2486 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2487 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2488 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2489 *pCaps->VS20Caps.Caps = 0;
2490 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2491 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2492 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2494 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2495 *pCaps->MaxVertexShader30InstructionSlots = 0;
2496 } else { /* VS 1.x */
2497 *pCaps->VS20Caps.Caps = 0;
2498 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2499 *pCaps->VS20Caps.NumTemps = 0;
2500 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2502 *pCaps->MaxVShaderInstructionsExecuted = 0;
2503 *pCaps->MaxVertexShader30InstructionSlots = 0;
2506 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2507 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2508 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2510 /* 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 */
2511 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2512 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2513 WINED3DPS20CAPS_PREDICATION |
2514 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2515 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2516 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2517 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2518 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2519 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2521 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2522 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2523 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2524 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2525 *pCaps->PS20Caps.Caps = 0;
2526 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2527 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2528 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2529 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2531 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2532 *pCaps->MaxPixelShader30InstructionSlots = 0;
2533 } else { /* PS 1.x */
2534 *pCaps->PS20Caps.Caps = 0;
2535 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2536 *pCaps->PS20Caps.NumTemps = 0;
2537 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2538 *pCaps->PS20Caps.NumInstructionSlots = 0;
2540 *pCaps->MaxPShaderInstructionsExecuted = 0;
2541 *pCaps->MaxPixelShader30InstructionSlots = 0;
2548 static unsigned int glsl_program_key_hash(void *key) {
2549 glsl_program_key_t *k = (glsl_program_key_t *)key;
2551 unsigned int hash = k->vshader | k->pshader << 16;
2552 hash += ~(hash << 15);
2553 hash ^= (hash >> 10);
2554 hash += (hash << 3);
2555 hash ^= (hash >> 6);
2556 hash += ~(hash << 11);
2557 hash ^= (hash >> 16);
2562 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2563 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2564 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2566 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2569 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2570 and fields being inserted in the middle, a new structure is used in place */
2571 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2572 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2575 IWineD3DDeviceImpl *object = NULL;
2576 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2580 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2581 * number and create a device without a 3D adapter for 2D only operation.
2583 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2584 return WINED3DERR_INVALIDCALL;
2587 /* Create a WineD3DDevice object */
2588 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2589 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2590 TRACE("Created WineD3DDevice object @ %p\n", object);
2591 if (NULL == object) {
2592 return WINED3DERR_OUTOFVIDEOMEMORY;
2595 /* Set up initial COM information */
2596 object->lpVtbl = &IWineD3DDevice_Vtbl;
2598 object->wineD3D = iface;
2599 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2600 IWineD3D_AddRef(object->wineD3D);
2601 object->parent = parent;
2603 if(This->dxVersion == 7) {
2604 object->surface_alignment = 8;
2606 object->surface_alignment = 4;
2609 /* Set the state up as invalid until the device is fully created */
2610 object->state = WINED3DERR_DRIVERINTERNALERROR;
2612 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2613 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2615 /* Save the creation parameters */
2616 object->createParms.AdapterOrdinal = Adapter;
2617 object->createParms.DeviceType = DeviceType;
2618 object->createParms.hFocusWindow = hFocusWindow;
2619 object->createParms.BehaviorFlags = BehaviourFlags;
2621 /* Initialize other useful values */
2622 object->adapterNo = Adapter;
2623 object->devType = DeviceType;
2625 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2626 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2627 object->shader_backend = &glsl_shader_backend;
2628 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2629 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2630 object->shader_backend = &arb_program_shader_backend;
2632 object->shader_backend = &none_shader_backend;
2635 /* set the state of the device to valid */
2636 object->state = WINED3D_OK;
2638 /* Get the initial screen setup for ddraw */
2639 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2640 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2642 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2645 for(i = 0; i < PATCHMAP_SIZE; i++) {
2646 list_init(&object->patches[i]);
2650 #undef GLINFO_LOCATION
2652 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2653 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2654 IUnknown_AddRef(This->parent);
2655 *pParent = This->parent;
2659 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2660 IUnknown* surfaceParent;
2661 TRACE("(%p) call back\n", pSurface);
2663 /* Now, release the parent, which will take care of cleaning up the surface for us */
2664 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2665 IUnknown_Release(surfaceParent);
2666 return IUnknown_Release(surfaceParent);
2669 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2670 IUnknown* volumeParent;
2671 TRACE("(%p) call back\n", pVolume);
2673 /* Now, release the parent, which will take care of cleaning up the volume for us */
2674 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2675 IUnknown_Release(volumeParent);
2676 return IUnknown_Release(volumeParent);
2679 #define PUSH1(att) attribs[nAttribs++] = (att);
2680 #define GLINFO_LOCATION (Adapters[0].gl_info)
2681 BOOL InitAdapters(void) {
2682 static HMODULE mod_gl;
2684 int ps_selected_mode, vs_selected_mode;
2686 /* No need to hold any lock. The calling library makes sure only one thread calls
2687 * wined3d simultaneously
2689 if(numAdapters > 0) return TRUE;
2691 TRACE("Initializing adapters\n");
2694 #ifdef USE_WIN32_OPENGL
2695 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2696 mod_gl = LoadLibraryA("opengl32.dll");
2698 ERR("Can't load opengl32.dll!\n");
2702 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2703 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2704 mod_gl = GetModuleHandleA("gdi32.dll");
2708 /* Load WGL core functions from opengl32.dll */
2709 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2713 if(!pwglGetProcAddress) {
2714 ERR("Unable to load wglGetProcAddress!\n");
2718 /* Dynamically load all GL core functions */
2722 /* For now only one default adapter */
2729 WineD3D_PixelFormat *cfgs;
2731 DISPLAY_DEVICEW DisplayDevice;
2734 TRACE("Initializing default adapter\n");
2735 Adapters[0].monitorPoint.x = -1;
2736 Adapters[0].monitorPoint.y = -1;
2738 if (!WineD3D_CreateFakeGLContext()) {
2739 ERR("Failed to get a gl context for default adapter\n");
2740 HeapFree(GetProcessHeap(), 0, Adapters);
2741 WineD3D_ReleaseFakeGLContext();
2745 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2747 ERR("Failed to initialize gl caps for default adapter\n");
2748 HeapFree(GetProcessHeap(), 0, Adapters);
2749 WineD3D_ReleaseFakeGLContext();
2752 ret = initPixelFormats(&Adapters[0].gl_info);
2754 ERR("Failed to init gl formats\n");
2755 HeapFree(GetProcessHeap(), 0, Adapters);
2756 WineD3D_ReleaseFakeGLContext();
2760 hdc = pwglGetCurrentDC();
2762 ERR("Failed to get gl HDC\n");
2763 HeapFree(GetProcessHeap(), 0, Adapters);
2764 WineD3D_ReleaseFakeGLContext();
2768 Adapters[0].driver = "Display";
2769 Adapters[0].description = "Direct3D HAL";
2771 /* Use the VideoRamSize registry setting when set */
2772 if(wined3d_settings.emulated_textureram)
2773 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
2775 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
2776 Adapters[0].UsedTextureRam = 0;
2777 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
2779 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2780 DisplayDevice.cb = sizeof(DisplayDevice);
2781 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2782 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2783 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2785 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2786 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2788 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2789 cfgs = Adapters[0].cfgs;
2790 PUSH1(WGL_RED_BITS_ARB)
2791 PUSH1(WGL_GREEN_BITS_ARB)
2792 PUSH1(WGL_BLUE_BITS_ARB)
2793 PUSH1(WGL_ALPHA_BITS_ARB)
2794 PUSH1(WGL_DEPTH_BITS_ARB)
2795 PUSH1(WGL_STENCIL_BITS_ARB)
2797 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2798 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
2803 /* Cache the pixel format */
2804 cfgs->iPixelFormat = iPixelFormat;
2805 cfgs->redSize = values[0];
2806 cfgs->greenSize = values[1];
2807 cfgs->blueSize = values[2];
2808 cfgs->alphaSize = values[3];
2809 cfgs->depthSize = values[4];
2810 cfgs->stencilSize = values[5];
2812 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);
2815 WineD3D_ReleaseFakeGLContext();
2817 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2818 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2822 TRACE("%d adapters successfully initialized\n", numAdapters);
2827 #undef GLINFO_LOCATION
2829 /**********************************************************
2830 * IWineD3D VTbl follows
2831 **********************************************************/
2833 const IWineD3DVtbl IWineD3D_Vtbl =
2836 IWineD3DImpl_QueryInterface,
2837 IWineD3DImpl_AddRef,
2838 IWineD3DImpl_Release,
2840 IWineD3DImpl_GetParent,
2841 IWineD3DImpl_GetAdapterCount,
2842 IWineD3DImpl_RegisterSoftwareDevice,
2843 IWineD3DImpl_GetAdapterMonitor,
2844 IWineD3DImpl_GetAdapterModeCount,
2845 IWineD3DImpl_EnumAdapterModes,
2846 IWineD3DImpl_GetAdapterDisplayMode,
2847 IWineD3DImpl_GetAdapterIdentifier,
2848 IWineD3DImpl_CheckDeviceMultiSampleType,
2849 IWineD3DImpl_CheckDepthStencilMatch,
2850 IWineD3DImpl_CheckDeviceType,
2851 IWineD3DImpl_CheckDeviceFormat,
2852 IWineD3DImpl_CheckDeviceFormatConversion,
2853 IWineD3DImpl_GetDeviceCaps,
2854 IWineD3DImpl_CreateDevice