wined3d: Implement D3DFMT_G16R16.
[wine/multimedia.git] / dlls / wined3d / directx.c
blob7badb4c4ad35f1a45b13a6375753b06bbb289f4b
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_minmax", EXT_BLEND_MINMAX, 0 },
87 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
88 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
89 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
90 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
91 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
92 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
93 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
94 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
95 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
96 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
97 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
98 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
99 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
100 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
101 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
102 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
103 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
104 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
105 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
107 /* NV */
108 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
109 {"GL_NV_fence", NV_FENCE, 0 },
110 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
111 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
112 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
113 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
114 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
115 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
116 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
117 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
118 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
119 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
120 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
121 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
122 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
123 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
124 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
125 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
127 /* SGI */
128 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
131 /**********************************************************
132 * Utility functions follow
133 **********************************************************/
135 /* Adapters */
136 static int numAdapters = 0;
137 static struct WineD3DAdapter Adapters[1];
139 /* lookup tables */
140 int minLookup[MAX_LOOKUPS];
141 int maxLookup[MAX_LOOKUPS];
142 DWORD *stateLookup[MAX_LOOKUPS];
144 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
148 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
149 * ie there is no GL Context - Get a default rendering context to enable the
150 * function query some info from GL
153 static int wined3d_fake_gl_context_ref = 0;
154 static BOOL wined3d_fake_gl_context_foreign;
155 static BOOL wined3d_fake_gl_context_available = FALSE;
156 static HDC wined3d_fake_gl_context_hdc = NULL;
157 static HWND wined3d_fake_gl_context_hwnd = NULL;
159 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
160 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
162 0, 0, &wined3d_fake_gl_context_cs,
163 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
164 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
165 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
167 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
169 static void WineD3D_ReleaseFakeGLContext(void) {
170 HGLRC glCtx;
172 EnterCriticalSection(&wined3d_fake_gl_context_cs);
174 if(!wined3d_fake_gl_context_available) {
175 TRACE_(d3d_caps)("context not available\n");
176 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
177 return;
180 glCtx = pwglGetCurrentContext();
182 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
183 if (0 == (--wined3d_fake_gl_context_ref) ) {
184 if(!wined3d_fake_gl_context_foreign && glCtx) {
185 TRACE_(d3d_caps)("destroying fake GL context\n");
186 pwglMakeCurrent(NULL, NULL);
187 pwglDeleteContext(glCtx);
189 if(wined3d_fake_gl_context_hdc)
190 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
191 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
192 if(wined3d_fake_gl_context_hwnd)
193 DestroyWindow(wined3d_fake_gl_context_hwnd);
194 wined3d_fake_gl_context_hwnd = NULL;
195 wined3d_fake_gl_context_available = FALSE;
197 assert(wined3d_fake_gl_context_ref >= 0);
199 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
202 static BOOL WineD3D_CreateFakeGLContext(void) {
203 HGLRC glCtx = NULL;
205 EnterCriticalSection(&wined3d_fake_gl_context_cs);
207 TRACE("getting context...\n");
208 if(wined3d_fake_gl_context_ref > 0) goto ret;
209 assert(0 == wined3d_fake_gl_context_ref);
211 wined3d_fake_gl_context_foreign = TRUE;
213 glCtx = pwglGetCurrentContext();
214 if (!glCtx) {
215 PIXELFORMATDESCRIPTOR pfd;
216 int iPixelFormat;
218 wined3d_fake_gl_context_foreign = FALSE;
220 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
221 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
222 if(!wined3d_fake_gl_context_hwnd) {
223 ERR("HWND creation failed!\n");
224 goto fail;
226 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
227 if(!wined3d_fake_gl_context_hdc) {
228 ERR("GetDC failed!\n");
229 goto fail;
232 /* PixelFormat selection */
233 ZeroMemory(&pfd, sizeof(pfd));
234 pfd.nSize = sizeof(pfd);
235 pfd.nVersion = 1;
236 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
237 pfd.iPixelType = PFD_TYPE_RGBA;
238 pfd.cColorBits = 32;
239 pfd.iLayerType = PFD_MAIN_PLANE;
241 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
242 if(!iPixelFormat) {
243 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
244 ERR("Can't find a suitable iPixelFormat\n");
245 goto fail;
247 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
248 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
250 /* Create a GL context */
251 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
252 if (!glCtx) {
253 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
254 goto fail;
257 /* Make it the current GL context */
258 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
259 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
260 goto fail;
264 ret:
265 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
266 wined3d_fake_gl_context_ref++;
267 wined3d_fake_gl_context_available = TRUE;
268 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
269 return TRUE;
270 fail:
271 if(wined3d_fake_gl_context_hdc)
272 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
273 wined3d_fake_gl_context_hdc = NULL;
274 if(wined3d_fake_gl_context_hwnd)
275 DestroyWindow(wined3d_fake_gl_context_hwnd);
276 wined3d_fake_gl_context_hwnd = NULL;
277 if(glCtx) pwglDeleteContext(glCtx);
278 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
279 return FALSE;
282 /* Adjust the amount of used texture memory */
283 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
284 UINT Adapter = D3DDevice->adapterNo;
286 Adapters[Adapter].UsedTextureRam += glram;
287 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
288 return Adapters[Adapter].UsedTextureRam;
291 /**********************************************************
292 * IUnknown parts follows
293 **********************************************************/
295 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
299 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
300 if (IsEqualGUID(riid, &IID_IUnknown)
301 || IsEqualGUID(riid, &IID_IWineD3DBase)
302 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
303 IUnknown_AddRef(iface);
304 *ppobj = This;
305 return S_OK;
307 *ppobj = NULL;
308 return E_NOINTERFACE;
311 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
312 IWineD3DImpl *This = (IWineD3DImpl *)iface;
313 ULONG refCount = InterlockedIncrement(&This->ref);
315 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
316 return refCount;
319 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
320 IWineD3DImpl *This = (IWineD3DImpl *)iface;
321 ULONG ref;
322 TRACE("(%p) : Releasing from %d\n", This, This->ref);
323 ref = InterlockedDecrement(&This->ref);
324 if (ref == 0) {
325 HeapFree(GetProcessHeap(), 0, This);
328 return ref;
331 /* Set the shader type for this device, depending on the given capabilities,
332 * the device type, and the user preferences in wined3d_settings */
334 static void select_shader_mode(
335 WineD3D_GL_Info *gl_info,
336 WINED3DDEVTYPE DeviceType,
337 int* ps_selected,
338 int* vs_selected) {
340 if (wined3d_settings.vs_mode == VS_NONE) {
341 *vs_selected = SHADER_NONE;
342 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
343 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
344 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
345 * shaders only on this card. */
346 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
347 *vs_selected = SHADER_ARB;
348 else
349 *vs_selected = SHADER_GLSL;
350 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
351 *vs_selected = SHADER_ARB;
352 } else {
353 *vs_selected = SHADER_NONE;
356 if (wined3d_settings.ps_mode == PS_NONE) {
357 *ps_selected = SHADER_NONE;
358 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
359 *ps_selected = SHADER_GLSL;
360 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
361 *ps_selected = SHADER_ARB;
362 } else {
363 *ps_selected = SHADER_NONE;
367 /** Select the number of report maximum shader constants based on the selected shader modes */
368 static void select_shader_max_constants(
369 int ps_selected_mode,
370 int vs_selected_mode,
371 WineD3D_GL_Info *gl_info) {
373 switch (vs_selected_mode) {
374 case SHADER_GLSL:
375 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
376 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
377 break;
378 case SHADER_ARB:
379 /* We have to subtract any other PARAMs that we might use in our shader programs.
380 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
381 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
382 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
383 break;
384 default:
385 gl_info->max_vshader_constantsF = 0;
386 break;
389 switch (ps_selected_mode) {
390 case SHADER_GLSL:
391 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
392 * In theory the texbem instruction may need one more shader constant too. But lets assume
393 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
394 * and lets not take away a uniform needlessly from all other shaders.
396 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
397 break;
398 case SHADER_ARB:
399 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
400 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
402 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
403 break;
404 default:
405 gl_info->max_pshader_constantsF = 0;
406 break;
410 /**********************************************************
411 * IWineD3D parts follows
412 **********************************************************/
414 #define GLINFO_LOCATION (*gl_info)
415 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
416 GLuint prog;
417 BOOL ret = FALSE;
418 const char *testcode =
419 "!!ARBvp1.0\n"
420 "PARAM C[66] = { program.env[0..65] };\n"
421 "ADDRESS A0;"
422 "ARL A0.x, 0.0;\n"
423 "MOV result.position, C[A0.x + 65];\n"
424 "END\n";
426 while(glGetError());
427 GL_EXTCALL(glGenProgramsARB(1, &prog));
428 if(!prog) {
429 ERR("Failed to create an ARB offset limit test program\n");
431 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
432 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
433 strlen(testcode), testcode));
434 if(glGetError() != 0) {
435 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
436 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
437 ret = TRUE;
438 } else TRACE("OpenGL implementation allows offsets > 63\n");
440 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
441 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
442 checkGLcall("ARB vp offset limit test cleanup\n");
444 return ret;
447 static DWORD ver_for_ext(GL_SupportedExt ext)
449 unsigned int i;
450 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
451 if(EXTENSION_MAP[i].extension == ext) {
452 return EXTENSION_MAP[i].version;
455 return 0;
458 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
459 const char *GL_Extensions = NULL;
460 const char *WGL_Extensions = NULL;
461 const char *gl_string = NULL;
462 const char *gl_string_cursor = NULL;
463 GLint gl_max;
464 GLfloat gl_floatv[2];
465 int major = 1, minor = 0;
466 BOOL return_value = TRUE;
467 unsigned i;
468 HDC hdc;
469 unsigned int vidmem=0;
471 TRACE_(d3d_caps)("(%p)\n", gl_info);
473 ENTER_GL();
475 gl_string = (const char *) glGetString(GL_RENDERER);
476 if (NULL == gl_string)
477 gl_string = "None";
478 strcpy(gl_info->gl_renderer, gl_string);
480 gl_string = (const char *) glGetString(GL_VENDOR);
481 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
482 if (gl_string != NULL) {
483 /* Fill in the GL vendor */
484 if (strstr(gl_string, "NVIDIA")) {
485 gl_info->gl_vendor = VENDOR_NVIDIA;
486 } else if (strstr(gl_string, "ATI")) {
487 gl_info->gl_vendor = VENDOR_ATI;
488 } else if (strstr(gl_string, "Intel(R)") ||
489 strstr(gl_info->gl_renderer, "Intel(R)") ||
490 strstr(gl_string, "Intel Inc.")) {
491 gl_info->gl_vendor = VENDOR_INTEL;
492 } else if (strstr(gl_string, "Mesa")) {
493 gl_info->gl_vendor = VENDOR_MESA;
494 } else {
495 gl_info->gl_vendor = VENDOR_WINE;
497 } else {
498 gl_info->gl_vendor = VENDOR_WINE;
502 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
504 /* Parse the GL_VERSION field into major and minor information */
505 gl_string = (const char *) glGetString(GL_VERSION);
506 if (gl_string != NULL) {
508 switch (gl_info->gl_vendor) {
509 case VENDOR_NVIDIA:
510 gl_string_cursor = strstr(gl_string, "NVIDIA");
511 if (!gl_string_cursor) {
512 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
513 break;
516 gl_string_cursor = strstr(gl_string_cursor, " ");
517 if (!gl_string_cursor) {
518 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
519 break;
522 while (*gl_string_cursor == ' ') {
523 ++gl_string_cursor;
526 if (!*gl_string_cursor) {
527 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
528 break;
531 major = atoi(gl_string_cursor);
532 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
533 ++gl_string_cursor;
536 if (*gl_string_cursor++ != '.') {
537 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
538 break;
541 minor = atoi(gl_string_cursor);
542 minor = major*100+minor;
543 major = 10;
545 break;
547 case VENDOR_ATI:
548 major = minor = 0;
549 gl_string_cursor = strchr(gl_string, '-');
550 if (gl_string_cursor) {
551 int error = 0;
552 gl_string_cursor++;
554 /* Check if version number is of the form x.y.z */
555 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
556 error = 1;
557 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
558 error = 1;
559 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
560 error = 1;
561 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
562 error = 1;
564 /* Mark version number as malformed */
565 if (error)
566 gl_string_cursor = 0;
569 if (!gl_string_cursor)
570 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
571 else {
572 major = *gl_string_cursor - '0';
573 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
575 break;
577 case VENDOR_INTEL:
578 /* Apple and Mesa version strings look differently, but both provide intel drivers */
579 if(strstr(gl_string, "APPLE")) {
580 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
581 * We only need the first part, and use the APPLE as identification
582 * "1.2 APPLE-1.4.56"
584 gl_string_cursor = gl_string;
585 major = atoi(gl_string_cursor);
586 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
587 ++gl_string_cursor;
590 if (*gl_string_cursor++ != '.') {
591 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
592 break;
595 minor = atoi(gl_string_cursor);
596 break;
599 case VENDOR_MESA:
600 gl_string_cursor = strstr(gl_string, "Mesa");
601 gl_string_cursor = strstr(gl_string_cursor, " ");
602 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
603 if (*gl_string_cursor) {
604 char tmp[16];
605 int cursor = 0;
607 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
608 tmp[cursor++] = *gl_string_cursor;
609 ++gl_string_cursor;
611 tmp[cursor] = 0;
612 major = atoi(tmp);
614 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
615 ++gl_string_cursor;
617 cursor = 0;
618 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
619 tmp[cursor++] = *gl_string_cursor;
620 ++gl_string_cursor;
622 tmp[cursor] = 0;
623 minor = atoi(tmp);
625 break;
627 default:
628 major = 0;
629 minor = 9;
631 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
632 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
635 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
638 * Initialize openGL extension related variables
639 * with Default values
641 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
642 gl_info->max_buffers = 1;
643 gl_info->max_textures = 1;
644 gl_info->max_texture_stages = 1;
645 gl_info->max_fragment_samplers = 1;
646 gl_info->max_vertex_samplers = 0;
647 gl_info->max_combined_samplers = 0;
648 gl_info->max_sampler_stages = 1;
649 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
650 gl_info->ps_arb_max_temps = 0;
651 gl_info->ps_arb_max_instructions = 0;
652 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
653 gl_info->vs_arb_max_temps = 0;
654 gl_info->vs_arb_max_instructions = 0;
655 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
656 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
657 gl_info->vs_glsl_constantsF = 0;
658 gl_info->ps_glsl_constantsF = 0;
659 gl_info->vs_arb_constantsF = 0;
660 gl_info->ps_arb_constantsF = 0;
662 /* Retrieve opengl defaults */
663 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
664 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
665 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
667 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
668 gl_info->max_lights = gl_max;
669 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
671 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
672 gl_info->max_texture_size = gl_max;
673 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
675 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
676 gl_info->max_pointsizemin = gl_floatv[0];
677 gl_info->max_pointsize = gl_floatv[1];
678 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
680 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
681 gl_info->max_aux_buffers = gl_max;
682 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
684 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
685 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
686 TRACE_(d3d_caps)("GL_Extensions reported:\n");
688 if (NULL == GL_Extensions) {
689 ERR(" GL_Extensions returns NULL\n");
690 } else {
691 while (*GL_Extensions != 0x00) {
692 const char *Start;
693 char ThisExtn[256];
694 size_t len;
696 while (isspace(*GL_Extensions)) GL_Extensions++;
697 Start = GL_Extensions;
698 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
699 GL_Extensions++;
702 len = GL_Extensions - Start;
703 if (len == 0 || len >= sizeof(ThisExtn))
704 continue;
706 memcpy(ThisExtn, Start, len);
707 ThisExtn[len] = '\0';
708 TRACE_(d3d_caps)("- %s\n", ThisExtn);
710 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
711 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
712 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
713 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
714 break;
718 /* Now work out what GL support this card really has */
719 #define USE_GL_FUNC(type, pfn, ext, replace) { \
720 DWORD ver = ver_for_ext(ext); \
721 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
722 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
723 else gl_info->pfn = NULL; \
725 GL_EXT_FUNCS_GEN;
726 #undef USE_GL_FUNC
728 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
729 WGL_EXT_FUNCS_GEN;
730 #undef USE_GL_FUNC
732 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
733 * loading the functions, otherwise the code above will load the extension entry points instead of the
734 * core functions, which may not work
736 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
737 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
738 EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
739 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
740 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
744 if (gl_info->supported[APPLE_FENCE]) {
745 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
746 * The apple extension interacts with some other apple exts. Disable the NV
747 * extension if the apple one is support to prevent confusion in other parts
748 * of the code
750 gl_info->supported[NV_FENCE] = FALSE;
752 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
753 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
754 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
756 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
757 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
758 * Won't occur in any real world situation though
760 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
762 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
763 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
764 gl_info->max_buffers = gl_max;
765 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
767 if (gl_info->supported[ARB_MULTITEXTURE]) {
768 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
769 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
770 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
772 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
773 GLint tmp;
774 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
775 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
776 } else {
777 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
779 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
781 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
782 GLint tmp;
783 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
784 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
785 } else {
786 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
788 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
790 if (gl_info->supported[ARB_VERTEX_SHADER]) {
791 GLint tmp;
792 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
793 gl_info->max_vertex_samplers = tmp;
794 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
795 gl_info->max_combined_samplers = tmp;
797 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
798 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
799 * an issue because then the sampler setup only depends on the two shaders. If a pixel
800 * shader is used with fixed function vertex processing we're fine too because fixed function
801 * vertex processing doesn't use any samplers. If fixed function fragment processing is
802 * used we have to make sure that all vertex sampler setups are valid together with all
803 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
804 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
805 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
806 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
807 * a fixed function pipeline anymore.
809 * So this is just a check to check that our assumption holds true. If not, write a warning
810 * and reduce the number of vertex samplers or propably disable vertex texture fetch.
812 if(gl_info->max_vertex_samplers &&
813 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
814 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
815 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
816 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
817 if( gl_info->max_combined_samplers > MAX_TEXTURES )
818 gl_info->max_vertex_samplers =
819 gl_info->max_combined_samplers - MAX_TEXTURES;
820 else
821 gl_info->max_vertex_samplers = 0;
823 } else {
824 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
826 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
827 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
829 if (gl_info->supported[ARB_VERTEX_BLEND]) {
830 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
831 gl_info->max_blends = gl_max;
832 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
834 if (gl_info->supported[EXT_TEXTURE3D]) {
835 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
836 gl_info->max_texture3d_size = gl_max;
837 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
839 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
840 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
841 gl_info->max_anisotropy = gl_max;
842 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
844 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
845 gl_info->ps_arb_version = PS_VERSION_11;
846 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
847 gl_info->ps_arb_constantsF = gl_max;
848 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
849 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
850 gl_info->ps_arb_max_temps = gl_max;
851 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
852 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
853 gl_info->ps_arb_max_instructions = gl_max;
854 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
856 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
857 gl_info->vs_arb_version = VS_VERSION_11;
858 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
859 gl_info->vs_arb_constantsF = gl_max;
860 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
861 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
862 gl_info->vs_arb_max_temps = gl_max;
863 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
864 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
865 gl_info->vs_arb_max_instructions = gl_max;
866 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
868 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
870 if (gl_info->supported[ARB_VERTEX_SHADER]) {
871 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
872 gl_info->vs_glsl_constantsF = gl_max / 4;
873 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
875 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
876 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
877 gl_info->ps_glsl_constantsF = gl_max / 4;
878 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
879 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
880 gl_info->max_glsl_varyings = gl_max;
881 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
883 if (gl_info->supported[EXT_VERTEX_SHADER]) {
884 gl_info->vs_ati_version = VS_VERSION_11;
886 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
887 gl_info->vs_nv_version = VS_VERSION_30;
888 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
889 gl_info->vs_nv_version = VS_VERSION_20;
890 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
891 gl_info->vs_nv_version = VS_VERSION_11;
892 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
893 gl_info->vs_nv_version = VS_VERSION_10;
895 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
896 gl_info->ps_nv_version = PS_VERSION_30;
897 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
898 gl_info->ps_nv_version = PS_VERSION_20;
900 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
901 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
902 * This saves a few redundant glDisable calls
904 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
908 checkGLcall("extension detection\n");
910 /* In some cases the number of texture stages can be larger than the number
911 * of samplers. The GF4 for example can use only 2 samplers (no fragment
912 * shaders), but 8 texture stages (register combiners). */
913 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
915 /* We can only use ORM_FBO when the hardware supports it. */
916 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
917 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
918 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
921 /* MRTs are currently only supported when FBOs are used. */
922 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
923 gl_info->max_buffers = 1;
926 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
927 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
928 * in case of the latest videocards in the number of pixel/vertex pipelines.
930 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
931 * rendering. Various games use this information to get a rough estimation of the features of the card
932 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
933 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
934 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
935 * not the PCI id.
937 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
938 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
939 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
940 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
941 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
942 * is used for rendering which is not always the case). This would work but it is not very portable. Second
943 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
944 * is limited.
946 * As said most games only use the PCI id to get an indication of the capabilities of the card.
947 * It doesn't really matter if the given id is the correct one if we return the id of a card with
948 * similar 3d features.
950 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
951 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
952 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
953 * won't pass we return a default card. This way is better than maintaining a full card database as even
954 * without a full database we can return a card with similar features. Second the size of the database
955 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
956 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
957 * to distinguishes between different models from that family.
959 * The code also selects a default amount of video memory which we will use for an estimation of the amount
960 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
961 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
962 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
963 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
964 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
965 * memory behind our backs if really needed.
966 * Note that the amout of video memory can be overruled using a registry setting.
968 switch (gl_info->gl_vendor) {
969 case VENDOR_NVIDIA:
970 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
971 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
973 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
974 /* Geforce8 - highend */
975 if (strstr(gl_info->gl_renderer, "8800")) {
976 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
977 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
979 /* Geforce8 - midend mobile */
980 else if(strstr(gl_info->gl_renderer, "8600 M")) {
981 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
982 vidmem = 512;
984 /* Geforce8 - midend */
985 else if(strstr(gl_info->gl_renderer, "8600") ||
986 strstr(gl_info->gl_renderer, "8700"))
988 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
989 vidmem = 256;
991 /* Geforce8 - lowend */
992 else if(strstr(gl_info->gl_renderer, "8300") ||
993 strstr(gl_info->gl_renderer, "8400") ||
994 strstr(gl_info->gl_renderer, "8500"))
996 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
997 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
999 /* Geforce7 - highend */
1000 else if(strstr(gl_info->gl_renderer, "7800") ||
1001 strstr(gl_info->gl_renderer, "7900") ||
1002 strstr(gl_info->gl_renderer, "7950") ||
1003 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1004 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1006 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1007 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1009 /* Geforce7 midend */
1010 else if(strstr(gl_info->gl_renderer, "7600") ||
1011 strstr(gl_info->gl_renderer, "7700")) {
1012 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1013 vidmem = 256; /* The 7600 uses 256-512MB */
1014 /* Geforce7 lower medium */
1015 } else if(strstr(gl_info->gl_renderer, "7400")) {
1016 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1017 vidmem = 256; /* The 7400 uses 256-512MB */
1019 /* Geforce6 highend */
1020 else if(strstr(gl_info->gl_renderer, "6800"))
1022 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1023 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1025 /* Geforce6 - midend */
1026 else if(strstr(gl_info->gl_renderer, "6600") ||
1027 strstr(gl_info->gl_renderer, "6610") ||
1028 strstr(gl_info->gl_renderer, "6700"))
1030 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1031 vidmem = 128; /* A 6600GT has 128-256MB */
1033 /* Geforce6/7 lowend */
1034 else {
1035 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1036 vidmem = 64; /* */
1038 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1039 /* GeforceFX - highend */
1040 if (strstr(gl_info->gl_renderer, "5800") ||
1041 strstr(gl_info->gl_renderer, "5900") ||
1042 strstr(gl_info->gl_renderer, "5950") ||
1043 strstr(gl_info->gl_renderer, "Quadro FX"))
1045 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1046 vidmem = 256; /* 5800-5900 cards use 256MB */
1048 /* GeforceFX - midend */
1049 else if(strstr(gl_info->gl_renderer, "5600") ||
1050 strstr(gl_info->gl_renderer, "5650") ||
1051 strstr(gl_info->gl_renderer, "5700") ||
1052 strstr(gl_info->gl_renderer, "5750"))
1054 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1055 vidmem = 128; /* A 5600 uses 128-256MB */
1057 /* GeforceFX - lowend */
1058 else {
1059 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1060 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1062 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1063 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1064 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1065 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1067 else {
1068 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1069 vidmem = 64; /* Geforce3 cards have 64-128MB */
1071 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1072 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1073 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1074 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1076 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1077 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1078 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1080 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1081 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1082 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1084 else {
1085 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1086 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1088 } else {
1089 if (strstr(gl_info->gl_renderer, "TNT2")) {
1090 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1091 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1093 else {
1094 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1095 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1098 break;
1099 case VENDOR_ATI:
1100 if(WINE_D3D9_CAPABLE(gl_info)) {
1101 /* Radeon R6xx HD2900 - highend */
1102 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1103 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1104 vidmem = 512; /* HD2900 uses 512-1024MB */
1106 /* Radeon R6xx HD2600- midend */
1107 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1108 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1109 vidmem = 256; /* HD2600 uses 256-512MB */
1111 /* Radeon R6xx HD2300/HD2400 - lowend */
1112 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1113 strstr(gl_info->gl_renderer, "HD 2400"))
1115 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1116 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1118 /* Radeon R5xx */
1119 else if (strstr(gl_info->gl_renderer, "X1600") ||
1120 strstr(gl_info->gl_renderer, "X1650") ||
1121 strstr(gl_info->gl_renderer, "X1800") ||
1122 strstr(gl_info->gl_renderer, "X1900") ||
1123 strstr(gl_info->gl_renderer, "X1950"))
1125 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1126 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1128 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1129 else if(strstr(gl_info->gl_renderer, "X700") ||
1130 strstr(gl_info->gl_renderer, "X800") ||
1131 strstr(gl_info->gl_renderer, "X850") ||
1132 strstr(gl_info->gl_renderer, "X1300") ||
1133 strstr(gl_info->gl_renderer, "X1400") ||
1134 strstr(gl_info->gl_renderer, "X1450") ||
1135 strstr(gl_info->gl_renderer, "X1550"))
1137 gl_info->gl_card = CARD_ATI_RADEON_X700;
1138 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1140 /* Radeon R3xx */
1141 else {
1142 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1143 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1145 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1146 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1147 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1148 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1149 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1150 vidmem = 32; /* There are models with up to 64MB */
1151 } else {
1152 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1153 vidmem = 16; /* There are 16-32MB models */
1155 break;
1156 case VENDOR_INTEL:
1157 if (strstr(gl_info->gl_renderer, "GMA 950")) {
1158 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1159 gl_info->gl_card = CARD_INTEL_I945GM;
1160 vidmem = 64;
1161 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1162 gl_info->gl_card = CARD_INTEL_I915GM;
1163 } else if (strstr(gl_info->gl_renderer, "915G")) {
1164 gl_info->gl_card = CARD_INTEL_I915G;
1165 } else if (strstr(gl_info->gl_renderer, "865G")) {
1166 gl_info->gl_card = CARD_INTEL_I865G;
1167 } else if (strstr(gl_info->gl_renderer, "855G")) {
1168 gl_info->gl_card = CARD_INTEL_I855G;
1169 } else if (strstr(gl_info->gl_renderer, "830G")) {
1170 gl_info->gl_card = CARD_INTEL_I830G;
1171 } else {
1172 gl_info->gl_card = CARD_INTEL_I915G;
1174 break;
1175 case VENDOR_MESA:
1176 case VENDOR_WINE:
1177 default:
1178 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1179 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1180 * them a good generic choice.
1182 gl_info->gl_vendor = VENDOR_NVIDIA;
1183 if(WINE_D3D9_CAPABLE(gl_info))
1184 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1185 else if(WINE_D3D8_CAPABLE(gl_info))
1186 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1187 else if(WINE_D3D7_CAPABLE(gl_info))
1188 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1189 else if(WINE_D3D6_CAPABLE(gl_info))
1190 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1191 else
1192 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1194 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1196 /* If we have an estimate use it, else default to 64MB; */
1197 if(vidmem)
1198 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1199 else
1200 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1202 /* Load all the lookup tables
1203 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1204 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1205 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1207 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1208 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1211 for (i = 0; i < MAX_LOOKUPS; i++) {
1212 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1215 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1216 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1217 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1218 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1219 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1220 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1221 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1222 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1223 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1224 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1226 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1227 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1228 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1229 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1230 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1233 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1234 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1235 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1236 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1237 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1238 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1239 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1240 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1241 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1242 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1243 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1244 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1245 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1247 /* TODO: config lookups */
1249 /* Make sure there's an active HDC else the WGL extensions will fail */
1250 hdc = pwglGetCurrentDC();
1251 if (hdc) {
1252 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1253 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1255 if (NULL == WGL_Extensions) {
1256 ERR(" WGL_Extensions returns NULL\n");
1257 } else {
1258 while (*WGL_Extensions != 0x00) {
1259 const char *Start;
1260 char ThisExtn[256];
1261 size_t len;
1263 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1264 Start = WGL_Extensions;
1265 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1266 WGL_Extensions++;
1269 len = WGL_Extensions - Start;
1270 if (len == 0 || len >= sizeof(ThisExtn))
1271 continue;
1273 memcpy(ThisExtn, Start, len);
1274 ThisExtn[len] = '\0';
1275 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1277 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1278 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1279 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1284 LEAVE_GL();
1286 return return_value;
1288 #undef GLINFO_LOCATION
1290 /**********************************************************
1291 * IWineD3D implementation follows
1292 **********************************************************/
1294 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1295 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1297 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1298 return numAdapters;
1301 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1302 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1303 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1304 return WINED3D_OK;
1307 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1308 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1310 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1311 return NULL;
1314 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1315 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1318 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1319 of the same bpp but different resolutions */
1321 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1322 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1323 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1324 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1326 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1327 return 0;
1330 /* TODO: Store modes per adapter and read it from the adapter structure */
1331 if (Adapter == 0) { /* Display */
1332 int i = 0;
1333 int j = 0;
1335 if (!DEBUG_SINGLE_MODE) {
1336 DEVMODEW DevModeW;
1338 ZeroMemory(&DevModeW, sizeof(DevModeW));
1339 DevModeW.dmSize = sizeof(DevModeW);
1340 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1341 j++;
1342 switch (Format)
1344 case WINED3DFMT_UNKNOWN:
1345 /* This is for D3D8, do not enumerate P8 here */
1346 if (DevModeW.dmBitsPerPel == 32 ||
1347 DevModeW.dmBitsPerPel == 16) i++;
1348 break;
1349 case WINED3DFMT_X8R8G8B8:
1350 if (DevModeW.dmBitsPerPel == 32) i++;
1351 break;
1352 case WINED3DFMT_R5G6B5:
1353 if (DevModeW.dmBitsPerPel == 16) i++;
1354 break;
1355 case WINED3DFMT_P8:
1356 if (DevModeW.dmBitsPerPel == 8) i++;
1357 break;
1358 default:
1359 /* Skip other modes as they do not match the requested format */
1360 break;
1363 } else {
1364 i = 1;
1365 j = 1;
1368 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1369 return i;
1370 } else {
1371 FIXME_(d3d_caps)("Adapter not primary display\n");
1373 return 0;
1376 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1377 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1378 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1379 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1381 /* Validate the parameters as much as possible */
1382 if (NULL == pMode ||
1383 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1384 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1385 return WINED3DERR_INVALIDCALL;
1388 /* TODO: Store modes per adapter and read it from the adapter structure */
1389 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1390 DEVMODEW DevModeW;
1391 int ModeIdx = 0;
1392 int i = 0;
1393 int j = 0;
1395 ZeroMemory(&DevModeW, sizeof(DevModeW));
1396 DevModeW.dmSize = sizeof(DevModeW);
1398 /* If we are filtering to a specific format (D3D9), then need to skip
1399 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1400 just count through the ones with valid bit depths */
1401 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1402 switch (Format)
1404 case WINED3DFMT_UNKNOWN:
1405 /* This is D3D8. Do not enumerate P8 here */
1406 if (DevModeW.dmBitsPerPel == 32 ||
1407 DevModeW.dmBitsPerPel == 16) i++;
1408 break;
1409 case WINED3DFMT_X8R8G8B8:
1410 if (DevModeW.dmBitsPerPel == 32) i++;
1411 break;
1412 case WINED3DFMT_R5G6B5:
1413 if (DevModeW.dmBitsPerPel == 16) i++;
1414 break;
1415 case WINED3DFMT_P8:
1416 if (DevModeW.dmBitsPerPel == 8) i++;
1417 break;
1418 default:
1419 /* Modes that don't match what we support can get an early-out */
1420 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1421 return WINED3DERR_INVALIDCALL;
1425 if (i == 0) {
1426 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1427 return WINED3DERR_INVALIDCALL;
1429 ModeIdx = j - 1;
1431 /* Now get the display mode via the calculated index */
1432 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1433 pMode->Width = DevModeW.dmPelsWidth;
1434 pMode->Height = DevModeW.dmPelsHeight;
1435 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1436 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1437 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1439 if (Format == WINED3DFMT_UNKNOWN) {
1440 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1441 } else {
1442 pMode->Format = Format;
1444 } else {
1445 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1446 return WINED3DERR_INVALIDCALL;
1449 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1450 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1451 DevModeW.dmBitsPerPel);
1453 } else if (DEBUG_SINGLE_MODE) {
1454 /* Return one setting of the format requested */
1455 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1456 pMode->Width = 800;
1457 pMode->Height = 600;
1458 pMode->RefreshRate = 60;
1459 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1460 } else {
1461 FIXME_(d3d_caps)("Adapter not primary display\n");
1464 return WINED3D_OK;
1467 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1468 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1469 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1471 if (NULL == pMode ||
1472 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1473 return WINED3DERR_INVALIDCALL;
1476 if (Adapter == 0) { /* Display */
1477 int bpp = 0;
1478 DEVMODEW DevModeW;
1480 ZeroMemory(&DevModeW, sizeof(DevModeW));
1481 DevModeW.dmSize = sizeof(DevModeW);
1483 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1484 pMode->Width = DevModeW.dmPelsWidth;
1485 pMode->Height = DevModeW.dmPelsHeight;
1486 bpp = DevModeW.dmBitsPerPel;
1487 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1488 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1490 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1493 pMode->Format = pixelformat_for_depth(bpp);
1494 } else {
1495 FIXME_(d3d_caps)("Adapter not primary display\n");
1498 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1499 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1500 return WINED3D_OK;
1503 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1504 and fields being inserted in the middle, a new structure is used in place */
1505 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1506 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1507 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1509 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1511 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1512 return WINED3DERR_INVALIDCALL;
1515 /* Return the information requested */
1516 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1517 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1518 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1520 /* Note dx8 doesn't supply a DeviceName */
1521 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1522 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1523 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1524 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1525 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1526 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1527 *(pIdentifier->SubSysId) = 0;
1528 *(pIdentifier->Revision) = 0;
1530 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1531 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1532 *(pIdentifier->WHQLLevel) = 0;
1533 } else {
1534 *(pIdentifier->WHQLLevel) = 1;
1537 return WINED3D_OK;
1540 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1541 short redSize, greenSize, blueSize, alphaSize, colorBits;
1543 if(!cfg)
1544 return FALSE;
1546 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1547 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1548 return FALSE;
1551 if(cfg->redSize < redSize)
1552 return FALSE;
1554 if(cfg->greenSize < greenSize)
1555 return FALSE;
1557 if(cfg->blueSize < blueSize)
1558 return FALSE;
1560 if(cfg->alphaSize < alphaSize)
1561 return FALSE;
1563 return TRUE;
1566 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1567 short depthSize, stencilSize;
1569 if(!cfg)
1570 return FALSE;
1572 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1573 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1574 return FALSE;
1577 if(cfg->depthSize < depthSize)
1578 return FALSE;
1580 if(cfg->stencilSize < stencilSize)
1581 return FALSE;
1583 return TRUE;
1586 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1587 WINED3DFORMAT AdapterFormat,
1588 WINED3DFORMAT RenderTargetFormat,
1589 WINED3DFORMAT DepthStencilFormat) {
1590 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1591 int nCfgs;
1592 WineD3D_PixelFormat *cfgs;
1593 int it;
1595 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1596 This, Adapter,
1597 DeviceType, debug_d3ddevicetype(DeviceType),
1598 AdapterFormat, debug_d3dformat(AdapterFormat),
1599 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1600 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1602 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1603 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1604 return WINED3DERR_INVALIDCALL;
1607 cfgs = Adapters[Adapter].cfgs;
1608 nCfgs = Adapters[Adapter].nCfgs;
1609 for (it = 0; it < nCfgs; ++it) {
1610 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1611 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1612 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1613 return WINED3D_OK;
1617 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1619 return WINED3DERR_NOTAVAILABLE;
1622 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1623 WINED3DFORMAT SurfaceFormat,
1624 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1626 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1627 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1628 This,
1629 Adapter,
1630 DeviceType, debug_d3ddevicetype(DeviceType),
1631 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1632 Windowed,
1633 MultiSampleType,
1634 pQualityLevels);
1636 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1637 return WINED3DERR_INVALIDCALL;
1640 /* TODO: Store in Adapter structure */
1641 if (pQualityLevels != NULL) {
1642 static int s_single_shot = 0;
1643 if (!s_single_shot) {
1644 FIXME("Quality levels unsupported at present\n");
1645 s_single_shot = 1;
1647 *pQualityLevels = 1; /* Guess at a value! */
1650 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1651 return WINED3DERR_NOTAVAILABLE;
1654 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1655 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1657 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1658 int nCfgs = 0;
1659 WineD3D_PixelFormat *cfgs;
1660 int it;
1661 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1663 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1664 This,
1665 Adapter,
1666 CheckType, debug_d3ddevicetype(CheckType),
1667 DisplayFormat, debug_d3dformat(DisplayFormat),
1668 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1669 Windowed);
1671 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1672 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1673 return WINED3DERR_INVALIDCALL;
1676 cfgs = Adapters[Adapter].cfgs;
1677 nCfgs = Adapters[Adapter].nCfgs;
1678 for (it = 0; it < nCfgs; ++it) {
1679 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1680 hr = WINED3D_OK;
1681 TRACE_(d3d_caps)("OK\n");
1682 break ;
1686 if(hr != WINED3D_OK)
1687 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1689 if(hr != WINED3D_OK)
1690 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1692 return hr;
1695 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1696 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1697 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1698 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1699 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1700 This,
1701 Adapter,
1702 DeviceType, debug_d3ddevicetype(DeviceType),
1703 AdapterFormat, debug_d3dformat(AdapterFormat),
1704 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1705 RType, debug_d3dresourcetype(RType),
1706 CheckFormat, debug_d3dformat(CheckFormat));
1708 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1709 return WINED3DERR_INVALIDCALL;
1712 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1713 switch (CheckFormat) {
1714 /* Filtering not supported */
1715 case WINED3DFMT_R32F:
1716 case WINED3DFMT_A32B32G32R32F:
1717 TRACE_(d3d_caps)("[FAILED]\n");
1718 return WINED3DERR_NOTAVAILABLE;
1719 default:
1720 break;
1724 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1725 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1726 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1727 return WINED3DERR_NOTAVAILABLE;
1731 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1732 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1733 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1734 return WINED3DERR_NOTAVAILABLE;
1736 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1737 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1738 * app needing one of those formats, don't advertize them to avoid leading apps into
1739 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1740 * except of R32F.
1742 switch(CheckFormat) {
1743 case WINED3DFMT_P8:
1744 case WINED3DFMT_A4L4:
1745 case WINED3DFMT_R32F:
1746 case WINED3DFMT_R16F:
1747 case WINED3DFMT_X8L8V8U8:
1748 case WINED3DFMT_L6V5U5:
1749 case WINED3DFMT_G16R16:
1750 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1751 return WINED3DERR_NOTAVAILABLE;
1753 case WINED3DFMT_Q8W8V8U8:
1754 case WINED3DFMT_V16U16:
1755 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1756 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1757 return WINED3DERR_NOTAVAILABLE;
1759 break;
1761 case WINED3DFMT_V8U8:
1762 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1763 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1764 return WINED3DERR_NOTAVAILABLE;
1766 break;
1768 case WINED3DFMT_DXT1:
1769 case WINED3DFMT_DXT2:
1770 case WINED3DFMT_DXT3:
1771 case WINED3DFMT_DXT4:
1772 case WINED3DFMT_DXT5:
1773 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1774 * compressed texture results in an error. While the D3D refrast does
1775 * support s3tc volumes, at least the nvidia windows driver does not, so
1776 * we're free not to support this format.
1778 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1779 return WINED3DERR_NOTAVAILABLE;
1781 default:
1782 /* Do nothing, continue with checking the format below */
1783 break;
1786 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1787 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1788 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1789 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1790 if (!GL_LIMITS(vertex_samplers)) {
1791 TRACE_(d3d_caps)("[FAILED]\n");
1792 return WINED3DERR_NOTAVAILABLE;
1795 switch (CheckFormat) {
1796 case WINED3DFMT_A32B32G32R32F:
1797 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1798 TRACE_(d3d_caps)("[FAILED]\n");
1799 return WINED3DERR_NOTAVAILABLE;
1801 TRACE_(d3d_caps)("[OK]\n");
1802 return WINED3D_OK;
1804 default:
1805 TRACE_(d3d_caps)("[FAILED]\n");
1806 return WINED3DERR_NOTAVAILABLE;
1810 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1811 switch (CheckFormat) {
1812 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1813 * Windows supports only those 3, and enumerating the other formats confuses applications
1815 case WINED3DFMT_D24S8:
1816 case WINED3DFMT_D24X8:
1817 case WINED3DFMT_D16:
1818 TRACE_(d3d_caps)("[OK]\n");
1819 return WINED3D_OK;
1820 case WINED3DFMT_D16_LOCKABLE:
1821 case WINED3DFMT_D24FS8:
1822 case WINED3DFMT_D32F_LOCKABLE:
1823 case WINED3DFMT_D24X4S4:
1824 case WINED3DFMT_D15S1:
1825 case WINED3DFMT_D32:
1826 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1827 return WINED3DERR_NOTAVAILABLE;
1828 default:
1829 TRACE_(d3d_caps)("[FAILED]\n");
1830 return WINED3DERR_NOTAVAILABLE;
1832 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1833 switch (CheckFormat) {
1834 case WINED3DFMT_R8G8B8:
1835 case WINED3DFMT_A8R8G8B8:
1836 case WINED3DFMT_X8R8G8B8:
1837 case WINED3DFMT_R5G6B5:
1838 case WINED3DFMT_X1R5G5B5:
1839 case WINED3DFMT_A1R5G5B5:
1840 case WINED3DFMT_A4R4G4B4:
1841 case WINED3DFMT_R3G3B2:
1842 case WINED3DFMT_X4R4G4B4:
1843 case WINED3DFMT_A8B8G8R8:
1844 case WINED3DFMT_X8B8G8R8:
1845 case WINED3DFMT_P8:
1846 case WINED3DFMT_G16R16:
1847 TRACE_(d3d_caps)("[OK]\n");
1848 return WINED3D_OK;
1849 case WINED3DFMT_R16F:
1850 case WINED3DFMT_A16B16G16R16F:
1851 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1852 TRACE_(d3d_caps)("[FAILED]\n");
1853 return WINED3DERR_NOTAVAILABLE;
1855 TRACE_(d3d_caps)("[OK]\n");
1856 return WINED3D_OK;
1857 case WINED3DFMT_A32B32G32R32F:
1858 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1859 TRACE_(d3d_caps)("[FAILED]\n");
1860 return WINED3DERR_NOTAVAILABLE;
1862 TRACE_(d3d_caps)("[OK]\n");
1863 return WINED3D_OK;
1864 default:
1865 TRACE_(d3d_caps)("[FAILED]\n");
1866 return WINED3DERR_NOTAVAILABLE;
1868 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1869 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1870 switch (CheckFormat) {
1871 case WINED3DFMT_V8U8:
1872 TRACE_(d3d_caps)("[OK]\n");
1873 return WINED3D_OK;
1874 /* TODO: Other bump map formats */
1875 default:
1876 TRACE_(d3d_caps)("[FAILED]\n");
1877 return WINED3DERR_NOTAVAILABLE;
1880 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1881 switch (CheckFormat) {
1882 case WINED3DFMT_V8U8:
1883 TRACE_(d3d_caps)("[OK]\n");
1884 return WINED3D_OK;
1885 default:
1886 TRACE_(d3d_caps)("[FAILED]\n");
1887 return WINED3DERR_NOTAVAILABLE;
1890 TRACE_(d3d_caps)("[FAILED]\n");
1891 return WINED3DERR_NOTAVAILABLE;
1894 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1895 switch (CheckFormat) {
1896 case WINED3DFMT_DXT1:
1897 case WINED3DFMT_DXT2:
1898 case WINED3DFMT_DXT3:
1899 case WINED3DFMT_DXT4:
1900 case WINED3DFMT_DXT5:
1901 TRACE_(d3d_caps)("[OK]\n");
1902 return WINED3D_OK;
1903 default:
1904 break; /* Avoid compiler warnings */
1908 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1909 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1910 switch (CheckFormat) {
1911 case WINED3DFMT_A8R8G8B8:
1912 case WINED3DFMT_X8R8G8B8:
1913 case WINED3DFMT_A4R4G4B4:
1914 case WINED3DFMT_L8:
1915 case WINED3DFMT_A8L8:
1916 case WINED3DFMT_DXT1:
1917 case WINED3DFMT_DXT2:
1918 case WINED3DFMT_DXT3:
1919 case WINED3DFMT_DXT4:
1920 case WINED3DFMT_DXT5:
1921 TRACE_(d3d_caps)("[OK]\n");
1922 return WINED3D_OK;
1924 default:
1925 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1926 return WINED3DERR_NOTAVAILABLE;
1930 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1932 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1934 switch (CheckFormat) {
1935 case WINED3DFMT_R16F:
1936 case WINED3DFMT_A16B16G16R16F:
1937 if (!half_pixel_support) break;
1938 case WINED3DFMT_R32F:
1939 case WINED3DFMT_A32B32G32R32F:
1940 TRACE_(d3d_caps)("[OK]\n");
1941 return WINED3D_OK;
1942 default:
1943 break; /* Avoid compiler warnings */
1947 /* This format is nothing special and it is supported perfectly.
1948 * However, ati and nvidia driver on windows do not mark this format as
1949 * supported (tested with the dxCapsViewer) and pretending to
1950 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1951 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1952 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1954 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1955 TRACE_(d3d_caps)("[FAILED]\n");
1956 return WINED3DERR_NOTAVAILABLE;
1959 switch (CheckFormat) {
1961 /*****
1962 * supported: RGB(A) formats
1964 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1965 case WINED3DFMT_A8R8G8B8:
1966 case WINED3DFMT_X8R8G8B8:
1967 case WINED3DFMT_R5G6B5:
1968 case WINED3DFMT_X1R5G5B5:
1969 case WINED3DFMT_A1R5G5B5:
1970 case WINED3DFMT_A4R4G4B4:
1971 case WINED3DFMT_R3G3B2:
1972 case WINED3DFMT_A8:
1973 case WINED3DFMT_X4R4G4B4:
1974 case WINED3DFMT_A8B8G8R8:
1975 case WINED3DFMT_X8B8G8R8:
1976 case WINED3DFMT_A2R10G10B10:
1977 case WINED3DFMT_A2B10G10R10:
1978 case WINED3DFMT_G16R16:
1979 TRACE_(d3d_caps)("[OK]\n");
1980 return WINED3D_OK;
1982 /*****
1983 * supported: Palettized
1985 case WINED3DFMT_P8:
1986 TRACE_(d3d_caps)("[OK]\n");
1987 return WINED3D_OK;
1989 /*****
1990 * Supported: (Alpha)-Luminance
1992 case WINED3DFMT_L8:
1993 case WINED3DFMT_A8L8:
1994 case WINED3DFMT_A4L4:
1995 TRACE_(d3d_caps)("[OK]\n");
1996 return WINED3D_OK;
1998 /*****
1999 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2000 * GL_NV_texture_shader), but advertized to make apps happy.
2001 * Enable some because games often fail when they are not available
2002 * and are still playable even without bump mapping
2004 case WINED3DFMT_V8U8:
2005 case WINED3DFMT_V16U16:
2006 case WINED3DFMT_L6V5U5:
2007 case WINED3DFMT_X8L8V8U8:
2008 case WINED3DFMT_Q8W8V8U8:
2009 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
2010 return WINED3D_OK;
2012 /* Those are not advertized by the nvidia windows driver, and not
2013 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
2014 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
2015 * ARGB format if needed
2017 case WINED3DFMT_W11V11U10:
2018 case WINED3DFMT_A2W10V10U10:
2019 WARN_(d3d_caps)("[FAILED]\n");
2020 return WINED3DERR_NOTAVAILABLE;
2022 /*****
2023 * DXTN Formats: Handled above
2024 * WINED3DFMT_DXT1
2025 * WINED3DFMT_DXT2
2026 * WINED3DFMT_DXT3
2027 * WINED3DFMT_DXT4
2028 * WINED3DFMT_DXT5
2031 /*****
2032 * Odd formats - not supported
2034 case WINED3DFMT_VERTEXDATA:
2035 case WINED3DFMT_INDEX16:
2036 case WINED3DFMT_INDEX32:
2037 case WINED3DFMT_Q16W16V16U16:
2038 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2039 return WINED3DERR_NOTAVAILABLE;
2041 /*****
2042 * Float formats: Not supported right now
2044 case WINED3DFMT_G16R16F:
2045 case WINED3DFMT_G32R32F:
2046 case WINED3DFMT_CxV8U8:
2047 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2048 return WINED3DERR_NOTAVAILABLE;
2050 /* Not supported */
2051 case WINED3DFMT_A16B16G16R16:
2052 case WINED3DFMT_A8R3G3B2:
2053 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2054 return WINED3DERR_NOTAVAILABLE;
2056 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2057 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2058 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2059 * We can do instancing with all shader versions, but we need vertex shaders.
2061 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2062 * to enable instancing. WineD3D doesn't need that and just ignores it.
2064 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2066 case WINEMAKEFOURCC('I','N','S','T'):
2067 TRACE("ATI Instancing check hack\n");
2068 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2069 TRACE_(d3d_caps)("[OK]\n");
2070 return WINED3D_OK;
2071 } else {
2072 TRACE_(d3d_caps)("[FAILED]\n");
2073 return WINED3DERR_NOTAVAILABLE;
2076 default:
2077 break;
2080 TRACE_(d3d_caps)("[FAILED]\n");
2081 return WINED3DERR_NOTAVAILABLE;
2084 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2085 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2086 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2088 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2089 This,
2090 Adapter,
2091 DeviceType, debug_d3ddevicetype(DeviceType),
2092 SourceFormat, debug_d3dformat(SourceFormat),
2093 TargetFormat, debug_d3dformat(TargetFormat));
2094 return WINED3D_OK;
2097 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2098 subset of a D3DCAPS9 structure. However, it has to come via a void *
2099 as the d3d8 interface cannot import the d3d9 header */
2100 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2102 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2103 int vs_selected_mode;
2104 int ps_selected_mode;
2106 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2108 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2109 return WINED3DERR_INVALIDCALL;
2112 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2114 /* This function should *not* be modifying GL caps
2115 * TODO: move the functionality where it belongs */
2116 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2118 /* ------------------------------------------------
2119 The following fields apply to both d3d8 and d3d9
2120 ------------------------------------------------ */
2121 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2122 *pCaps->AdapterOrdinal = Adapter;
2124 *pCaps->Caps = 0;
2125 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2126 WINED3DCAPS2_FULLSCREENGAMMA |
2127 WINED3DCAPS2_DYNAMICTEXTURES;
2128 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2129 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2131 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2132 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2133 WINED3DPRESENT_INTERVAL_ONE;
2135 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2136 WINED3DCURSORCAPS_LOWRES;
2138 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2139 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2140 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2141 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2142 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2143 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2144 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2145 WINED3DDEVCAPS_PUREDEVICE |
2146 WINED3DDEVCAPS_HWRASTERIZATION |
2147 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2148 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2149 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2150 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2151 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2152 WINED3DDEVCAPS_RTPATCHES;
2154 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2155 WINED3DPMISCCAPS_CULLCCW |
2156 WINED3DPMISCCAPS_CULLCW |
2157 WINED3DPMISCCAPS_COLORWRITEENABLE |
2158 WINED3DPMISCCAPS_CLIPTLVERTS |
2159 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2160 WINED3DPMISCCAPS_MASKZ |
2161 WINED3DPMISCCAPS_BLENDOP;
2162 /* TODO:
2163 WINED3DPMISCCAPS_NULLREFERENCE
2164 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2165 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2166 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2167 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2168 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2169 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2171 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2172 #if 0
2173 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2174 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2175 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2176 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2177 #endif
2179 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2180 WINED3DPRASTERCAPS_PAT |
2181 WINED3DPRASTERCAPS_WFOG |
2182 WINED3DPRASTERCAPS_ZFOG |
2183 WINED3DPRASTERCAPS_FOGVERTEX |
2184 WINED3DPRASTERCAPS_FOGTABLE |
2185 WINED3DPRASTERCAPS_STIPPLE |
2186 WINED3DPRASTERCAPS_SUBPIXEL |
2187 WINED3DPRASTERCAPS_ZTEST |
2188 WINED3DPRASTERCAPS_SCISSORTEST |
2189 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2190 WINED3DPRASTERCAPS_DEPTHBIAS;
2192 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2193 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2194 WINED3DPRASTERCAPS_ZBIAS |
2195 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2197 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2198 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2200 /* FIXME Add:
2201 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2202 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2203 WINED3DPRASTERCAPS_ANTIALIASEDGES
2204 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2205 WINED3DPRASTERCAPS_WBUFFER */
2207 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2208 WINED3DPCMPCAPS_EQUAL |
2209 WINED3DPCMPCAPS_GREATER |
2210 WINED3DPCMPCAPS_GREATEREQUAL |
2211 WINED3DPCMPCAPS_LESS |
2212 WINED3DPCMPCAPS_LESSEQUAL |
2213 WINED3DPCMPCAPS_NEVER |
2214 WINED3DPCMPCAPS_NOTEQUAL;
2216 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2217 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2218 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2219 WINED3DPBLENDCAPS_DESTALPHA |
2220 WINED3DPBLENDCAPS_DESTCOLOR |
2221 WINED3DPBLENDCAPS_INVDESTALPHA |
2222 WINED3DPBLENDCAPS_INVDESTCOLOR |
2223 WINED3DPBLENDCAPS_INVSRCALPHA |
2224 WINED3DPBLENDCAPS_INVSRCCOLOR |
2225 WINED3DPBLENDCAPS_ONE |
2226 WINED3DPBLENDCAPS_SRCALPHA |
2227 WINED3DPBLENDCAPS_SRCALPHASAT |
2228 WINED3DPBLENDCAPS_SRCCOLOR |
2229 WINED3DPBLENDCAPS_ZERO;
2231 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2232 WINED3DPBLENDCAPS_DESTALPHA |
2233 WINED3DPBLENDCAPS_DESTCOLOR |
2234 WINED3DPBLENDCAPS_INVDESTALPHA |
2235 WINED3DPBLENDCAPS_INVDESTCOLOR |
2236 WINED3DPBLENDCAPS_INVSRCALPHA |
2237 WINED3DPBLENDCAPS_INVSRCCOLOR |
2238 WINED3DPBLENDCAPS_ONE |
2239 WINED3DPBLENDCAPS_SRCALPHA |
2240 WINED3DPBLENDCAPS_SRCCOLOR |
2241 WINED3DPBLENDCAPS_ZERO;
2242 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2243 * according to the glBlendFunc manpage
2245 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2246 * legacy settings for srcblend only
2249 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2250 WINED3DPCMPCAPS_EQUAL |
2251 WINED3DPCMPCAPS_GREATER |
2252 WINED3DPCMPCAPS_GREATEREQUAL |
2253 WINED3DPCMPCAPS_LESS |
2254 WINED3DPCMPCAPS_LESSEQUAL |
2255 WINED3DPCMPCAPS_NEVER |
2256 WINED3DPCMPCAPS_NOTEQUAL;
2258 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2259 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2260 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2261 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2262 WINED3DPSHADECAPS_COLORFLATRGB |
2263 WINED3DPSHADECAPS_FOGFLAT |
2264 WINED3DPSHADECAPS_FOGGOURAUD |
2265 WINED3DPSHADECAPS_SPECULARFLATRGB;
2267 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2268 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2269 WINED3DPTEXTURECAPS_BORDER |
2270 WINED3DPTEXTURECAPS_MIPMAP |
2271 WINED3DPTEXTURECAPS_PROJECTED |
2272 WINED3DPTEXTURECAPS_PERSPECTIVE;
2274 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2275 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2276 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2279 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2280 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2281 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2282 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2285 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2286 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2287 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2288 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2292 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2293 WINED3DPTFILTERCAPS_MAGFPOINT |
2294 WINED3DPTFILTERCAPS_MINFLINEAR |
2295 WINED3DPTFILTERCAPS_MINFPOINT |
2296 WINED3DPTFILTERCAPS_MIPFLINEAR |
2297 WINED3DPTFILTERCAPS_MIPFPOINT |
2298 WINED3DPTFILTERCAPS_LINEAR |
2299 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2300 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2301 WINED3DPTFILTERCAPS_MIPLINEAR |
2302 WINED3DPTFILTERCAPS_MIPNEAREST |
2303 WINED3DPTFILTERCAPS_NEAREST;
2305 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2306 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2307 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2310 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2311 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2312 WINED3DPTFILTERCAPS_MAGFPOINT |
2313 WINED3DPTFILTERCAPS_MINFLINEAR |
2314 WINED3DPTFILTERCAPS_MINFPOINT |
2315 WINED3DPTFILTERCAPS_MIPFLINEAR |
2316 WINED3DPTFILTERCAPS_MIPFPOINT |
2317 WINED3DPTFILTERCAPS_LINEAR |
2318 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2319 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2320 WINED3DPTFILTERCAPS_MIPLINEAR |
2321 WINED3DPTFILTERCAPS_MIPNEAREST |
2322 WINED3DPTFILTERCAPS_NEAREST;
2324 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2325 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2326 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2328 } else
2329 *pCaps->CubeTextureFilterCaps = 0;
2331 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2332 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2333 WINED3DPTFILTERCAPS_MAGFPOINT |
2334 WINED3DPTFILTERCAPS_MINFLINEAR |
2335 WINED3DPTFILTERCAPS_MINFPOINT |
2336 WINED3DPTFILTERCAPS_MIPFLINEAR |
2337 WINED3DPTFILTERCAPS_MIPFPOINT |
2338 WINED3DPTFILTERCAPS_LINEAR |
2339 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2340 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2341 WINED3DPTFILTERCAPS_MIPLINEAR |
2342 WINED3DPTFILTERCAPS_MIPNEAREST |
2343 WINED3DPTFILTERCAPS_NEAREST;
2344 } else
2345 *pCaps->VolumeTextureFilterCaps = 0;
2347 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2348 WINED3DPTADDRESSCAPS_CLAMP |
2349 WINED3DPTADDRESSCAPS_WRAP;
2351 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2352 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2354 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2355 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2357 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2358 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2361 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2362 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2363 WINED3DPTADDRESSCAPS_CLAMP |
2364 WINED3DPTADDRESSCAPS_WRAP;
2365 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2366 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2368 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2369 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2371 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2372 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2374 } else
2375 *pCaps->VolumeTextureAddressCaps = 0;
2377 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2378 WINED3DLINECAPS_ZTEST;
2379 /* FIXME: Add
2380 WINED3DLINECAPS_BLEND
2381 WINED3DLINECAPS_ALPHACMP
2382 WINED3DLINECAPS_FOG */
2384 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2385 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2387 if(GL_SUPPORT(EXT_TEXTURE3D))
2388 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2389 else
2390 *pCaps->MaxVolumeExtent = 0;
2392 *pCaps->MaxTextureRepeat = 32768;
2393 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2394 *pCaps->MaxVertexW = 1.0;
2396 *pCaps->GuardBandLeft = 0;
2397 *pCaps->GuardBandTop = 0;
2398 *pCaps->GuardBandRight = 0;
2399 *pCaps->GuardBandBottom = 0;
2401 *pCaps->ExtentsAdjust = 0;
2403 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2404 WINED3DSTENCILCAPS_INCRSAT |
2405 WINED3DSTENCILCAPS_INVERT |
2406 WINED3DSTENCILCAPS_KEEP |
2407 WINED3DSTENCILCAPS_REPLACE |
2408 WINED3DSTENCILCAPS_ZERO;
2409 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2410 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2411 WINED3DSTENCILCAPS_INCR;
2413 if ( This->dxVersion > 8 &&
2414 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2415 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2416 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2419 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2421 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2422 WINED3DTEXOPCAPS_ADDSIGNED |
2423 WINED3DTEXOPCAPS_ADDSIGNED2X |
2424 WINED3DTEXOPCAPS_MODULATE |
2425 WINED3DTEXOPCAPS_MODULATE2X |
2426 WINED3DTEXOPCAPS_MODULATE4X |
2427 WINED3DTEXOPCAPS_SELECTARG1 |
2428 WINED3DTEXOPCAPS_SELECTARG2 |
2429 WINED3DTEXOPCAPS_DISABLE;
2431 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2432 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2433 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2434 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2435 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2436 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2437 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2438 WINED3DTEXOPCAPS_LERP |
2439 WINED3DTEXOPCAPS_SUBTRACT;
2441 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2442 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2443 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2444 WINED3DTEXOPCAPS_MULTIPLYADD |
2445 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2446 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2447 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2449 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2450 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2452 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2453 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2454 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2457 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2458 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2459 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2460 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2461 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2462 * and 3D textures. It also allows us to keep the code simpler by having texture
2463 * shaders constantly enabled.
2465 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2466 /* TODO: Luminance bump map? */
2468 #if 0
2469 /* FIXME: Add
2470 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2471 WINED3DTEXOPCAPS_PREMODULATE */
2472 #endif
2474 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2475 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2476 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2477 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2479 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2480 *pCaps->MaxVertexBlendMatrixIndex = 0;
2482 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2483 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2486 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2487 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2488 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2489 WINED3DVTXPCAPS_LOCALVIEWER |
2490 WINED3DVTXPCAPS_VERTEXFOG |
2491 WINED3DVTXPCAPS_TEXGEN;
2492 /* FIXME: Add
2493 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2495 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2496 *pCaps->MaxVertexIndex = 0xFFFFF;
2497 *pCaps->MaxStreams = MAX_STREAMS;
2498 *pCaps->MaxStreamStride = 1024;
2500 if (vs_selected_mode == SHADER_GLSL) {
2501 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2502 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2503 * vs_nv_version which is based on NV_vertex_program.
2504 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2505 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2506 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2507 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2508 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2509 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2510 else
2511 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2512 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2513 } else if (vs_selected_mode == SHADER_ARB) {
2514 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2515 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2516 } else {
2517 *pCaps->VertexShaderVersion = 0;
2518 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2521 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2523 if (ps_selected_mode == SHADER_GLSL) {
2524 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2525 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2526 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2527 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2528 * in max native instructions. Intel and others also offer the info in this extension but they
2529 * don't support GLSL (at least on Windows).
2531 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go up to 512. Assume that if the number
2532 * of instructions is 512 or less we have to do with ps2.0 hardware.
2533 * 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.
2535 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2536 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2537 else
2538 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2539 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2540 * Direct3D minimum requirement.
2542 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2543 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2545 * The problem is that the refrast clamps temporary results in the shader to
2546 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2547 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2548 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2549 * offer a way to query this.
2551 *pCaps->PixelShader1xMaxValue = 8.0;
2552 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2553 } else if (ps_selected_mode == SHADER_ARB) {
2554 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2555 *pCaps->PixelShader1xMaxValue = 8.0;
2556 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2557 } else {
2558 *pCaps->PixelShaderVersion = 0;
2559 *pCaps->PixelShader1xMaxValue = 0.0;
2560 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2563 /* ------------------------------------------------
2564 The following fields apply to d3d9 only
2565 ------------------------------------------------ */
2566 if (This->dxVersion > 8) {
2567 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2568 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2569 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2570 *pCaps->MaxNpatchTessellationLevel = 0;
2571 *pCaps->MasterAdapterOrdinal = 0;
2572 *pCaps->AdapterOrdinalInGroup = 0;
2573 *pCaps->NumberOfAdaptersInGroup = 1;
2575 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2576 /* OpenGL supports all the formats below, perhaps not always
2577 * without conversion, but it supports them.
2578 * Further GLSL doesn't seem to have an official unsigned type so
2579 * don't advertise it yet as I'm not sure how we handle it.
2580 * We might need to add some clamping in the shader engine to
2581 * support it.
2582 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2583 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2584 WINED3DDTCAPS_UBYTE4N |
2585 WINED3DDTCAPS_SHORT2N |
2586 WINED3DDTCAPS_SHORT4N;
2587 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2588 *pCaps->DeclTypes |=
2589 WINED3DDTCAPS_FLOAT16_2 |
2590 WINED3DDTCAPS_FLOAT16_4;
2592 } else
2593 *pCaps->DeclTypes = 0;
2595 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2598 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2599 WINED3DPTFILTERCAPS_MAGFPOINT |
2600 WINED3DPTFILTERCAPS_MINFLINEAR |
2601 WINED3DPTFILTERCAPS_MAGFLINEAR;
2602 *pCaps->VertexTextureFilterCaps = 0;
2604 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2605 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2606 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2607 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2608 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2609 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2610 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2612 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2613 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2614 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2615 *pCaps->VS20Caps.Caps = 0;
2616 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2617 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2618 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2620 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2621 *pCaps->MaxVertexShader30InstructionSlots = 0;
2622 } else { /* VS 1.x */
2623 *pCaps->VS20Caps.Caps = 0;
2624 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2625 *pCaps->VS20Caps.NumTemps = 0;
2626 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2628 *pCaps->MaxVShaderInstructionsExecuted = 0;
2629 *pCaps->MaxVertexShader30InstructionSlots = 0;
2632 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2633 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2634 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2636 /* 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 */
2637 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2638 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2639 WINED3DPS20CAPS_PREDICATION |
2640 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2641 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2642 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2643 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2644 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2645 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2647 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2648 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2649 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2650 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2651 *pCaps->PS20Caps.Caps = 0;
2652 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2653 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2654 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2655 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2657 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2658 *pCaps->MaxPixelShader30InstructionSlots = 0;
2659 } else { /* PS 1.x */
2660 *pCaps->PS20Caps.Caps = 0;
2661 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2662 *pCaps->PS20Caps.NumTemps = 0;
2663 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2664 *pCaps->PS20Caps.NumInstructionSlots = 0;
2666 *pCaps->MaxPShaderInstructionsExecuted = 0;
2667 *pCaps->MaxPixelShader30InstructionSlots = 0;
2671 return WINED3D_OK;
2674 static unsigned int glsl_program_key_hash(void *key) {
2675 glsl_program_key_t *k = (glsl_program_key_t *)key;
2677 unsigned int hash = k->vshader | k->pshader << 16;
2678 hash += ~(hash << 15);
2679 hash ^= (hash >> 10);
2680 hash += (hash << 3);
2681 hash ^= (hash >> 6);
2682 hash += ~(hash << 11);
2683 hash ^= (hash >> 16);
2685 return hash;
2688 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2689 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2690 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2692 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2695 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2696 and fields being inserted in the middle, a new structure is used in place */
2697 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2698 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2699 IUnknown *parent) {
2701 IWineD3DDeviceImpl *object = NULL;
2702 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2703 WINED3DDISPLAYMODE mode;
2704 int i;
2706 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2707 * number and create a device without a 3D adapter for 2D only operation.
2709 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2710 return WINED3DERR_INVALIDCALL;
2713 /* Create a WineD3DDevice object */
2714 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2715 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2716 TRACE("Created WineD3DDevice object @ %p\n", object);
2717 if (NULL == object) {
2718 return WINED3DERR_OUTOFVIDEOMEMORY;
2721 /* Set up initial COM information */
2722 object->lpVtbl = &IWineD3DDevice_Vtbl;
2723 object->ref = 1;
2724 object->wineD3D = iface;
2725 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2726 IWineD3D_AddRef(object->wineD3D);
2727 object->parent = parent;
2728 list_init(&object->resources);
2730 if(This->dxVersion == 7) {
2731 object->surface_alignment = 8;
2732 } else {
2733 object->surface_alignment = 4;
2735 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2737 /* Set the state up as invalid until the device is fully created */
2738 object->state = WINED3DERR_DRIVERINTERNALERROR;
2740 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2741 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2743 /* Save the creation parameters */
2744 object->createParms.AdapterOrdinal = Adapter;
2745 object->createParms.DeviceType = DeviceType;
2746 object->createParms.hFocusWindow = hFocusWindow;
2747 object->createParms.BehaviorFlags = BehaviourFlags;
2749 /* Initialize other useful values */
2750 object->adapterNo = Adapter;
2751 object->devType = DeviceType;
2753 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2754 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2755 object->shader_backend = &glsl_shader_backend;
2756 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2757 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2758 object->shader_backend = &arb_program_shader_backend;
2759 } else {
2760 object->shader_backend = &none_shader_backend;
2763 /* set the state of the device to valid */
2764 object->state = WINED3D_OK;
2766 /* Get the initial screen setup for ddraw */
2767 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
2769 object->ddraw_width = mode.Width;
2770 object->ddraw_height = mode.Height;
2771 object->ddraw_format = mode.Format;
2773 for(i = 0; i < PATCHMAP_SIZE; i++) {
2774 list_init(&object->patches[i]);
2776 return WINED3D_OK;
2778 #undef GLINFO_LOCATION
2780 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2781 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2782 IUnknown_AddRef(This->parent);
2783 *pParent = This->parent;
2784 return WINED3D_OK;
2787 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2788 IUnknown* surfaceParent;
2789 TRACE("(%p) call back\n", pSurface);
2791 /* Now, release the parent, which will take care of cleaning up the surface for us */
2792 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2793 IUnknown_Release(surfaceParent);
2794 return IUnknown_Release(surfaceParent);
2797 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2798 IUnknown* volumeParent;
2799 TRACE("(%p) call back\n", pVolume);
2801 /* Now, release the parent, which will take care of cleaning up the volume for us */
2802 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2803 IUnknown_Release(volumeParent);
2804 return IUnknown_Release(volumeParent);
2807 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2808 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2809 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2810 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2812 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2813 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2814 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2815 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2816 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
2817 * the chance that other implementations support them is rather small since Win32 QuickTime uses
2818 * DirectDraw, not OpenGL.
2820 if(gl_info->supported[APPLE_FENCE] &&
2821 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2822 gl_info->supported[APPLE_FLUSH_RENDER] &&
2823 gl_info->supported[APPLE_YCBCR_422]) {
2824 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2825 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2826 return TRUE;
2827 } else {
2828 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2829 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2830 return FALSE;
2834 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2835 if(implementation_is_apple(gl_info)) {
2836 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
2837 * used it falls back to software. While the compiler can detect if the shader uses all declared
2838 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2839 * using relative addressing falls back to software.
2841 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2843 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2844 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2845 } else {
2846 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2847 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
2848 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
2851 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2852 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2853 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2854 * flag for this extension
2856 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
2857 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
2858 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
2859 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
2860 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2861 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
2862 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
2866 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
2867 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
2868 * and opengl feedback mode, but some GL implementations(MacOS ATI at least, propably all macos ones)
2869 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
2870 * according to the spec.
2872 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
2873 * makes the shader slower and eats instruction slots which should be available to the d3d app.
2875 if(gl_info->gl_vendor == VENDOR_INTEL) {
2876 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
2877 gl_info->set_texcoord_w = TRUE;
2882 #define PUSH1(att) attribs[nAttribs++] = (att);
2883 #define GLINFO_LOCATION (Adapters[0].gl_info)
2884 BOOL InitAdapters(void) {
2885 static HMODULE mod_gl;
2886 BOOL ret;
2887 int ps_selected_mode, vs_selected_mode;
2889 /* No need to hold any lock. The calling library makes sure only one thread calls
2890 * wined3d simultaneously
2892 if(numAdapters > 0) return TRUE;
2894 TRACE("Initializing adapters\n");
2896 if(!mod_gl) {
2897 #ifdef USE_WIN32_OPENGL
2898 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2899 mod_gl = LoadLibraryA("opengl32.dll");
2900 if(!mod_gl) {
2901 ERR("Can't load opengl32.dll!\n");
2902 return FALSE;
2904 #else
2905 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2906 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2907 mod_gl = GetModuleHandleA("gdi32.dll");
2908 #endif
2911 /* Load WGL core functions from opengl32.dll */
2912 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2913 WGL_FUNCS_GEN;
2914 #undef USE_WGL_FUNC
2916 if(!pwglGetProcAddress) {
2917 ERR("Unable to load wglGetProcAddress!\n");
2918 return FALSE;
2921 /* Dynamically load all GL core functions */
2922 GL_FUNCS_GEN;
2923 #undef USE_GL_FUNC
2925 /* For now only one default adapter */
2927 int iPixelFormat;
2928 int attribs[8];
2929 int values[8];
2930 int nAttribs = 0;
2931 int res;
2932 WineD3D_PixelFormat *cfgs;
2933 int attribute;
2934 DISPLAY_DEVICEW DisplayDevice;
2935 HDC hdc;
2937 TRACE("Initializing default adapter\n");
2938 Adapters[0].num = 0;
2939 Adapters[0].monitorPoint.x = -1;
2940 Adapters[0].monitorPoint.y = -1;
2942 if (!WineD3D_CreateFakeGLContext()) {
2943 ERR("Failed to get a gl context for default adapter\n");
2944 HeapFree(GetProcessHeap(), 0, Adapters);
2945 WineD3D_ReleaseFakeGLContext();
2946 return FALSE;
2949 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2950 if(!ret) {
2951 ERR("Failed to initialize gl caps for default adapter\n");
2952 HeapFree(GetProcessHeap(), 0, Adapters);
2953 WineD3D_ReleaseFakeGLContext();
2954 return FALSE;
2956 ret = initPixelFormats(&Adapters[0].gl_info);
2957 if(!ret) {
2958 ERR("Failed to init gl formats\n");
2959 HeapFree(GetProcessHeap(), 0, Adapters);
2960 WineD3D_ReleaseFakeGLContext();
2961 return FALSE;
2964 hdc = pwglGetCurrentDC();
2965 if(!hdc) {
2966 ERR("Failed to get gl HDC\n");
2967 HeapFree(GetProcessHeap(), 0, Adapters);
2968 WineD3D_ReleaseFakeGLContext();
2969 return FALSE;
2972 Adapters[0].driver = "Display";
2973 Adapters[0].description = "Direct3D HAL";
2975 /* Use the VideoRamSize registry setting when set */
2976 if(wined3d_settings.emulated_textureram)
2977 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
2978 else
2979 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
2980 Adapters[0].UsedTextureRam = 0;
2981 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
2983 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2984 DisplayDevice.cb = sizeof(DisplayDevice);
2985 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2986 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2987 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2989 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2990 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2992 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2993 cfgs = Adapters[0].cfgs;
2994 PUSH1(WGL_RED_BITS_ARB)
2995 PUSH1(WGL_GREEN_BITS_ARB)
2996 PUSH1(WGL_BLUE_BITS_ARB)
2997 PUSH1(WGL_ALPHA_BITS_ARB)
2998 PUSH1(WGL_DEPTH_BITS_ARB)
2999 PUSH1(WGL_STENCIL_BITS_ARB)
3001 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
3002 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
3004 if(!res)
3005 continue;
3007 /* Cache the pixel format */
3008 cfgs->iPixelFormat = iPixelFormat;
3009 cfgs->redSize = values[0];
3010 cfgs->greenSize = values[1];
3011 cfgs->blueSize = values[2];
3012 cfgs->alphaSize = values[3];
3013 cfgs->depthSize = values[4];
3014 cfgs->stencilSize = values[5];
3016 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);
3017 cfgs++;
3019 WineD3D_ReleaseFakeGLContext();
3021 fixup_extensions(&Adapters[0].gl_info);
3023 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
3024 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
3027 numAdapters = 1;
3028 TRACE("%d adapters successfully initialized\n", numAdapters);
3030 return TRUE;
3032 #undef PUSH1
3033 #undef GLINFO_LOCATION
3035 /**********************************************************
3036 * IWineD3D VTbl follows
3037 **********************************************************/
3039 const IWineD3DVtbl IWineD3D_Vtbl =
3041 /* IUnknown */
3042 IWineD3DImpl_QueryInterface,
3043 IWineD3DImpl_AddRef,
3044 IWineD3DImpl_Release,
3045 /* IWineD3D */
3046 IWineD3DImpl_GetParent,
3047 IWineD3DImpl_GetAdapterCount,
3048 IWineD3DImpl_RegisterSoftwareDevice,
3049 IWineD3DImpl_GetAdapterMonitor,
3050 IWineD3DImpl_GetAdapterModeCount,
3051 IWineD3DImpl_EnumAdapterModes,
3052 IWineD3DImpl_GetAdapterDisplayMode,
3053 IWineD3DImpl_GetAdapterIdentifier,
3054 IWineD3DImpl_CheckDeviceMultiSampleType,
3055 IWineD3DImpl_CheckDepthStencilMatch,
3056 IWineD3DImpl_CheckDeviceType,
3057 IWineD3DImpl_CheckDeviceFormat,
3058 IWineD3DImpl_CheckDeviceFormatConversion,
3059 IWineD3DImpl_GetDeviceCaps,
3060 IWineD3DImpl_CreateDevice