user32: Remove unneeded casts.
[wine/winequartzdrv.git] / dlls / wined3d / directx.c
blob679dcbbab99ad1798d27b67f3e502f4e795512c5
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 DWORD version;
44 } EXTENSION_MAP[] = {
45 /* APPLE */
46 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
47 {"GL_APPLE_fence", APPLE_FENCE, 0 },
48 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
49 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
51 /* ATI */
52 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
53 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
54 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
55 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP, 0 },
57 /* ARB */
58 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
59 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
60 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
61 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
62 {"GL_ARB_imaging", ARB_IMAGING, 0 },
63 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
64 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
65 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
66 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
67 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
68 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
69 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
70 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
71 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
72 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
73 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
74 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
75 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
76 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
77 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, 0 },
78 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
79 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
80 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
81 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
82 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
83 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
85 /* EXT */
86 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
87 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
88 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
89 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
90 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
91 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
92 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
93 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
94 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
95 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
96 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
97 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
98 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
99 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
100 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
101 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
102 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
103 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
104 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
105 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
106 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
108 /* NV */
109 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
110 {"GL_NV_fence", NV_FENCE, 0 },
111 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
112 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
113 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
114 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
115 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
116 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
117 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
118 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
119 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
120 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
121 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
122 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
123 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
124 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
125 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
126 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
128 /* SGI */
129 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
132 /**********************************************************
133 * Utility functions follow
134 **********************************************************/
136 /* Adapters */
137 static int numAdapters = 0;
138 static struct WineD3DAdapter Adapters[1];
140 /* lookup tables */
141 int minLookup[MAX_LOOKUPS];
142 int maxLookup[MAX_LOOKUPS];
143 DWORD *stateLookup[MAX_LOOKUPS];
145 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
147 /* drawStridedSlow attributes */
148 glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
149 glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
150 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
151 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
152 glTexAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
155 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
156 * ie there is no GL Context - Get a default rendering context to enable the
157 * function query some info from GL
160 static int wined3d_fake_gl_context_ref = 0;
161 static BOOL wined3d_fake_gl_context_foreign;
162 static BOOL wined3d_fake_gl_context_available = FALSE;
163 static HDC wined3d_fake_gl_context_hdc = NULL;
164 static HWND wined3d_fake_gl_context_hwnd = NULL;
166 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
167 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
169 0, 0, &wined3d_fake_gl_context_cs,
170 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
171 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
172 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
174 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
176 static void WineD3D_ReleaseFakeGLContext(void) {
177 HGLRC glCtx;
179 EnterCriticalSection(&wined3d_fake_gl_context_cs);
181 if(!wined3d_fake_gl_context_available) {
182 TRACE_(d3d_caps)("context not available\n");
183 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
184 return;
187 glCtx = pwglGetCurrentContext();
189 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
190 if (0 == (--wined3d_fake_gl_context_ref) ) {
191 if(!wined3d_fake_gl_context_foreign && glCtx) {
192 TRACE_(d3d_caps)("destroying fake GL context\n");
193 pwglMakeCurrent(NULL, NULL);
194 pwglDeleteContext(glCtx);
196 if(wined3d_fake_gl_context_hdc)
197 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
198 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
199 if(wined3d_fake_gl_context_hwnd)
200 DestroyWindow(wined3d_fake_gl_context_hwnd);
201 wined3d_fake_gl_context_hwnd = NULL;
202 wined3d_fake_gl_context_available = FALSE;
204 assert(wined3d_fake_gl_context_ref >= 0);
206 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
209 static BOOL WineD3D_CreateFakeGLContext(void) {
210 HGLRC glCtx = NULL;
212 EnterCriticalSection(&wined3d_fake_gl_context_cs);
214 TRACE("getting context...\n");
215 if(wined3d_fake_gl_context_ref > 0) goto ret;
216 assert(0 == wined3d_fake_gl_context_ref);
218 wined3d_fake_gl_context_foreign = TRUE;
220 glCtx = pwglGetCurrentContext();
221 if (!glCtx) {
222 PIXELFORMATDESCRIPTOR pfd;
223 int iPixelFormat;
225 wined3d_fake_gl_context_foreign = FALSE;
227 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
228 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
229 if(!wined3d_fake_gl_context_hwnd) {
230 ERR("HWND creation failed!\n");
231 goto fail;
233 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
234 if(!wined3d_fake_gl_context_hdc) {
235 ERR("GetDC failed!\n");
236 goto fail;
239 /* PixelFormat selection */
240 ZeroMemory(&pfd, sizeof(pfd));
241 pfd.nSize = sizeof(pfd);
242 pfd.nVersion = 1;
243 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
244 pfd.iPixelType = PFD_TYPE_RGBA;
245 pfd.cColorBits = 32;
246 pfd.iLayerType = PFD_MAIN_PLANE;
248 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
249 if(!iPixelFormat) {
250 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
251 ERR("Can't find a suitable iPixelFormat\n");
252 goto fail;
254 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
255 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
257 /* Create a GL context */
258 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
259 if (!glCtx) {
260 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
261 goto fail;
264 /* Make it the current GL context */
265 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
266 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
267 goto fail;
271 ret:
272 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
273 wined3d_fake_gl_context_ref++;
274 wined3d_fake_gl_context_available = TRUE;
275 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
276 return TRUE;
277 fail:
278 if(wined3d_fake_gl_context_hdc)
279 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
280 wined3d_fake_gl_context_hdc = NULL;
281 if(wined3d_fake_gl_context_hwnd)
282 DestroyWindow(wined3d_fake_gl_context_hwnd);
283 wined3d_fake_gl_context_hwnd = NULL;
284 if(glCtx) pwglDeleteContext(glCtx);
285 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
286 return FALSE;
289 /* Adjust the amount of used texture memory */
290 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
291 UINT Adapter = D3DDevice->adapterNo;
293 Adapters[Adapter].UsedTextureRam += glram;
294 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
295 return Adapters[Adapter].UsedTextureRam;
298 /**********************************************************
299 * IUnknown parts follows
300 **********************************************************/
302 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
306 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
307 if (IsEqualGUID(riid, &IID_IUnknown)
308 || IsEqualGUID(riid, &IID_IWineD3DBase)
309 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
310 IUnknown_AddRef(iface);
311 *ppobj = This;
312 return S_OK;
314 *ppobj = NULL;
315 return E_NOINTERFACE;
318 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
319 IWineD3DImpl *This = (IWineD3DImpl *)iface;
320 ULONG refCount = InterlockedIncrement(&This->ref);
322 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
323 return refCount;
326 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
327 IWineD3DImpl *This = (IWineD3DImpl *)iface;
328 ULONG ref;
329 TRACE("(%p) : Releasing from %d\n", This, This->ref);
330 ref = InterlockedDecrement(&This->ref);
331 if (ref == 0) {
332 HeapFree(GetProcessHeap(), 0, This);
335 return ref;
338 /* Set the shader type for this device, depending on the given capabilities,
339 * the device type, and the user preferences in wined3d_settings */
341 static void select_shader_mode(
342 WineD3D_GL_Info *gl_info,
343 WINED3DDEVTYPE DeviceType,
344 int* ps_selected,
345 int* vs_selected) {
347 if (wined3d_settings.vs_mode == VS_NONE) {
348 *vs_selected = SHADER_NONE;
349 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
350 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
351 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
352 * shaders only on this card. */
353 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
354 *vs_selected = SHADER_ARB;
355 else
356 *vs_selected = SHADER_GLSL;
357 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
358 *vs_selected = SHADER_ARB;
359 } else {
360 *vs_selected = SHADER_NONE;
363 if (wined3d_settings.ps_mode == PS_NONE) {
364 *ps_selected = SHADER_NONE;
365 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
366 *ps_selected = SHADER_GLSL;
367 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
368 *ps_selected = SHADER_ARB;
369 } else {
370 *ps_selected = SHADER_NONE;
374 /** Select the number of report maximum shader constants based on the selected shader modes */
375 static void select_shader_max_constants(
376 int ps_selected_mode,
377 int vs_selected_mode,
378 WineD3D_GL_Info *gl_info) {
380 switch (vs_selected_mode) {
381 case SHADER_GLSL:
382 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
383 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
384 break;
385 case SHADER_ARB:
386 /* We have to subtract any other PARAMs that we might use in our shader programs.
387 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
388 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
389 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
390 break;
391 default:
392 gl_info->max_vshader_constantsF = 0;
393 break;
396 switch (ps_selected_mode) {
397 case SHADER_GLSL:
398 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
399 * In theory the texbem instruction may need one more shader constant too. But lets assume
400 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
401 * and lets not take away a uniform needlessly from all other shaders.
403 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
404 break;
405 case SHADER_ARB:
406 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
407 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
409 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
410 break;
411 default:
412 gl_info->max_pshader_constantsF = 0;
413 break;
417 /**********************************************************
418 * IWineD3D parts follows
419 **********************************************************/
421 #define GLINFO_LOCATION (*gl_info)
422 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
423 GLuint prog;
424 BOOL ret = FALSE;
425 const char *testcode =
426 "!!ARBvp1.0\n"
427 "PARAM C[66] = { program.env[0..65] };\n"
428 "ADDRESS A0;"
429 "ARL A0.x, 0.0;\n"
430 "MOV result.position, C[A0.x + 65];\n"
431 "END\n";
433 while(glGetError());
434 GL_EXTCALL(glGenProgramsARB(1, &prog));
435 if(!prog) {
436 ERR("Failed to create an ARB offset limit test program\n");
438 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
439 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
440 strlen(testcode), testcode));
441 if(glGetError() != 0) {
442 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
443 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
444 ret = TRUE;
445 } else TRACE("OpenGL implementation allows offsets > 63\n");
447 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
448 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
449 checkGLcall("ARB vp offset limit test cleanup\n");
451 return ret;
454 static DWORD ver_for_ext(GL_SupportedExt ext)
456 unsigned int i;
457 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
458 if(EXTENSION_MAP[i].extension == ext) {
459 return EXTENSION_MAP[i].version;
462 return 0;
465 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
466 const char *GL_Extensions = NULL;
467 const char *WGL_Extensions = NULL;
468 const char *gl_string = NULL;
469 const char *gl_string_cursor = NULL;
470 GLint gl_max;
471 GLfloat gl_floatv[2];
472 int major = 1, minor = 0;
473 BOOL return_value = TRUE;
474 unsigned i;
475 HDC hdc;
476 unsigned int vidmem=0;
478 TRACE_(d3d_caps)("(%p)\n", gl_info);
480 ENTER_GL();
482 gl_string = (const char *) glGetString(GL_RENDERER);
483 if (NULL == gl_string)
484 gl_string = "None";
485 strcpy(gl_info->gl_renderer, gl_string);
487 gl_string = (const char *) glGetString(GL_VENDOR);
488 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
489 if (gl_string != NULL) {
490 /* Fill in the GL vendor */
491 if (strstr(gl_string, "NVIDIA")) {
492 gl_info->gl_vendor = VENDOR_NVIDIA;
493 } else if (strstr(gl_string, "ATI")) {
494 gl_info->gl_vendor = VENDOR_ATI;
495 } else if (strstr(gl_string, "Intel(R)") ||
496 strstr(gl_info->gl_renderer, "Intel(R)") ||
497 strstr(gl_string, "Intel Inc.")) {
498 gl_info->gl_vendor = VENDOR_INTEL;
499 } else if (strstr(gl_string, "Mesa")) {
500 gl_info->gl_vendor = VENDOR_MESA;
501 } else {
502 gl_info->gl_vendor = VENDOR_WINE;
504 } else {
505 gl_info->gl_vendor = VENDOR_WINE;
509 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
511 /* Parse the GL_VERSION field into major and minor information */
512 gl_string = (const char *) glGetString(GL_VERSION);
513 if (gl_string != NULL) {
515 switch (gl_info->gl_vendor) {
516 case VENDOR_NVIDIA:
517 gl_string_cursor = strstr(gl_string, "NVIDIA");
518 if (!gl_string_cursor) {
519 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
520 break;
523 gl_string_cursor = strstr(gl_string_cursor, " ");
524 if (!gl_string_cursor) {
525 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
526 break;
529 while (*gl_string_cursor == ' ') {
530 ++gl_string_cursor;
533 if (!*gl_string_cursor) {
534 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
535 break;
538 major = atoi(gl_string_cursor);
539 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
540 ++gl_string_cursor;
543 if (*gl_string_cursor++ != '.') {
544 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
545 break;
548 minor = atoi(gl_string_cursor);
549 minor = major*100+minor;
550 major = 10;
552 break;
554 case VENDOR_ATI:
555 major = minor = 0;
556 gl_string_cursor = strchr(gl_string, '-');
557 if (gl_string_cursor) {
558 int error = 0;
559 gl_string_cursor++;
561 /* Check if version number is of the form x.y.z */
562 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
563 error = 1;
564 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
565 error = 1;
566 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
567 error = 1;
568 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
569 error = 1;
571 /* Mark version number as malformed */
572 if (error)
573 gl_string_cursor = 0;
576 if (!gl_string_cursor)
577 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
578 else {
579 major = *gl_string_cursor - '0';
580 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
582 break;
584 case VENDOR_INTEL:
585 /* Apple and Mesa version strings look differently, but both provide intel drivers */
586 if(strstr(gl_string, "APPLE")) {
587 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
588 * We only need the first part, and use the APPLE as identification
589 * "1.2 APPLE-1.4.56"
591 gl_string_cursor = gl_string;
592 major = atoi(gl_string_cursor);
593 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
594 ++gl_string_cursor;
597 if (*gl_string_cursor++ != '.') {
598 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
599 break;
602 minor = atoi(gl_string_cursor);
603 break;
606 case VENDOR_MESA:
607 gl_string_cursor = strstr(gl_string, "Mesa");
608 gl_string_cursor = strstr(gl_string_cursor, " ");
609 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
610 if (*gl_string_cursor) {
611 char tmp[16];
612 int cursor = 0;
614 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
615 tmp[cursor++] = *gl_string_cursor;
616 ++gl_string_cursor;
618 tmp[cursor] = 0;
619 major = atoi(tmp);
621 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
622 ++gl_string_cursor;
624 cursor = 0;
625 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
626 tmp[cursor++] = *gl_string_cursor;
627 ++gl_string_cursor;
629 tmp[cursor] = 0;
630 minor = atoi(tmp);
632 break;
634 default:
635 major = 0;
636 minor = 9;
638 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
639 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
642 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
645 * Initialize openGL extension related variables
646 * with Default values
648 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
649 gl_info->max_buffers = 1;
650 gl_info->max_textures = 1;
651 gl_info->max_texture_stages = 1;
652 gl_info->max_fragment_samplers = 1;
653 gl_info->max_vertex_samplers = 0;
654 gl_info->max_combined_samplers = 0;
655 gl_info->max_sampler_stages = 1;
656 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
657 gl_info->ps_arb_max_temps = 0;
658 gl_info->ps_arb_max_instructions = 0;
659 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
660 gl_info->vs_arb_max_temps = 0;
661 gl_info->vs_arb_max_instructions = 0;
662 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
663 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
664 gl_info->vs_glsl_constantsF = 0;
665 gl_info->ps_glsl_constantsF = 0;
666 gl_info->vs_arb_constantsF = 0;
667 gl_info->ps_arb_constantsF = 0;
669 /* Retrieve opengl defaults */
670 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
671 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
672 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
674 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
675 gl_info->max_lights = gl_max;
676 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
678 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
679 gl_info->max_texture_size = gl_max;
680 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
682 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
683 gl_info->max_pointsizemin = gl_floatv[0];
684 gl_info->max_pointsize = gl_floatv[1];
685 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
687 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
688 gl_info->max_aux_buffers = gl_max;
689 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
691 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
692 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
693 TRACE_(d3d_caps)("GL_Extensions reported:\n");
695 if (NULL == GL_Extensions) {
696 ERR(" GL_Extensions returns NULL\n");
697 } else {
698 while (*GL_Extensions != 0x00) {
699 const char *Start;
700 char ThisExtn[256];
701 size_t len;
703 while (isspace(*GL_Extensions)) GL_Extensions++;
704 Start = GL_Extensions;
705 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
706 GL_Extensions++;
709 len = GL_Extensions - Start;
710 if (len == 0 || len >= sizeof(ThisExtn))
711 continue;
713 memcpy(ThisExtn, Start, len);
714 ThisExtn[len] = '\0';
715 TRACE_(d3d_caps)("- %s\n", ThisExtn);
717 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
718 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
719 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
720 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
721 break;
725 /* Now work out what GL support this card really has */
726 #define USE_GL_FUNC(type, pfn, ext, replace) { \
727 DWORD ver = ver_for_ext(ext); \
728 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
729 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
730 else gl_info->pfn = NULL; \
732 GL_EXT_FUNCS_GEN;
733 #undef USE_GL_FUNC
735 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
736 WGL_EXT_FUNCS_GEN;
737 #undef USE_GL_FUNC
739 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
740 * loading the functions, otherwise the code above will load the extension entry points instead of the
741 * core functions, which may not work
743 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
744 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
745 EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
746 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
747 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
751 if (gl_info->supported[APPLE_FENCE]) {
752 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
753 * The apple extension interacts with some other apple exts. Disable the NV
754 * extension if the apple one is support to prevent confusion in other parts
755 * of the code
757 gl_info->supported[NV_FENCE] = FALSE;
759 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
760 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
761 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
763 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
764 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
765 * Won't occur in any real world situation though
767 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
769 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
770 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
771 gl_info->max_buffers = gl_max;
772 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
774 if (gl_info->supported[ARB_MULTITEXTURE]) {
775 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
776 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
777 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
779 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
780 GLint tmp;
781 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
782 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
783 } else {
784 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
786 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
788 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
789 GLint tmp;
790 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
791 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
792 } else {
793 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
795 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
797 if (gl_info->supported[ARB_VERTEX_SHADER]) {
798 GLint tmp;
799 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
800 gl_info->max_vertex_samplers = tmp;
801 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
802 gl_info->max_combined_samplers = tmp;
804 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
805 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
806 * an issue because then the sampler setup only depends on the two shaders. If a pixel
807 * shader is used with fixed function vertex processing we're fine too because fixed function
808 * vertex processing doesn't use any samplers. If fixed function fragment processing is
809 * used we have to make sure that all vertex sampler setups are valid together with all
810 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
811 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
812 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
813 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
814 * a fixed function pipeline anymore.
816 * So this is just a check to check that our assumption holds true. If not, write a warning
817 * and reduce the number of vertex samplers or propably disable vertex texture fetch.
819 if(gl_info->max_vertex_samplers &&
820 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
821 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
822 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
823 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
824 if( gl_info->max_combined_samplers > MAX_TEXTURES )
825 gl_info->max_vertex_samplers =
826 gl_info->max_combined_samplers - MAX_TEXTURES;
827 else
828 gl_info->max_vertex_samplers = 0;
830 } else {
831 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
833 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
834 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
836 if (gl_info->supported[ARB_VERTEX_BLEND]) {
837 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
838 gl_info->max_blends = gl_max;
839 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
841 if (gl_info->supported[EXT_TEXTURE3D]) {
842 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
843 gl_info->max_texture3d_size = gl_max;
844 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
846 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
847 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
848 gl_info->max_anisotropy = gl_max;
849 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
851 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
852 gl_info->ps_arb_version = PS_VERSION_11;
853 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
854 gl_info->ps_arb_constantsF = gl_max;
855 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
856 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
857 gl_info->ps_arb_max_temps = gl_max;
858 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
859 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
860 gl_info->ps_arb_max_instructions = gl_max;
861 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
863 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
864 gl_info->vs_arb_version = VS_VERSION_11;
865 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
866 gl_info->vs_arb_constantsF = gl_max;
867 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
868 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
869 gl_info->vs_arb_max_temps = gl_max;
870 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
871 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
872 gl_info->vs_arb_max_instructions = gl_max;
873 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
875 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
877 if (gl_info->supported[ARB_VERTEX_SHADER]) {
878 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
879 gl_info->vs_glsl_constantsF = gl_max / 4;
880 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
882 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
883 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
884 gl_info->ps_glsl_constantsF = gl_max / 4;
885 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
886 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
887 gl_info->max_glsl_varyings = gl_max;
888 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
890 if (gl_info->supported[EXT_VERTEX_SHADER]) {
891 gl_info->vs_ati_version = VS_VERSION_11;
893 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
894 gl_info->vs_nv_version = VS_VERSION_30;
895 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
896 gl_info->vs_nv_version = VS_VERSION_20;
897 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
898 gl_info->vs_nv_version = VS_VERSION_11;
899 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
900 gl_info->vs_nv_version = VS_VERSION_10;
902 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
903 gl_info->ps_nv_version = PS_VERSION_30;
904 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
905 gl_info->ps_nv_version = PS_VERSION_20;
907 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
908 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
909 * This saves a few redundant glDisable calls
911 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
915 checkGLcall("extension detection\n");
917 /* In some cases the number of texture stages can be larger than the number
918 * of samplers. The GF4 for example can use only 2 samplers (no fragment
919 * shaders), but 8 texture stages (register combiners). */
920 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
922 /* We can only use ORM_FBO when the hardware supports it. */
923 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
924 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
925 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
928 /* MRTs are currently only supported when FBOs are used. */
929 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
930 gl_info->max_buffers = 1;
933 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
934 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
935 * in case of the latest videocards in the number of pixel/vertex pipelines.
937 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
938 * rendering. Various games use this information to get a rough estimation of the features of the card
939 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
940 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
941 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
942 * not the PCI id.
944 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
945 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
946 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
947 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
948 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
949 * is used for rendering which is not always the case). This would work but it is not very portable. Second
950 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
951 * is limited.
953 * As said most games only use the PCI id to get an indication of the capabilities of the card.
954 * It doesn't really matter if the given id is the correct one if we return the id of a card with
955 * similar 3d features.
957 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
958 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
959 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
960 * won't pass we return a default card. This way is better than maintaining a full card database as even
961 * without a full database we can return a card with similar features. Second the size of the database
962 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
963 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
964 * to distinguishes between different models from that family.
966 * The code also selects a default amount of video memory which we will use for an estimation of the amount
967 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
968 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
969 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
970 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
971 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
972 * memory behind our backs if really needed.
973 * Note that the amount of video memory can be overruled using a registry setting.
975 switch (gl_info->gl_vendor) {
976 case VENDOR_NVIDIA:
977 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
978 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
980 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
981 /* Geforce8 - highend */
982 if (strstr(gl_info->gl_renderer, "8800")) {
983 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
984 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
986 /* Geforce8 - midend mobile */
987 else if(strstr(gl_info->gl_renderer, "8600 M")) {
988 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
989 vidmem = 512;
991 /* Geforce8 - midend */
992 else if(strstr(gl_info->gl_renderer, "8600") ||
993 strstr(gl_info->gl_renderer, "8700"))
995 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
996 vidmem = 256;
998 /* Geforce8 - lowend */
999 else if(strstr(gl_info->gl_renderer, "8300") ||
1000 strstr(gl_info->gl_renderer, "8400") ||
1001 strstr(gl_info->gl_renderer, "8500"))
1003 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1004 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1006 /* Geforce7 - highend */
1007 else if(strstr(gl_info->gl_renderer, "7800") ||
1008 strstr(gl_info->gl_renderer, "7900") ||
1009 strstr(gl_info->gl_renderer, "7950") ||
1010 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1011 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1013 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1014 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1016 /* Geforce7 midend */
1017 else if(strstr(gl_info->gl_renderer, "7600") ||
1018 strstr(gl_info->gl_renderer, "7700")) {
1019 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1020 vidmem = 256; /* The 7600 uses 256-512MB */
1021 /* Geforce7 lower medium */
1022 } else if(strstr(gl_info->gl_renderer, "7400")) {
1023 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1024 vidmem = 256; /* The 7400 uses 256-512MB */
1026 /* Geforce7 lowend */
1027 else if(strstr(gl_info->gl_renderer, "7300")) {
1028 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1029 vidmem = 256; /* Mac Pros with this card have 256 MB */
1031 /* Geforce6 highend */
1032 else if(strstr(gl_info->gl_renderer, "6800"))
1034 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1035 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1037 /* Geforce6 - midend */
1038 else if(strstr(gl_info->gl_renderer, "6600") ||
1039 strstr(gl_info->gl_renderer, "6610") ||
1040 strstr(gl_info->gl_renderer, "6700"))
1042 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1043 vidmem = 128; /* A 6600GT has 128-256MB */
1045 /* Geforce6/7 lowend */
1046 else {
1047 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1048 vidmem = 64; /* */
1050 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1051 /* GeforceFX - highend */
1052 if (strstr(gl_info->gl_renderer, "5800") ||
1053 strstr(gl_info->gl_renderer, "5900") ||
1054 strstr(gl_info->gl_renderer, "5950") ||
1055 strstr(gl_info->gl_renderer, "Quadro FX"))
1057 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1058 vidmem = 256; /* 5800-5900 cards use 256MB */
1060 /* GeforceFX - midend */
1061 else if(strstr(gl_info->gl_renderer, "5600") ||
1062 strstr(gl_info->gl_renderer, "5650") ||
1063 strstr(gl_info->gl_renderer, "5700") ||
1064 strstr(gl_info->gl_renderer, "5750"))
1066 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1067 vidmem = 128; /* A 5600 uses 128-256MB */
1069 /* GeforceFX - lowend */
1070 else {
1071 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1072 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1074 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1075 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1076 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1077 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1079 else {
1080 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1081 vidmem = 64; /* Geforce3 cards have 64-128MB */
1083 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1084 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1085 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1086 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1088 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1089 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1090 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1092 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1093 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1094 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1096 else {
1097 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1098 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1100 } else {
1101 if (strstr(gl_info->gl_renderer, "TNT2")) {
1102 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1103 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1105 else {
1106 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1107 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1110 break;
1111 case VENDOR_ATI:
1112 if(WINE_D3D9_CAPABLE(gl_info)) {
1113 /* Radeon R6xx HD2900 - highend */
1114 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1115 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1116 vidmem = 512; /* HD2900 uses 512-1024MB */
1118 /* Radeon R6xx HD2600- midend */
1119 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1120 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1121 vidmem = 256; /* HD2600 uses 256-512MB */
1123 /* Radeon R6xx HD2300/HD2400 - lowend */
1124 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1125 strstr(gl_info->gl_renderer, "HD 2400"))
1127 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1128 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1130 /* Radeon R5xx */
1131 else if (strstr(gl_info->gl_renderer, "X1600") ||
1132 strstr(gl_info->gl_renderer, "X1650") ||
1133 strstr(gl_info->gl_renderer, "X1800") ||
1134 strstr(gl_info->gl_renderer, "X1900") ||
1135 strstr(gl_info->gl_renderer, "X1950"))
1137 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1138 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1140 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1141 else if(strstr(gl_info->gl_renderer, "X700") ||
1142 strstr(gl_info->gl_renderer, "X800") ||
1143 strstr(gl_info->gl_renderer, "X850") ||
1144 strstr(gl_info->gl_renderer, "X1300") ||
1145 strstr(gl_info->gl_renderer, "X1400") ||
1146 strstr(gl_info->gl_renderer, "X1450") ||
1147 strstr(gl_info->gl_renderer, "X1550"))
1149 gl_info->gl_card = CARD_ATI_RADEON_X700;
1150 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1152 /* Radeon R3xx */
1153 else {
1154 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1155 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1157 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1158 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1159 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1160 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1161 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1162 vidmem = 32; /* There are models with up to 64MB */
1163 } else {
1164 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1165 vidmem = 16; /* There are 16-32MB models */
1167 break;
1168 case VENDOR_INTEL:
1169 if (strstr(gl_info->gl_renderer, "GMA 950")) {
1170 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1171 gl_info->gl_card = CARD_INTEL_I945GM;
1172 vidmem = 64;
1173 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1174 gl_info->gl_card = CARD_INTEL_I915GM;
1175 } else if (strstr(gl_info->gl_renderer, "915G")) {
1176 gl_info->gl_card = CARD_INTEL_I915G;
1177 } else if (strstr(gl_info->gl_renderer, "865G")) {
1178 gl_info->gl_card = CARD_INTEL_I865G;
1179 } else if (strstr(gl_info->gl_renderer, "855G")) {
1180 gl_info->gl_card = CARD_INTEL_I855G;
1181 } else if (strstr(gl_info->gl_renderer, "830G")) {
1182 gl_info->gl_card = CARD_INTEL_I830G;
1183 } else {
1184 gl_info->gl_card = CARD_INTEL_I915G;
1186 break;
1187 case VENDOR_MESA:
1188 case VENDOR_WINE:
1189 default:
1190 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1191 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1192 * them a good generic choice.
1194 gl_info->gl_vendor = VENDOR_NVIDIA;
1195 if(WINE_D3D9_CAPABLE(gl_info))
1196 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1197 else if(WINE_D3D8_CAPABLE(gl_info))
1198 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1199 else if(WINE_D3D7_CAPABLE(gl_info))
1200 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1201 else if(WINE_D3D6_CAPABLE(gl_info))
1202 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1203 else
1204 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1206 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1208 /* If we have an estimate use it, else default to 64MB; */
1209 if(vidmem)
1210 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1211 else
1212 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1214 /* Load all the lookup tables
1215 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1216 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1217 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1219 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1220 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1223 for (i = 0; i < MAX_LOOKUPS; i++) {
1224 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1227 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1228 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1229 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1230 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1231 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1232 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1233 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1234 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1235 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1236 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1238 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1239 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1240 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1241 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1242 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1245 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1246 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1247 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1248 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1249 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1250 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1251 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1252 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1253 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1254 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1255 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1256 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1257 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1259 /* TODO: config lookups */
1261 /* Make sure there's an active HDC else the WGL extensions will fail */
1262 hdc = pwglGetCurrentDC();
1263 if (hdc) {
1264 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1265 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1267 if (NULL == WGL_Extensions) {
1268 ERR(" WGL_Extensions returns NULL\n");
1269 } else {
1270 while (*WGL_Extensions != 0x00) {
1271 const char *Start;
1272 char ThisExtn[256];
1273 size_t len;
1275 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1276 Start = WGL_Extensions;
1277 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1278 WGL_Extensions++;
1281 len = WGL_Extensions - Start;
1282 if (len == 0 || len >= sizeof(ThisExtn))
1283 continue;
1285 memcpy(ThisExtn, Start, len);
1286 ThisExtn[len] = '\0';
1287 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1289 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1290 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1291 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1296 LEAVE_GL();
1298 return return_value;
1300 #undef GLINFO_LOCATION
1302 /**********************************************************
1303 * IWineD3D implementation follows
1304 **********************************************************/
1306 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1307 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1309 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1310 return numAdapters;
1313 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1314 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1315 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1316 return WINED3D_OK;
1319 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1320 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1322 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1323 return NULL;
1326 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1327 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1330 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1331 of the same bpp but different resolutions */
1333 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1334 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1335 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1336 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1338 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1339 return 0;
1342 /* TODO: Store modes per adapter and read it from the adapter structure */
1343 if (Adapter == 0) { /* Display */
1344 int i = 0;
1345 int j = 0;
1347 if (!DEBUG_SINGLE_MODE) {
1348 DEVMODEW DevModeW;
1350 ZeroMemory(&DevModeW, sizeof(DevModeW));
1351 DevModeW.dmSize = sizeof(DevModeW);
1352 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1353 j++;
1354 switch (Format)
1356 case WINED3DFMT_UNKNOWN:
1357 /* This is for D3D8, do not enumerate P8 here */
1358 if (DevModeW.dmBitsPerPel == 32 ||
1359 DevModeW.dmBitsPerPel == 16) i++;
1360 break;
1361 case WINED3DFMT_X8R8G8B8:
1362 if (DevModeW.dmBitsPerPel == 32) i++;
1363 break;
1364 case WINED3DFMT_R5G6B5:
1365 if (DevModeW.dmBitsPerPel == 16) i++;
1366 break;
1367 case WINED3DFMT_P8:
1368 if (DevModeW.dmBitsPerPel == 8) i++;
1369 break;
1370 default:
1371 /* Skip other modes as they do not match the requested format */
1372 break;
1375 } else {
1376 i = 1;
1377 j = 1;
1380 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1381 return i;
1382 } else {
1383 FIXME_(d3d_caps)("Adapter not primary display\n");
1385 return 0;
1388 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1389 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1390 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1391 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1393 /* Validate the parameters as much as possible */
1394 if (NULL == pMode ||
1395 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1396 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1397 return WINED3DERR_INVALIDCALL;
1400 /* TODO: Store modes per adapter and read it from the adapter structure */
1401 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1402 DEVMODEW DevModeW;
1403 int ModeIdx = 0;
1404 int i = 0;
1405 int j = 0;
1407 ZeroMemory(&DevModeW, sizeof(DevModeW));
1408 DevModeW.dmSize = sizeof(DevModeW);
1410 /* If we are filtering to a specific format (D3D9), then need to skip
1411 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1412 just count through the ones with valid bit depths */
1413 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1414 switch (Format)
1416 case WINED3DFMT_UNKNOWN:
1417 /* This is D3D8. Do not enumerate P8 here */
1418 if (DevModeW.dmBitsPerPel == 32 ||
1419 DevModeW.dmBitsPerPel == 16) i++;
1420 break;
1421 case WINED3DFMT_X8R8G8B8:
1422 if (DevModeW.dmBitsPerPel == 32) i++;
1423 break;
1424 case WINED3DFMT_R5G6B5:
1425 if (DevModeW.dmBitsPerPel == 16) i++;
1426 break;
1427 case WINED3DFMT_P8:
1428 if (DevModeW.dmBitsPerPel == 8) i++;
1429 break;
1430 default:
1431 /* Modes that don't match what we support can get an early-out */
1432 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1433 return WINED3DERR_INVALIDCALL;
1437 if (i == 0) {
1438 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1439 return WINED3DERR_INVALIDCALL;
1441 ModeIdx = j - 1;
1443 /* Now get the display mode via the calculated index */
1444 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1445 pMode->Width = DevModeW.dmPelsWidth;
1446 pMode->Height = DevModeW.dmPelsHeight;
1447 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1448 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1449 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1451 if (Format == WINED3DFMT_UNKNOWN) {
1452 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1453 } else {
1454 pMode->Format = Format;
1456 } else {
1457 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1458 return WINED3DERR_INVALIDCALL;
1461 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1462 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1463 DevModeW.dmBitsPerPel);
1465 } else if (DEBUG_SINGLE_MODE) {
1466 /* Return one setting of the format requested */
1467 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1468 pMode->Width = 800;
1469 pMode->Height = 600;
1470 pMode->RefreshRate = 60;
1471 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1472 } else {
1473 FIXME_(d3d_caps)("Adapter not primary display\n");
1476 return WINED3D_OK;
1479 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1480 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1481 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1483 if (NULL == pMode ||
1484 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1485 return WINED3DERR_INVALIDCALL;
1488 if (Adapter == 0) { /* Display */
1489 int bpp = 0;
1490 DEVMODEW DevModeW;
1492 ZeroMemory(&DevModeW, sizeof(DevModeW));
1493 DevModeW.dmSize = sizeof(DevModeW);
1495 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1496 pMode->Width = DevModeW.dmPelsWidth;
1497 pMode->Height = DevModeW.dmPelsHeight;
1498 bpp = DevModeW.dmBitsPerPel;
1499 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1500 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1502 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1505 pMode->Format = pixelformat_for_depth(bpp);
1506 } else {
1507 FIXME_(d3d_caps)("Adapter not primary display\n");
1510 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1511 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1512 return WINED3D_OK;
1515 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1516 and fields being inserted in the middle, a new structure is used in place */
1517 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1518 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1519 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1521 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1523 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1524 return WINED3DERR_INVALIDCALL;
1527 /* Return the information requested */
1528 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1529 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1530 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1532 /* Note dx8 doesn't supply a DeviceName */
1533 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1534 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1535 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1536 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1537 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1538 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1539 *(pIdentifier->SubSysId) = 0;
1540 *(pIdentifier->Revision) = 0;
1542 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1543 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1544 *(pIdentifier->WHQLLevel) = 0;
1545 } else {
1546 *(pIdentifier->WHQLLevel) = 1;
1549 return WINED3D_OK;
1552 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1553 short redSize, greenSize, blueSize, alphaSize, colorBits;
1555 if(!cfg)
1556 return FALSE;
1558 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1559 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1560 return FALSE;
1563 if(cfg->redSize < redSize)
1564 return FALSE;
1566 if(cfg->greenSize < greenSize)
1567 return FALSE;
1569 if(cfg->blueSize < blueSize)
1570 return FALSE;
1572 if(cfg->alphaSize < alphaSize)
1573 return FALSE;
1575 return TRUE;
1578 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1579 short depthSize, stencilSize;
1581 if(!cfg)
1582 return FALSE;
1584 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1585 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1586 return FALSE;
1589 if(cfg->depthSize < depthSize)
1590 return FALSE;
1592 if(cfg->stencilSize < stencilSize)
1593 return FALSE;
1595 return TRUE;
1598 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1599 WINED3DFORMAT AdapterFormat,
1600 WINED3DFORMAT RenderTargetFormat,
1601 WINED3DFORMAT DepthStencilFormat) {
1602 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1603 int nCfgs;
1604 WineD3D_PixelFormat *cfgs;
1605 int it;
1607 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1608 This, Adapter,
1609 DeviceType, debug_d3ddevicetype(DeviceType),
1610 AdapterFormat, debug_d3dformat(AdapterFormat),
1611 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1612 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1614 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1615 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1616 return WINED3DERR_INVALIDCALL;
1619 cfgs = Adapters[Adapter].cfgs;
1620 nCfgs = Adapters[Adapter].nCfgs;
1621 for (it = 0; it < nCfgs; ++it) {
1622 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1623 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1624 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1625 return WINED3D_OK;
1629 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1631 return WINED3DERR_NOTAVAILABLE;
1634 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1635 WINED3DFORMAT SurfaceFormat,
1636 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1638 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1639 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1640 This,
1641 Adapter,
1642 DeviceType, debug_d3ddevicetype(DeviceType),
1643 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1644 Windowed,
1645 MultiSampleType,
1646 pQualityLevels);
1648 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1649 return WINED3DERR_INVALIDCALL;
1652 /* TODO: Store in Adapter structure */
1653 if (pQualityLevels != NULL) {
1654 static int s_single_shot = 0;
1655 if (!s_single_shot) {
1656 FIXME("Quality levels unsupported at present\n");
1657 s_single_shot = 1;
1659 *pQualityLevels = 1; /* Guess at a value! */
1662 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1663 return WINED3DERR_NOTAVAILABLE;
1666 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1667 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1669 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1670 int nCfgs = 0;
1671 WineD3D_PixelFormat *cfgs;
1672 int it;
1673 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1675 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1676 This,
1677 Adapter,
1678 CheckType, debug_d3ddevicetype(CheckType),
1679 DisplayFormat, debug_d3dformat(DisplayFormat),
1680 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1681 Windowed);
1683 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1684 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1685 return WINED3DERR_INVALIDCALL;
1688 cfgs = Adapters[Adapter].cfgs;
1689 nCfgs = Adapters[Adapter].nCfgs;
1690 for (it = 0; it < nCfgs; ++it) {
1691 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1692 hr = WINED3D_OK;
1693 TRACE_(d3d_caps)("OK\n");
1694 break ;
1698 if(hr != WINED3D_OK)
1699 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1701 if(hr != WINED3D_OK)
1702 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1704 return hr;
1707 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1708 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1709 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1710 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1711 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1712 This,
1713 Adapter,
1714 DeviceType, debug_d3ddevicetype(DeviceType),
1715 AdapterFormat, debug_d3dformat(AdapterFormat),
1716 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1717 RType, debug_d3dresourcetype(RType),
1718 CheckFormat, debug_d3dformat(CheckFormat));
1720 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1721 return WINED3DERR_INVALIDCALL;
1724 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1725 switch (CheckFormat) {
1726 /* Filtering not supported */
1727 case WINED3DFMT_R32F:
1728 case WINED3DFMT_A32B32G32R32F:
1729 TRACE_(d3d_caps)("[FAILED]\n");
1730 return WINED3DERR_NOTAVAILABLE;
1731 default:
1732 break;
1736 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1737 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1738 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1739 return WINED3DERR_NOTAVAILABLE;
1743 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1744 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1745 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1746 return WINED3DERR_NOTAVAILABLE;
1748 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1749 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1750 * app needing one of those formats, don't advertize them to avoid leading apps into
1751 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1752 * except of R32F.
1754 switch(CheckFormat) {
1755 case WINED3DFMT_P8:
1756 case WINED3DFMT_A4L4:
1757 case WINED3DFMT_R32F:
1758 case WINED3DFMT_R16F:
1759 case WINED3DFMT_X8L8V8U8:
1760 case WINED3DFMT_L6V5U5:
1761 case WINED3DFMT_G16R16:
1762 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1763 return WINED3DERR_NOTAVAILABLE;
1765 case WINED3DFMT_Q8W8V8U8:
1766 case WINED3DFMT_V16U16:
1767 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1768 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1769 return WINED3DERR_NOTAVAILABLE;
1771 break;
1773 case WINED3DFMT_V8U8:
1774 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1775 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1776 return WINED3DERR_NOTAVAILABLE;
1778 break;
1780 case WINED3DFMT_DXT1:
1781 case WINED3DFMT_DXT2:
1782 case WINED3DFMT_DXT3:
1783 case WINED3DFMT_DXT4:
1784 case WINED3DFMT_DXT5:
1785 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1786 * compressed texture results in an error. While the D3D refrast does
1787 * support s3tc volumes, at least the nvidia windows driver does not, so
1788 * we're free not to support this format.
1790 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1791 return WINED3DERR_NOTAVAILABLE;
1793 default:
1794 /* Do nothing, continue with checking the format below */
1795 break;
1798 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1799 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1800 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1801 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1802 if (!GL_LIMITS(vertex_samplers)) {
1803 TRACE_(d3d_caps)("[FAILED]\n");
1804 return WINED3DERR_NOTAVAILABLE;
1807 switch (CheckFormat) {
1808 case WINED3DFMT_A32B32G32R32F:
1809 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1810 TRACE_(d3d_caps)("[FAILED]\n");
1811 return WINED3DERR_NOTAVAILABLE;
1813 TRACE_(d3d_caps)("[OK]\n");
1814 return WINED3D_OK;
1816 default:
1817 TRACE_(d3d_caps)("[FAILED]\n");
1818 return WINED3DERR_NOTAVAILABLE;
1822 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1823 switch (CheckFormat) {
1824 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1825 * Windows supports only those 3, and enumerating the other formats confuses applications
1827 case WINED3DFMT_D24S8:
1828 case WINED3DFMT_D24X8:
1829 case WINED3DFMT_D16:
1830 TRACE_(d3d_caps)("[OK]\n");
1831 return WINED3D_OK;
1832 case WINED3DFMT_D16_LOCKABLE:
1833 case WINED3DFMT_D24FS8:
1834 case WINED3DFMT_D32F_LOCKABLE:
1835 case WINED3DFMT_D24X4S4:
1836 case WINED3DFMT_D15S1:
1837 case WINED3DFMT_D32:
1838 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1839 return WINED3DERR_NOTAVAILABLE;
1840 default:
1841 TRACE_(d3d_caps)("[FAILED]\n");
1842 return WINED3DERR_NOTAVAILABLE;
1844 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1845 switch (CheckFormat) {
1846 case WINED3DFMT_R8G8B8:
1847 case WINED3DFMT_A8R8G8B8:
1848 case WINED3DFMT_X8R8G8B8:
1849 case WINED3DFMT_R5G6B5:
1850 case WINED3DFMT_X1R5G5B5:
1851 case WINED3DFMT_A1R5G5B5:
1852 case WINED3DFMT_A4R4G4B4:
1853 case WINED3DFMT_R3G3B2:
1854 case WINED3DFMT_X4R4G4B4:
1855 case WINED3DFMT_A8B8G8R8:
1856 case WINED3DFMT_X8B8G8R8:
1857 case WINED3DFMT_P8:
1858 case WINED3DFMT_G16R16:
1859 TRACE_(d3d_caps)("[OK]\n");
1860 return WINED3D_OK;
1861 case WINED3DFMT_R16F:
1862 case WINED3DFMT_A16B16G16R16F:
1863 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1864 TRACE_(d3d_caps)("[FAILED]\n");
1865 return WINED3DERR_NOTAVAILABLE;
1867 TRACE_(d3d_caps)("[OK]\n");
1868 return WINED3D_OK;
1869 case WINED3DFMT_A32B32G32R32F:
1870 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1871 TRACE_(d3d_caps)("[FAILED]\n");
1872 return WINED3DERR_NOTAVAILABLE;
1874 TRACE_(d3d_caps)("[OK]\n");
1875 return WINED3D_OK;
1876 default:
1877 TRACE_(d3d_caps)("[FAILED]\n");
1878 return WINED3DERR_NOTAVAILABLE;
1880 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1881 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1882 switch (CheckFormat) {
1883 case WINED3DFMT_V8U8:
1884 TRACE_(d3d_caps)("[OK]\n");
1885 return WINED3D_OK;
1886 /* TODO: Other bump map formats */
1887 default:
1888 TRACE_(d3d_caps)("[FAILED]\n");
1889 return WINED3DERR_NOTAVAILABLE;
1892 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1893 switch (CheckFormat) {
1894 case WINED3DFMT_V8U8:
1895 TRACE_(d3d_caps)("[OK]\n");
1896 return WINED3D_OK;
1897 default:
1898 TRACE_(d3d_caps)("[FAILED]\n");
1899 return WINED3DERR_NOTAVAILABLE;
1902 TRACE_(d3d_caps)("[FAILED]\n");
1903 return WINED3DERR_NOTAVAILABLE;
1906 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1907 switch (CheckFormat) {
1908 case WINED3DFMT_DXT1:
1909 case WINED3DFMT_DXT2:
1910 case WINED3DFMT_DXT3:
1911 case WINED3DFMT_DXT4:
1912 case WINED3DFMT_DXT5:
1913 TRACE_(d3d_caps)("[OK]\n");
1914 return WINED3D_OK;
1915 default:
1916 break; /* Avoid compiler warnings */
1920 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1921 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1922 switch (CheckFormat) {
1923 case WINED3DFMT_A8R8G8B8:
1924 case WINED3DFMT_X8R8G8B8:
1925 case WINED3DFMT_A4R4G4B4:
1926 case WINED3DFMT_L8:
1927 case WINED3DFMT_A8L8:
1928 case WINED3DFMT_DXT1:
1929 case WINED3DFMT_DXT2:
1930 case WINED3DFMT_DXT3:
1931 case WINED3DFMT_DXT4:
1932 case WINED3DFMT_DXT5:
1933 TRACE_(d3d_caps)("[OK]\n");
1934 return WINED3D_OK;
1936 default:
1937 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1938 return WINED3DERR_NOTAVAILABLE;
1942 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1944 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1946 switch (CheckFormat) {
1947 case WINED3DFMT_R16F:
1948 case WINED3DFMT_A16B16G16R16F:
1949 if (!half_pixel_support) break;
1950 case WINED3DFMT_R32F:
1951 case WINED3DFMT_A32B32G32R32F:
1952 TRACE_(d3d_caps)("[OK]\n");
1953 return WINED3D_OK;
1954 default:
1955 break; /* Avoid compiler warnings */
1959 /* This format is nothing special and it is supported perfectly.
1960 * However, ati and nvidia driver on windows do not mark this format as
1961 * supported (tested with the dxCapsViewer) and pretending to
1962 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1963 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1964 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1966 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1967 TRACE_(d3d_caps)("[FAILED]\n");
1968 return WINED3DERR_NOTAVAILABLE;
1971 switch (CheckFormat) {
1973 /*****
1974 * supported: RGB(A) formats
1976 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1977 case WINED3DFMT_A8R8G8B8:
1978 case WINED3DFMT_X8R8G8B8:
1979 case WINED3DFMT_R5G6B5:
1980 case WINED3DFMT_X1R5G5B5:
1981 case WINED3DFMT_A1R5G5B5:
1982 case WINED3DFMT_A4R4G4B4:
1983 case WINED3DFMT_R3G3B2:
1984 case WINED3DFMT_A8:
1985 case WINED3DFMT_X4R4G4B4:
1986 case WINED3DFMT_A8B8G8R8:
1987 case WINED3DFMT_X8B8G8R8:
1988 case WINED3DFMT_A2R10G10B10:
1989 case WINED3DFMT_A2B10G10R10:
1990 case WINED3DFMT_G16R16:
1991 TRACE_(d3d_caps)("[OK]\n");
1992 return WINED3D_OK;
1994 /*****
1995 * supported: Palettized
1997 case WINED3DFMT_P8:
1998 TRACE_(d3d_caps)("[OK]\n");
1999 return WINED3D_OK;
2001 /*****
2002 * Supported: (Alpha)-Luminance
2004 case WINED3DFMT_L8:
2005 case WINED3DFMT_A8L8:
2006 case WINED3DFMT_A4L4:
2007 TRACE_(d3d_caps)("[OK]\n");
2008 return WINED3D_OK;
2010 /*****
2011 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2012 * GL_NV_texture_shader), but advertized to make apps happy.
2013 * Enable some because games often fail when they are not available
2014 * and are still playable even without bump mapping
2016 case WINED3DFMT_V8U8:
2017 case WINED3DFMT_V16U16:
2018 case WINED3DFMT_L6V5U5:
2019 case WINED3DFMT_X8L8V8U8:
2020 case WINED3DFMT_Q8W8V8U8:
2021 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
2022 return WINED3D_OK;
2024 /* Those are not advertized by the nvidia windows driver, and not
2025 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
2026 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
2027 * ARGB format if needed
2029 case WINED3DFMT_W11V11U10:
2030 case WINED3DFMT_A2W10V10U10:
2031 WARN_(d3d_caps)("[FAILED]\n");
2032 return WINED3DERR_NOTAVAILABLE;
2034 /*****
2035 * DXTN Formats: Handled above
2036 * WINED3DFMT_DXT1
2037 * WINED3DFMT_DXT2
2038 * WINED3DFMT_DXT3
2039 * WINED3DFMT_DXT4
2040 * WINED3DFMT_DXT5
2043 /*****
2044 * Odd formats - not supported
2046 case WINED3DFMT_VERTEXDATA:
2047 case WINED3DFMT_INDEX16:
2048 case WINED3DFMT_INDEX32:
2049 case WINED3DFMT_Q16W16V16U16:
2050 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2051 return WINED3DERR_NOTAVAILABLE;
2053 /*****
2054 * Float formats: Not supported right now
2056 case WINED3DFMT_G16R16F:
2057 case WINED3DFMT_G32R32F:
2058 case WINED3DFMT_CxV8U8:
2059 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2060 return WINED3DERR_NOTAVAILABLE;
2062 /* Not supported */
2063 case WINED3DFMT_A16B16G16R16:
2064 case WINED3DFMT_A8R3G3B2:
2065 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2066 return WINED3DERR_NOTAVAILABLE;
2068 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2069 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2070 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2071 * We can do instancing with all shader versions, but we need vertex shaders.
2073 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2074 * to enable instancing. WineD3D doesn't need that and just ignores it.
2076 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2078 case WINEMAKEFOURCC('I','N','S','T'):
2079 TRACE("ATI Instancing check hack\n");
2080 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2081 TRACE_(d3d_caps)("[OK]\n");
2082 return WINED3D_OK;
2083 } else {
2084 TRACE_(d3d_caps)("[FAILED]\n");
2085 return WINED3DERR_NOTAVAILABLE;
2088 default:
2089 break;
2092 TRACE_(d3d_caps)("[FAILED]\n");
2093 return WINED3DERR_NOTAVAILABLE;
2096 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2097 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2098 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2100 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2101 This,
2102 Adapter,
2103 DeviceType, debug_d3ddevicetype(DeviceType),
2104 SourceFormat, debug_d3dformat(SourceFormat),
2105 TargetFormat, debug_d3dformat(TargetFormat));
2106 return WINED3D_OK;
2109 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2110 subset of a D3DCAPS9 structure. However, it has to come via a void *
2111 as the d3d8 interface cannot import the d3d9 header */
2112 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2114 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2115 int vs_selected_mode;
2116 int ps_selected_mode;
2118 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2120 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2121 return WINED3DERR_INVALIDCALL;
2124 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2126 /* This function should *not* be modifying GL caps
2127 * TODO: move the functionality where it belongs */
2128 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2130 /* ------------------------------------------------
2131 The following fields apply to both d3d8 and d3d9
2132 ------------------------------------------------ */
2133 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2134 *pCaps->AdapterOrdinal = Adapter;
2136 *pCaps->Caps = 0;
2137 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2138 WINED3DCAPS2_FULLSCREENGAMMA |
2139 WINED3DCAPS2_DYNAMICTEXTURES;
2140 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2141 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2143 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2144 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2145 WINED3DPRESENT_INTERVAL_ONE;
2147 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2148 WINED3DCURSORCAPS_LOWRES;
2150 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2151 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2152 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2153 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2154 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2155 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2156 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2157 WINED3DDEVCAPS_PUREDEVICE |
2158 WINED3DDEVCAPS_HWRASTERIZATION |
2159 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2160 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2161 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2162 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2163 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2164 WINED3DDEVCAPS_RTPATCHES;
2166 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2167 WINED3DPMISCCAPS_CULLCCW |
2168 WINED3DPMISCCAPS_CULLCW |
2169 WINED3DPMISCCAPS_COLORWRITEENABLE |
2170 WINED3DPMISCCAPS_CLIPTLVERTS |
2171 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2172 WINED3DPMISCCAPS_MASKZ |
2173 WINED3DPMISCCAPS_BLENDOP;
2174 /* TODO:
2175 WINED3DPMISCCAPS_NULLREFERENCE
2176 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2177 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2178 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2179 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2180 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2181 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2183 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2184 #if 0
2185 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2186 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2187 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2188 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2189 #endif
2191 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2192 WINED3DPRASTERCAPS_PAT |
2193 WINED3DPRASTERCAPS_WFOG |
2194 WINED3DPRASTERCAPS_ZFOG |
2195 WINED3DPRASTERCAPS_FOGVERTEX |
2196 WINED3DPRASTERCAPS_FOGTABLE |
2197 WINED3DPRASTERCAPS_STIPPLE |
2198 WINED3DPRASTERCAPS_SUBPIXEL |
2199 WINED3DPRASTERCAPS_ZTEST |
2200 WINED3DPRASTERCAPS_SCISSORTEST |
2201 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2202 WINED3DPRASTERCAPS_DEPTHBIAS;
2204 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2205 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2206 WINED3DPRASTERCAPS_ZBIAS |
2207 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2209 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2210 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2212 /* FIXME Add:
2213 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2214 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2215 WINED3DPRASTERCAPS_ANTIALIASEDGES
2216 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2217 WINED3DPRASTERCAPS_WBUFFER */
2219 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2220 WINED3DPCMPCAPS_EQUAL |
2221 WINED3DPCMPCAPS_GREATER |
2222 WINED3DPCMPCAPS_GREATEREQUAL |
2223 WINED3DPCMPCAPS_LESS |
2224 WINED3DPCMPCAPS_LESSEQUAL |
2225 WINED3DPCMPCAPS_NEVER |
2226 WINED3DPCMPCAPS_NOTEQUAL;
2228 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2229 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2230 WINED3DPBLENDCAPS_DESTALPHA |
2231 WINED3DPBLENDCAPS_DESTCOLOR |
2232 WINED3DPBLENDCAPS_INVDESTALPHA |
2233 WINED3DPBLENDCAPS_INVDESTCOLOR |
2234 WINED3DPBLENDCAPS_INVSRCALPHA |
2235 WINED3DPBLENDCAPS_INVSRCCOLOR |
2236 WINED3DPBLENDCAPS_ONE |
2237 WINED3DPBLENDCAPS_SRCALPHA |
2238 WINED3DPBLENDCAPS_SRCALPHASAT |
2239 WINED3DPBLENDCAPS_SRCCOLOR |
2240 WINED3DPBLENDCAPS_ZERO;
2242 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
2243 WINED3DPBLENDCAPS_DESTCOLOR |
2244 WINED3DPBLENDCAPS_INVDESTALPHA |
2245 WINED3DPBLENDCAPS_INVDESTCOLOR |
2246 WINED3DPBLENDCAPS_INVSRCALPHA |
2247 WINED3DPBLENDCAPS_INVSRCCOLOR |
2248 WINED3DPBLENDCAPS_ONE |
2249 WINED3DPBLENDCAPS_SRCALPHA |
2250 WINED3DPBLENDCAPS_SRCCOLOR |
2251 WINED3DPBLENDCAPS_ZERO;
2252 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2253 * according to the glBlendFunc manpage
2255 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2256 * legacy settings for srcblend only
2259 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
2260 *pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
2261 *pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
2265 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2266 WINED3DPCMPCAPS_EQUAL |
2267 WINED3DPCMPCAPS_GREATER |
2268 WINED3DPCMPCAPS_GREATEREQUAL |
2269 WINED3DPCMPCAPS_LESS |
2270 WINED3DPCMPCAPS_LESSEQUAL |
2271 WINED3DPCMPCAPS_NEVER |
2272 WINED3DPCMPCAPS_NOTEQUAL;
2274 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2275 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2276 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2277 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2278 WINED3DPSHADECAPS_COLORFLATRGB |
2279 WINED3DPSHADECAPS_FOGFLAT |
2280 WINED3DPSHADECAPS_FOGGOURAUD |
2281 WINED3DPSHADECAPS_SPECULARFLATRGB;
2283 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2284 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2285 WINED3DPTEXTURECAPS_BORDER |
2286 WINED3DPTEXTURECAPS_MIPMAP |
2287 WINED3DPTEXTURECAPS_PROJECTED |
2288 WINED3DPTEXTURECAPS_PERSPECTIVE;
2290 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2291 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2292 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2295 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2296 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2297 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2298 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2301 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2302 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2303 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2304 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2308 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2309 WINED3DPTFILTERCAPS_MAGFPOINT |
2310 WINED3DPTFILTERCAPS_MINFLINEAR |
2311 WINED3DPTFILTERCAPS_MINFPOINT |
2312 WINED3DPTFILTERCAPS_MIPFLINEAR |
2313 WINED3DPTFILTERCAPS_MIPFPOINT |
2314 WINED3DPTFILTERCAPS_LINEAR |
2315 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2316 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2317 WINED3DPTFILTERCAPS_MIPLINEAR |
2318 WINED3DPTFILTERCAPS_MIPNEAREST |
2319 WINED3DPTFILTERCAPS_NEAREST;
2321 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2322 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2323 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2326 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2327 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2328 WINED3DPTFILTERCAPS_MAGFPOINT |
2329 WINED3DPTFILTERCAPS_MINFLINEAR |
2330 WINED3DPTFILTERCAPS_MINFPOINT |
2331 WINED3DPTFILTERCAPS_MIPFLINEAR |
2332 WINED3DPTFILTERCAPS_MIPFPOINT |
2333 WINED3DPTFILTERCAPS_LINEAR |
2334 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2335 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2336 WINED3DPTFILTERCAPS_MIPLINEAR |
2337 WINED3DPTFILTERCAPS_MIPNEAREST |
2338 WINED3DPTFILTERCAPS_NEAREST;
2340 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2341 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2342 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2344 } else
2345 *pCaps->CubeTextureFilterCaps = 0;
2347 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2348 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2349 WINED3DPTFILTERCAPS_MAGFPOINT |
2350 WINED3DPTFILTERCAPS_MINFLINEAR |
2351 WINED3DPTFILTERCAPS_MINFPOINT |
2352 WINED3DPTFILTERCAPS_MIPFLINEAR |
2353 WINED3DPTFILTERCAPS_MIPFPOINT |
2354 WINED3DPTFILTERCAPS_LINEAR |
2355 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2356 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2357 WINED3DPTFILTERCAPS_MIPLINEAR |
2358 WINED3DPTFILTERCAPS_MIPNEAREST |
2359 WINED3DPTFILTERCAPS_NEAREST;
2360 } else
2361 *pCaps->VolumeTextureFilterCaps = 0;
2363 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2364 WINED3DPTADDRESSCAPS_CLAMP |
2365 WINED3DPTADDRESSCAPS_WRAP;
2367 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2368 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2370 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2371 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2373 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2374 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2377 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2378 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2379 WINED3DPTADDRESSCAPS_CLAMP |
2380 WINED3DPTADDRESSCAPS_WRAP;
2381 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2382 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2384 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2385 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2387 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2388 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2390 } else
2391 *pCaps->VolumeTextureAddressCaps = 0;
2393 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2394 WINED3DLINECAPS_ZTEST;
2395 /* FIXME: Add
2396 WINED3DLINECAPS_BLEND
2397 WINED3DLINECAPS_ALPHACMP
2398 WINED3DLINECAPS_FOG */
2400 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2401 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2403 if(GL_SUPPORT(EXT_TEXTURE3D))
2404 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2405 else
2406 *pCaps->MaxVolumeExtent = 0;
2408 *pCaps->MaxTextureRepeat = 32768;
2409 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2410 *pCaps->MaxVertexW = 1.0;
2412 *pCaps->GuardBandLeft = 0;
2413 *pCaps->GuardBandTop = 0;
2414 *pCaps->GuardBandRight = 0;
2415 *pCaps->GuardBandBottom = 0;
2417 *pCaps->ExtentsAdjust = 0;
2419 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2420 WINED3DSTENCILCAPS_INCRSAT |
2421 WINED3DSTENCILCAPS_INVERT |
2422 WINED3DSTENCILCAPS_KEEP |
2423 WINED3DSTENCILCAPS_REPLACE |
2424 WINED3DSTENCILCAPS_ZERO;
2425 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2426 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2427 WINED3DSTENCILCAPS_INCR;
2429 if ( This->dxVersion > 8 &&
2430 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2431 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2432 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2435 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2437 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2438 WINED3DTEXOPCAPS_ADDSIGNED |
2439 WINED3DTEXOPCAPS_ADDSIGNED2X |
2440 WINED3DTEXOPCAPS_MODULATE |
2441 WINED3DTEXOPCAPS_MODULATE2X |
2442 WINED3DTEXOPCAPS_MODULATE4X |
2443 WINED3DTEXOPCAPS_SELECTARG1 |
2444 WINED3DTEXOPCAPS_SELECTARG2 |
2445 WINED3DTEXOPCAPS_DISABLE;
2447 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2448 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2449 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2450 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2451 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2452 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2453 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2454 WINED3DTEXOPCAPS_LERP |
2455 WINED3DTEXOPCAPS_SUBTRACT;
2457 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2458 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2459 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2460 WINED3DTEXOPCAPS_MULTIPLYADD |
2461 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2462 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2463 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2465 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2466 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2468 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2469 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2470 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2473 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2474 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2475 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2476 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2477 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2478 * and 3D textures. It also allows us to keep the code simpler by having texture
2479 * shaders constantly enabled.
2481 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2482 /* TODO: Luminance bump map? */
2484 #if 0
2485 /* FIXME: Add
2486 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2487 WINED3DTEXOPCAPS_PREMODULATE */
2488 #endif
2490 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2491 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2492 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2493 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2495 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2496 *pCaps->MaxVertexBlendMatrixIndex = 0;
2498 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2499 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2502 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2503 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2504 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2505 WINED3DVTXPCAPS_LOCALVIEWER |
2506 WINED3DVTXPCAPS_VERTEXFOG |
2507 WINED3DVTXPCAPS_TEXGEN;
2508 /* FIXME: Add
2509 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2511 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2512 *pCaps->MaxVertexIndex = 0xFFFFF;
2513 *pCaps->MaxStreams = MAX_STREAMS;
2514 *pCaps->MaxStreamStride = 1024;
2516 if (vs_selected_mode == SHADER_GLSL) {
2517 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2518 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2519 * vs_nv_version which is based on NV_vertex_program.
2520 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2521 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2522 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2523 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2524 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2525 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2526 else
2527 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2528 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2529 } else if (vs_selected_mode == SHADER_ARB) {
2530 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2531 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2532 } else {
2533 *pCaps->VertexShaderVersion = 0;
2534 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2537 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2539 if (ps_selected_mode == SHADER_GLSL) {
2540 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2541 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2542 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2543 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2544 * in max native instructions. Intel and others also offer the info in this extension but they
2545 * don't support GLSL (at least on Windows).
2547 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go up to 512. Assume that if the number
2548 * of instructions is 512 or less we have to do with ps2.0 hardware.
2549 * NOTE: ps3.0 hardware requires 512 or more instructions but ati and nvidia offer 'enough' (1024 vs 4096) on their most basic ps3.0 hardware.
2551 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2552 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2553 else
2554 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2555 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2556 * Direct3D minimum requirement.
2558 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2559 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2561 * The problem is that the refrast clamps temporary results in the shader to
2562 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2563 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2564 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2565 * offer a way to query this.
2567 *pCaps->PixelShader1xMaxValue = 8.0;
2568 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2569 } else if (ps_selected_mode == SHADER_ARB) {
2570 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2571 *pCaps->PixelShader1xMaxValue = 8.0;
2572 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2573 } else {
2574 *pCaps->PixelShaderVersion = 0;
2575 *pCaps->PixelShader1xMaxValue = 0.0;
2576 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2579 /* ------------------------------------------------
2580 The following fields apply to d3d9 only
2581 ------------------------------------------------ */
2582 if (This->dxVersion > 8) {
2583 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2584 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2585 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2586 *pCaps->MaxNpatchTessellationLevel = 0;
2587 *pCaps->MasterAdapterOrdinal = 0;
2588 *pCaps->AdapterOrdinalInGroup = 0;
2589 *pCaps->NumberOfAdaptersInGroup = 1;
2591 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2592 /* OpenGL supports all the formats below, perhaps not always
2593 * without conversion, but it supports them.
2594 * Further GLSL doesn't seem to have an official unsigned type so
2595 * don't advertise it yet as I'm not sure how we handle it.
2596 * We might need to add some clamping in the shader engine to
2597 * support it.
2598 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2599 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2600 WINED3DDTCAPS_UBYTE4N |
2601 WINED3DDTCAPS_SHORT2N |
2602 WINED3DDTCAPS_SHORT4N;
2603 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2604 *pCaps->DeclTypes |=
2605 WINED3DDTCAPS_FLOAT16_2 |
2606 WINED3DDTCAPS_FLOAT16_4;
2608 } else
2609 *pCaps->DeclTypes = 0;
2611 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2614 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2615 WINED3DPTFILTERCAPS_MAGFPOINT |
2616 WINED3DPTFILTERCAPS_MINFLINEAR |
2617 WINED3DPTFILTERCAPS_MAGFLINEAR;
2618 *pCaps->VertexTextureFilterCaps = 0;
2620 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2621 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2622 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2623 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2624 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2625 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2626 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2628 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2629 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2630 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2631 *pCaps->VS20Caps.Caps = 0;
2632 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2633 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2634 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2636 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2637 *pCaps->MaxVertexShader30InstructionSlots = 0;
2638 } else { /* VS 1.x */
2639 *pCaps->VS20Caps.Caps = 0;
2640 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2641 *pCaps->VS20Caps.NumTemps = 0;
2642 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2644 *pCaps->MaxVShaderInstructionsExecuted = 0;
2645 *pCaps->MaxVertexShader30InstructionSlots = 0;
2648 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2649 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2650 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2652 /* 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 */
2653 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2654 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2655 WINED3DPS20CAPS_PREDICATION |
2656 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2657 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2658 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2659 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2660 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2661 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2663 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2664 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2665 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2666 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2667 *pCaps->PS20Caps.Caps = 0;
2668 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2669 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2670 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
2671 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2673 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2674 *pCaps->MaxPixelShader30InstructionSlots = 0;
2675 } else { /* PS 1.x */
2676 *pCaps->PS20Caps.Caps = 0;
2677 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2678 *pCaps->PS20Caps.NumTemps = 0;
2679 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2680 *pCaps->PS20Caps.NumInstructionSlots = 0;
2682 *pCaps->MaxPShaderInstructionsExecuted = 0;
2683 *pCaps->MaxPixelShader30InstructionSlots = 0;
2687 return WINED3D_OK;
2690 static unsigned int glsl_program_key_hash(void *key) {
2691 glsl_program_key_t *k = (glsl_program_key_t *)key;
2693 unsigned int hash = k->vshader | k->pshader << 16;
2694 hash += ~(hash << 15);
2695 hash ^= (hash >> 10);
2696 hash += (hash << 3);
2697 hash ^= (hash >> 6);
2698 hash += ~(hash << 11);
2699 hash ^= (hash >> 16);
2701 return hash;
2704 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2705 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2706 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2708 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2711 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2712 and fields being inserted in the middle, a new structure is used in place */
2713 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2714 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2715 IUnknown *parent) {
2717 IWineD3DDeviceImpl *object = NULL;
2718 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2719 WINED3DDISPLAYMODE mode;
2720 int i;
2722 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2723 * number and create a device without a 3D adapter for 2D only operation.
2725 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2726 return WINED3DERR_INVALIDCALL;
2729 /* Create a WineD3DDevice object */
2730 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2731 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2732 TRACE("Created WineD3DDevice object @ %p\n", object);
2733 if (NULL == object) {
2734 return WINED3DERR_OUTOFVIDEOMEMORY;
2737 /* Set up initial COM information */
2738 object->lpVtbl = &IWineD3DDevice_Vtbl;
2739 object->ref = 1;
2740 object->wineD3D = iface;
2741 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2742 IWineD3D_AddRef(object->wineD3D);
2743 object->parent = parent;
2744 list_init(&object->resources);
2745 list_init(&object->shaders);
2747 if(This->dxVersion == 7) {
2748 object->surface_alignment = 8;
2749 } else {
2750 object->surface_alignment = 4;
2752 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2754 /* Set the state up as invalid until the device is fully created */
2755 object->state = WINED3DERR_DRIVERINTERNALERROR;
2757 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2758 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2760 /* Save the creation parameters */
2761 object->createParms.AdapterOrdinal = Adapter;
2762 object->createParms.DeviceType = DeviceType;
2763 object->createParms.hFocusWindow = hFocusWindow;
2764 object->createParms.BehaviorFlags = BehaviourFlags;
2766 /* Initialize other useful values */
2767 object->adapterNo = Adapter;
2768 object->devType = DeviceType;
2770 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2771 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2772 object->shader_backend = &glsl_shader_backend;
2773 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2774 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2775 object->shader_backend = &arb_program_shader_backend;
2776 } else {
2777 object->shader_backend = &none_shader_backend;
2780 /* set the state of the device to valid */
2781 object->state = WINED3D_OK;
2783 /* Get the initial screen setup for ddraw */
2784 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
2786 object->ddraw_width = mode.Width;
2787 object->ddraw_height = mode.Height;
2788 object->ddraw_format = mode.Format;
2790 for(i = 0; i < PATCHMAP_SIZE; i++) {
2791 list_init(&object->patches[i]);
2793 return WINED3D_OK;
2795 #undef GLINFO_LOCATION
2797 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2798 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2799 IUnknown_AddRef(This->parent);
2800 *pParent = This->parent;
2801 return WINED3D_OK;
2804 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2805 IUnknown* surfaceParent;
2806 TRACE("(%p) call back\n", pSurface);
2808 /* Now, release the parent, which will take care of cleaning up the surface for us */
2809 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2810 IUnknown_Release(surfaceParent);
2811 return IUnknown_Release(surfaceParent);
2814 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2815 IUnknown* volumeParent;
2816 TRACE("(%p) call back\n", pVolume);
2818 /* Now, release the parent, which will take care of cleaning up the volume for us */
2819 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2820 IUnknown_Release(volumeParent);
2821 return IUnknown_Release(volumeParent);
2824 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2825 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2826 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2827 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2829 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2830 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2831 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2832 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2833 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
2834 * the chance that other implementations support them is rather small since Win32 QuickTime uses
2835 * DirectDraw, not OpenGL.
2837 if(gl_info->supported[APPLE_FENCE] &&
2838 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2839 gl_info->supported[APPLE_FLUSH_RENDER] &&
2840 gl_info->supported[APPLE_YCBCR_422]) {
2841 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2842 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2843 return TRUE;
2844 } else {
2845 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2846 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2847 return FALSE;
2851 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2852 if(implementation_is_apple(gl_info)) {
2853 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
2854 * used it falls back to software. While the compiler can detect if the shader uses all declared
2855 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2856 * using relative addressing falls back to software.
2858 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2860 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2861 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2862 } else {
2863 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2864 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
2865 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
2868 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2869 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2870 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2871 * flag for this extension
2873 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
2874 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
2875 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
2876 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
2877 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2878 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
2879 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
2883 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
2884 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
2885 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
2886 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
2887 * according to the spec.
2889 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
2890 * makes the shader slower and eats instruction slots which should be available to the d3d app.
2892 if(gl_info->gl_vendor == VENDOR_INTEL) {
2893 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
2894 gl_info->set_texcoord_w = TRUE;
2899 void invalid_func(void *data) {
2900 ERR("Invalid vertex attribute function called\n");
2901 DebugBreak();
2904 #define GLINFO_LOCATION (Adapters[0].gl_info)
2906 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
2907 * the extension detection and are used in drawStridedSlow
2909 static void position_d3dcolor(void *data) {
2910 DWORD pos = *((DWORD *) data);
2912 FIXME("Add a test for fixed function position from d3dcolor type\n");
2913 glVertex4s(D3DCOLOR_B_R(pos),
2914 D3DCOLOR_B_G(pos),
2915 D3DCOLOR_B_B(pos),
2916 D3DCOLOR_B_A(pos));
2918 static void position_float4(void *data) {
2919 GLfloat *pos = (float *) data;
2921 if (pos[3] < eps && pos[3] > -eps)
2922 glVertex3fv(pos);
2923 else {
2924 float w = 1.0 / pos[3];
2926 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
2930 static void diffuse_d3dcolor(void *data) {
2931 DWORD diffuseColor = *((DWORD *) data);
2933 glColor4ub(D3DCOLOR_B_R(diffuseColor),
2934 D3DCOLOR_B_G(diffuseColor),
2935 D3DCOLOR_B_B(diffuseColor),
2936 D3DCOLOR_B_A(diffuseColor));
2939 static void specular_d3dcolor(void *data) {
2940 DWORD specularColor = *((DWORD *) data);
2942 GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
2943 D3DCOLOR_B_G(specularColor),
2944 D3DCOLOR_B_B(specularColor));
2946 static void warn_no_specular_func(void *data) {
2947 WARN("GL_EXT_secondary_color not supported\n");
2950 void fillGLAttribFuncs(WineD3D_GL_Info *gl_info) {
2951 position_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2952 position_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2953 position_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glVertex3fv;
2954 position_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) position_float4;
2955 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) position_d3dcolor;
2956 position_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
2957 position_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
2958 position_funcs[WINED3DDECLTYPE_SHORT4] = (void *) glVertex2sv;
2959 position_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
2960 position_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
2961 position_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
2962 position_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
2963 position_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
2964 position_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
2965 position_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
2966 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
2967 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
2969 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2970 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2971 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glColor3fv;
2972 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glColor4fv;
2973 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) diffuse_d3dcolor;
2974 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
2975 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
2976 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
2977 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) glColor4ubv;
2978 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
2979 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) glColor4sv;
2980 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
2981 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) glColor4usv;
2982 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
2983 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
2984 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
2985 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
2987 /* No 4 component entry points here */
2988 specular_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2989 specular_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2990 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2991 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) GL_EXTCALL(glSecondaryColor3fvEXT);
2992 } else {
2993 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
2995 specular_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) invalid_func;
2996 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2997 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) specular_d3dcolor;
2998 } else {
2999 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
3001 specular_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
3002 specular_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
3003 specular_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
3004 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
3005 specular_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3006 specular_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
3007 specular_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3008 specular_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
3009 specular_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3010 specular_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3011 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3012 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3014 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
3015 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
3017 normal_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
3018 normal_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
3019 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glNormal3fv;
3020 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glNormal3fv; /* Just ignore the 4th value */
3021 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) invalid_func;
3022 normal_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
3023 normal_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
3024 normal_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
3025 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
3026 normal_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3027 normal_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
3028 normal_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3029 normal_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
3030 normal_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3031 normal_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3032 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3033 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3036 #define PUSH1(att) attribs[nAttribs++] = (att);
3037 BOOL InitAdapters(void) {
3038 static HMODULE mod_gl;
3039 BOOL ret;
3040 int ps_selected_mode, vs_selected_mode;
3042 /* No need to hold any lock. The calling library makes sure only one thread calls
3043 * wined3d simultaneously
3045 if(numAdapters > 0) return TRUE;
3047 TRACE("Initializing adapters\n");
3049 if(!mod_gl) {
3050 #ifdef USE_WIN32_OPENGL
3051 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
3052 mod_gl = LoadLibraryA("opengl32.dll");
3053 if(!mod_gl) {
3054 ERR("Can't load opengl32.dll!\n");
3055 return FALSE;
3057 #else
3058 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
3059 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
3060 mod_gl = GetModuleHandleA("gdi32.dll");
3061 #endif
3064 /* Load WGL core functions from opengl32.dll */
3065 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
3066 WGL_FUNCS_GEN;
3067 #undef USE_WGL_FUNC
3069 if(!pwglGetProcAddress) {
3070 ERR("Unable to load wglGetProcAddress!\n");
3071 return FALSE;
3074 /* Dynamically load all GL core functions */
3075 GL_FUNCS_GEN;
3076 #undef USE_GL_FUNC
3078 /* For now only one default adapter */
3080 int iPixelFormat;
3081 int attribs[8];
3082 int values[8];
3083 int nAttribs = 0;
3084 int res;
3085 WineD3D_PixelFormat *cfgs;
3086 int attribute;
3087 DISPLAY_DEVICEW DisplayDevice;
3088 HDC hdc;
3090 TRACE("Initializing default adapter\n");
3091 Adapters[0].num = 0;
3092 Adapters[0].monitorPoint.x = -1;
3093 Adapters[0].monitorPoint.y = -1;
3095 if (!WineD3D_CreateFakeGLContext()) {
3096 ERR("Failed to get a gl context for default adapter\n");
3097 HeapFree(GetProcessHeap(), 0, Adapters);
3098 WineD3D_ReleaseFakeGLContext();
3099 return FALSE;
3102 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
3103 if(!ret) {
3104 ERR("Failed to initialize gl caps for default adapter\n");
3105 HeapFree(GetProcessHeap(), 0, Adapters);
3106 WineD3D_ReleaseFakeGLContext();
3107 return FALSE;
3109 ret = initPixelFormats(&Adapters[0].gl_info);
3110 if(!ret) {
3111 ERR("Failed to init gl formats\n");
3112 HeapFree(GetProcessHeap(), 0, Adapters);
3113 WineD3D_ReleaseFakeGLContext();
3114 return FALSE;
3117 hdc = pwglGetCurrentDC();
3118 if(!hdc) {
3119 ERR("Failed to get gl HDC\n");
3120 HeapFree(GetProcessHeap(), 0, Adapters);
3121 WineD3D_ReleaseFakeGLContext();
3122 return FALSE;
3125 Adapters[0].driver = "Display";
3126 Adapters[0].description = "Direct3D HAL";
3128 /* Use the VideoRamSize registry setting when set */
3129 if(wined3d_settings.emulated_textureram)
3130 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
3131 else
3132 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
3133 Adapters[0].UsedTextureRam = 0;
3134 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
3136 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
3137 DisplayDevice.cb = sizeof(DisplayDevice);
3138 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
3139 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
3140 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
3142 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
3143 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
3145 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
3146 cfgs = Adapters[0].cfgs;
3147 PUSH1(WGL_RED_BITS_ARB)
3148 PUSH1(WGL_GREEN_BITS_ARB)
3149 PUSH1(WGL_BLUE_BITS_ARB)
3150 PUSH1(WGL_ALPHA_BITS_ARB)
3151 PUSH1(WGL_DEPTH_BITS_ARB)
3152 PUSH1(WGL_STENCIL_BITS_ARB)
3154 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
3155 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
3157 if(!res)
3158 continue;
3160 /* Cache the pixel format */
3161 cfgs->iPixelFormat = iPixelFormat;
3162 cfgs->redSize = values[0];
3163 cfgs->greenSize = values[1];
3164 cfgs->blueSize = values[2];
3165 cfgs->alphaSize = values[3];
3166 cfgs->depthSize = values[4];
3167 cfgs->stencilSize = values[5];
3169 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);
3170 cfgs++;
3172 WineD3D_ReleaseFakeGLContext();
3174 fixup_extensions(&Adapters[0].gl_info);
3176 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
3177 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
3178 fillGLAttribFuncs(&Adapters[0].gl_info);
3179 init_type_lookup(&Adapters[0].gl_info);
3181 numAdapters = 1;
3182 TRACE("%d adapters successfully initialized\n", numAdapters);
3184 return TRUE;
3186 #undef PUSH1
3187 #undef GLINFO_LOCATION
3189 /**********************************************************
3190 * IWineD3D VTbl follows
3191 **********************************************************/
3193 const IWineD3DVtbl IWineD3D_Vtbl =
3195 /* IUnknown */
3196 IWineD3DImpl_QueryInterface,
3197 IWineD3DImpl_AddRef,
3198 IWineD3DImpl_Release,
3199 /* IWineD3D */
3200 IWineD3DImpl_GetParent,
3201 IWineD3DImpl_GetAdapterCount,
3202 IWineD3DImpl_RegisterSoftwareDevice,
3203 IWineD3DImpl_GetAdapterMonitor,
3204 IWineD3DImpl_GetAdapterModeCount,
3205 IWineD3DImpl_EnumAdapterModes,
3206 IWineD3DImpl_GetAdapterDisplayMode,
3207 IWineD3DImpl_GetAdapterIdentifier,
3208 IWineD3DImpl_CheckDeviceMultiSampleType,
3209 IWineD3DImpl_CheckDepthStencilMatch,
3210 IWineD3DImpl_CheckDeviceType,
3211 IWineD3DImpl_CheckDeviceFormat,
3212 IWineD3DImpl_CheckDeviceFormatConversion,
3213 IWineD3DImpl_GetDeviceCaps,
3214 IWineD3DImpl_CreateDevice