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