push 0f15bbd80d260bbd8adf052e820484a405c49375
[wine/hacks.git] / dlls / wined3d / directx.c
blobe4b5bdf46dbac60d8a75367e0de906673c1bc48a
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 int 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 gl_info->gl_vendor = VENDOR_INTEL;
491 } else if (strstr(gl_string, "Mesa")) {
492 gl_info->gl_vendor = VENDOR_MESA;
493 } else {
494 gl_info->gl_vendor = VENDOR_WINE;
496 } else {
497 gl_info->gl_vendor = VENDOR_WINE;
501 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
503 /* Parse the GL_VERSION field into major and minor information */
504 gl_string = (const char *) glGetString(GL_VERSION);
505 if (gl_string != NULL) {
507 switch (gl_info->gl_vendor) {
508 case VENDOR_NVIDIA:
509 gl_string_cursor = strstr(gl_string, "NVIDIA");
510 if (!gl_string_cursor) {
511 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
512 break;
515 gl_string_cursor = strstr(gl_string_cursor, " ");
516 if (!gl_string_cursor) {
517 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
518 break;
521 while (*gl_string_cursor == ' ') {
522 ++gl_string_cursor;
525 if (!*gl_string_cursor) {
526 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
527 break;
530 major = atoi(gl_string_cursor);
531 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
532 ++gl_string_cursor;
535 if (*gl_string_cursor++ != '.') {
536 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
537 break;
540 minor = atoi(gl_string_cursor);
541 minor = major*100+minor;
542 major = 10;
544 break;
546 case VENDOR_ATI:
547 major = minor = 0;
548 gl_string_cursor = strchr(gl_string, '-');
549 if (gl_string_cursor) {
550 int error = 0;
551 gl_string_cursor++;
553 /* Check if version number is of the form x.y.z */
554 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
555 error = 1;
556 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
557 error = 1;
558 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
559 error = 1;
560 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
561 error = 1;
563 /* Mark version number as malformed */
564 if (error)
565 gl_string_cursor = 0;
568 if (!gl_string_cursor)
569 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
570 else {
571 major = *gl_string_cursor - '0';
572 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
574 break;
576 case VENDOR_INTEL:
577 case VENDOR_MESA:
578 gl_string_cursor = strstr(gl_string, "Mesa");
579 gl_string_cursor = strstr(gl_string_cursor, " ");
580 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
581 if (*gl_string_cursor) {
582 char tmp[16];
583 int cursor = 0;
585 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
586 tmp[cursor++] = *gl_string_cursor;
587 ++gl_string_cursor;
589 tmp[cursor] = 0;
590 major = atoi(tmp);
592 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
593 ++gl_string_cursor;
595 cursor = 0;
596 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
597 tmp[cursor++] = *gl_string_cursor;
598 ++gl_string_cursor;
600 tmp[cursor] = 0;
601 minor = atoi(tmp);
603 break;
605 default:
606 major = 0;
607 minor = 9;
609 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
610 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
613 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
616 * Initialize openGL extension related variables
617 * with Default values
619 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
620 gl_info->max_buffers = 1;
621 gl_info->max_textures = 1;
622 gl_info->max_texture_stages = 1;
623 gl_info->max_fragment_samplers = 1;
624 gl_info->max_vertex_samplers = 0;
625 gl_info->max_combined_samplers = 0;
626 gl_info->max_sampler_stages = 1;
627 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
628 gl_info->ps_arb_max_temps = 0;
629 gl_info->ps_arb_max_instructions = 0;
630 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
631 gl_info->vs_arb_max_temps = 0;
632 gl_info->vs_arb_max_instructions = 0;
633 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
634 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
635 gl_info->vs_glsl_constantsF = 0;
636 gl_info->ps_glsl_constantsF = 0;
637 gl_info->vs_arb_constantsF = 0;
638 gl_info->ps_arb_constantsF = 0;
640 /* Retrieve opengl defaults */
641 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
642 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
643 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
645 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
646 gl_info->max_lights = gl_max;
647 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
649 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
650 gl_info->max_texture_size = gl_max;
651 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
653 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
654 gl_info->max_pointsizemin = gl_floatv[0];
655 gl_info->max_pointsize = gl_floatv[1];
656 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
658 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
659 gl_info->max_aux_buffers = gl_max;
660 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
662 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
663 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
664 TRACE_(d3d_caps)("GL_Extensions reported:\n");
666 if (NULL == GL_Extensions) {
667 ERR(" GL_Extensions returns NULL\n");
668 } else {
669 while (*GL_Extensions != 0x00) {
670 const char *Start;
671 char ThisExtn[256];
672 size_t len;
674 while (isspace(*GL_Extensions)) GL_Extensions++;
675 Start = GL_Extensions;
676 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
677 GL_Extensions++;
680 len = GL_Extensions - Start;
681 if (len == 0 || len >= sizeof(ThisExtn))
682 continue;
684 memcpy(ThisExtn, Start, len);
685 ThisExtn[len] = '\0';
686 TRACE_(d3d_caps)("- %s\n", ThisExtn);
688 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
689 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
690 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
691 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
692 break;
696 /* Now work out what GL support this card really has */
697 #define USE_GL_FUNC(type, pfn, ext, replace) { \
698 DWORD ver = ver_for_ext(ext); \
699 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
700 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
701 else gl_info->pfn = NULL; \
703 GL_EXT_FUNCS_GEN;
704 #undef USE_GL_FUNC
706 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
707 WGL_EXT_FUNCS_GEN;
708 #undef USE_GL_FUNC
710 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
711 * loading the functions, otherwise the code above will load the extension entry points instead of the
712 * core functions, which may not work
714 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
715 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
716 EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
717 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
718 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
722 if (gl_info->supported[APPLE_FENCE]) {
723 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
724 * The apple extension interacts with some other apple exts. Disable the NV
725 * extension if the apple one is support to prevent confusion in other parts
726 * of the code
728 gl_info->supported[NV_FENCE] = FALSE;
730 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
731 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
732 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
734 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
735 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
736 * Won't occur in any real world situation though
738 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
740 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
741 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
742 gl_info->max_buffers = gl_max;
743 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
745 if (gl_info->supported[ARB_MULTITEXTURE]) {
746 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
747 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
748 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
750 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
751 GLint tmp;
752 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
753 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
754 } else {
755 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
757 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
759 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
760 GLint tmp;
761 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
762 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
763 } else {
764 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
766 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
768 if (gl_info->supported[ARB_VERTEX_SHADER]) {
769 GLint tmp;
770 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
771 gl_info->max_vertex_samplers = tmp;
772 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
773 gl_info->max_combined_samplers = tmp;
775 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
776 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
777 * an issue because then the sampler setup only depends on the two shaders. If a pixel
778 * shader is used with fixed function vertex processing we're fine too because fixed function
779 * vertex processing doesn't use any samplers. If fixed function fragment processing is
780 * used we have to make sure that all vertex sampler setups are valid together with all
781 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
782 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
783 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
784 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
785 * a fixed function pipeline anymore.
787 * So this is just a check to check that our assumption holds true. If not, write a warning
788 * and reduce the number of vertex samplers or propably disable vertex texture fetch.
790 if(gl_info->max_vertex_samplers &&
791 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
792 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
793 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
794 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
795 gl_info->max_vertex_samplers = max(0, gl_info->max_combined_samplers - MAX_TEXTURES);
797 } else {
798 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
800 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
801 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
803 if (gl_info->supported[ARB_VERTEX_BLEND]) {
804 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
805 gl_info->max_blends = gl_max;
806 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
808 if (gl_info->supported[EXT_TEXTURE3D]) {
809 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
810 gl_info->max_texture3d_size = gl_max;
811 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
813 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
814 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
815 gl_info->max_anisotropy = gl_max;
816 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
818 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
819 gl_info->ps_arb_version = PS_VERSION_11;
820 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
821 gl_info->ps_arb_constantsF = gl_max;
822 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
823 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
824 gl_info->ps_arb_max_temps = gl_max;
825 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
826 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
827 gl_info->ps_arb_max_instructions = gl_max;
828 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
830 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
831 gl_info->vs_arb_version = VS_VERSION_11;
832 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
833 gl_info->vs_arb_constantsF = gl_max;
834 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
835 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
836 gl_info->vs_arb_max_temps = gl_max;
837 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
838 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
839 gl_info->vs_arb_max_instructions = gl_max;
840 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
842 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
844 if (gl_info->supported[ARB_VERTEX_SHADER]) {
845 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
846 gl_info->vs_glsl_constantsF = gl_max / 4;
847 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
849 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
850 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
851 gl_info->ps_glsl_constantsF = gl_max / 4;
852 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
853 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
854 gl_info->max_glsl_varyings = gl_max;
855 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
857 if (gl_info->supported[EXT_VERTEX_SHADER]) {
858 gl_info->vs_ati_version = VS_VERSION_11;
860 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
861 gl_info->vs_nv_version = VS_VERSION_30;
862 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
863 gl_info->vs_nv_version = VS_VERSION_20;
864 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
865 gl_info->vs_nv_version = VS_VERSION_11;
866 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
867 gl_info->vs_nv_version = VS_VERSION_10;
869 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
870 gl_info->ps_nv_version = PS_VERSION_30;
871 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
872 gl_info->ps_nv_version = PS_VERSION_20;
874 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
875 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
876 * This saves a few redundant glDisable calls
878 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
882 checkGLcall("extension detection\n");
884 /* In some cases the number of texture stages can be larger than the number
885 * of samplers. The GF4 for example can use only 2 samplers (no fragment
886 * shaders), but 8 texture stages (register combiners). */
887 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
889 /* We can only use ORM_FBO when the hardware supports it. */
890 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
891 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
892 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
895 /* MRTs are currently only supported when FBOs are used. */
896 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
897 gl_info->max_buffers = 1;
900 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
901 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
902 * in case of the latest videocards in the number of pixel/vertex pipelines.
904 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
905 * rendering. Various games use this information to get a rough estimation of the features of the card
906 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
907 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
908 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
909 * not the PCI id.
911 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
912 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
913 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
914 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
915 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
916 * is used for rendering which is not always the case). This would work but it is not very portable. Second
917 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
918 * is limited.
920 * As said most games only use the PCI id to get an indication of the capabilities of the card.
921 * It doesn't really matter if the given id is the correct one if we return the id of a card with
922 * similar 3d features.
924 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
925 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
926 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
927 * won't pass we return a default card. This way is better than maintaining a full card database as even
928 * without a full database we can return a card with similar features. Second the size of the database
929 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
930 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
931 * to distinguishes between different models from that family.
933 * The code also selects a default amount of video memory which we will use for an estimation of the amount
934 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
935 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
936 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
937 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
938 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
939 * memory behind our backs if really needed.
940 * Note that the amout of video memory can be overruled using a registry setting.
942 switch (gl_info->gl_vendor) {
943 case VENDOR_NVIDIA:
944 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
945 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
947 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
948 /* Geforce8 - highend */
949 if (strstr(gl_info->gl_renderer, "8800")) {
950 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
951 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
953 /* Geforce8 - midend */
954 else if(strstr(gl_info->gl_renderer, "8600") ||
955 strstr(gl_info->gl_renderer, "8700"))
957 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
958 vidmem = 256;
960 /* Geforce8 - midend mobile */
961 else if(strstr(gl_info->gl_renderer, "8600 M")) {
962 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
963 vidmem = 512;
965 /* Geforce8 - lowend */
966 else if(strstr(gl_info->gl_renderer, "8300") ||
967 strstr(gl_info->gl_renderer, "8400") ||
968 strstr(gl_info->gl_renderer, "8500"))
970 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
971 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
973 /* Geforce7 - highend */
974 else if(strstr(gl_info->gl_renderer, "7800") ||
975 strstr(gl_info->gl_renderer, "7900") ||
976 strstr(gl_info->gl_renderer, "7950") ||
977 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
978 strstr(gl_info->gl_renderer, "Quadro FX 5"))
980 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
981 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
983 /* Geforce7 midend */
984 else if(strstr(gl_info->gl_renderer, "7600") ||
985 strstr(gl_info->gl_renderer, "7700")) {
986 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
987 vidmem = 256; /* The 7600 uses 256-512MB */
988 /* Geforce7 lower medium */
989 } else if(strstr(gl_info->gl_renderer, "7400")) {
990 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
991 vidmem = 256; /* The 7400 uses 256-512MB */
993 /* Geforce6 highend */
994 else if(strstr(gl_info->gl_renderer, "6800"))
996 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
997 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
999 /* Geforce6 - midend */
1000 else if(strstr(gl_info->gl_renderer, "6600") ||
1001 strstr(gl_info->gl_renderer, "6610") ||
1002 strstr(gl_info->gl_renderer, "6700"))
1004 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1005 vidmem = 128; /* A 6600GT has 128-256MB */
1007 /* Geforce6/7 lowend */
1008 else {
1009 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1010 vidmem = 64; /* */
1012 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1013 /* GeforceFX - highend */
1014 if (strstr(gl_info->gl_renderer, "5800") ||
1015 strstr(gl_info->gl_renderer, "5900") ||
1016 strstr(gl_info->gl_renderer, "5950") ||
1017 strstr(gl_info->gl_renderer, "Quadro FX"))
1019 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1020 vidmem = 256; /* 5800-5900 cards use 256MB */
1022 /* GeforceFX - midend */
1023 else if(strstr(gl_info->gl_renderer, "5600") ||
1024 strstr(gl_info->gl_renderer, "5650") ||
1025 strstr(gl_info->gl_renderer, "5700") ||
1026 strstr(gl_info->gl_renderer, "5750"))
1028 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1029 vidmem = 128; /* A 5600 uses 128-256MB */
1031 /* GeforceFX - lowend */
1032 else {
1033 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1034 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1036 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1037 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1038 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1039 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1041 else {
1042 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1043 vidmem = 64; /* Geforce3 cards have 64-128MB */
1045 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1046 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1047 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1048 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1050 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1051 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1052 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1054 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1055 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1056 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1058 else {
1059 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1060 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1062 } else {
1063 if (strstr(gl_info->gl_renderer, "TNT2")) {
1064 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1065 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1067 else {
1068 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1069 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1072 break;
1073 case VENDOR_ATI:
1074 if(WINE_D3D9_CAPABLE(gl_info)) {
1075 /* Radeon R6xx HD2900 - highend */
1076 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1077 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1078 vidmem = 512; /* HD2900 uses 512-1024MB */
1080 /* Radeon R6xx HD2600- midend */
1081 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1082 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1083 vidmem = 256; /* HD2600 uses 256-512MB */
1085 /* Radeon R6xx HD2300/HD2400 - lowend */
1086 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1087 strstr(gl_info->gl_renderer, "HD 2400"))
1089 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1090 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1092 /* Radeon R5xx */
1093 else if (strstr(gl_info->gl_renderer, "X1600") ||
1094 strstr(gl_info->gl_renderer, "X1650") ||
1095 strstr(gl_info->gl_renderer, "X1800") ||
1096 strstr(gl_info->gl_renderer, "X1900") ||
1097 strstr(gl_info->gl_renderer, "X1950"))
1099 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1100 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1102 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1103 else if(strstr(gl_info->gl_renderer, "X700") ||
1104 strstr(gl_info->gl_renderer, "X800") ||
1105 strstr(gl_info->gl_renderer, "X850") ||
1106 strstr(gl_info->gl_renderer, "X1300") ||
1107 strstr(gl_info->gl_renderer, "X1400") ||
1108 strstr(gl_info->gl_renderer, "X1450") ||
1109 strstr(gl_info->gl_renderer, "X1550"))
1111 gl_info->gl_card = CARD_ATI_RADEON_X700;
1112 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1114 /* Radeon R3xx */
1115 else {
1116 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1117 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1119 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1120 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1121 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1122 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1123 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1124 vidmem = 32; /* There are models with up to 64MB */
1125 } else {
1126 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1127 vidmem = 16; /* There are 16-32MB models */
1129 break;
1130 case VENDOR_INTEL:
1131 if (strstr(gl_info->gl_renderer, "915GM")) {
1132 gl_info->gl_card = CARD_INTEL_I915GM;
1133 } else if (strstr(gl_info->gl_renderer, "915G")) {
1134 gl_info->gl_card = CARD_INTEL_I915G;
1135 } else if (strstr(gl_info->gl_renderer, "865G")) {
1136 gl_info->gl_card = CARD_INTEL_I865G;
1137 } else if (strstr(gl_info->gl_renderer, "855G")) {
1138 gl_info->gl_card = CARD_INTEL_I855G;
1139 } else if (strstr(gl_info->gl_renderer, "830G")) {
1140 gl_info->gl_card = CARD_INTEL_I830G;
1141 } else {
1142 gl_info->gl_card = CARD_INTEL_I915G;
1144 break;
1145 case VENDOR_MESA:
1146 case VENDOR_WINE:
1147 default:
1148 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1149 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1150 * them a good generic choice.
1152 gl_info->gl_vendor = VENDOR_NVIDIA;
1153 if(WINE_D3D9_CAPABLE(gl_info))
1154 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1155 else if(WINE_D3D8_CAPABLE(gl_info))
1156 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1157 else if(WINE_D3D7_CAPABLE(gl_info))
1158 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1159 else if(WINE_D3D6_CAPABLE(gl_info))
1160 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1161 else
1162 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1164 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1166 /* If we have an estimate use it, else default to 64MB; */
1167 if(vidmem)
1168 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1169 else
1170 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1172 /* Load all the lookup tables
1173 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1174 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1175 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1177 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1178 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1181 for (i = 0; i < MAX_LOOKUPS; i++) {
1182 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1185 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1186 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1187 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1188 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1189 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1190 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1191 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1192 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1193 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1194 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1196 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1197 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1198 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1199 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1200 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1203 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1204 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1205 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1206 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1207 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1208 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1209 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1210 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1211 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1212 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1213 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1214 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1215 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1217 /* TODO: config lookups */
1219 /* Make sure there's an active HDC else the WGL extensions will fail */
1220 hdc = pwglGetCurrentDC();
1221 if (hdc) {
1222 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1223 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1225 if (NULL == WGL_Extensions) {
1226 ERR(" WGL_Extensions returns NULL\n");
1227 } else {
1228 while (*WGL_Extensions != 0x00) {
1229 const char *Start;
1230 char ThisExtn[256];
1231 size_t len;
1233 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1234 Start = WGL_Extensions;
1235 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1236 WGL_Extensions++;
1239 len = WGL_Extensions - Start;
1240 if (len == 0 || len >= sizeof(ThisExtn))
1241 continue;
1243 memcpy(ThisExtn, Start, len);
1244 ThisExtn[len] = '\0';
1245 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1247 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1248 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1249 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1254 LEAVE_GL();
1256 return return_value;
1258 #undef GLINFO_LOCATION
1260 /**********************************************************
1261 * IWineD3D implementation follows
1262 **********************************************************/
1264 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1265 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1267 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1268 return numAdapters;
1271 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1272 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1273 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1274 return WINED3D_OK;
1277 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1278 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1280 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1281 return NULL;
1284 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1285 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1288 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1289 of the same bpp but different resolutions */
1291 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1292 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1293 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1294 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1296 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1297 return 0;
1300 /* TODO: Store modes per adapter and read it from the adapter structure */
1301 if (Adapter == 0) { /* Display */
1302 int i = 0;
1303 int j = 0;
1305 if (!DEBUG_SINGLE_MODE) {
1306 DEVMODEW DevModeW;
1308 ZeroMemory(&DevModeW, sizeof(DevModeW));
1309 DevModeW.dmSize = sizeof(DevModeW);
1310 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1311 j++;
1312 switch (Format)
1314 case WINED3DFMT_UNKNOWN:
1315 /* This is for D3D8, do not enumerate P8 here */
1316 if (DevModeW.dmBitsPerPel == 32 ||
1317 DevModeW.dmBitsPerPel == 16) i++;
1318 break;
1319 case WINED3DFMT_X8R8G8B8:
1320 if (DevModeW.dmBitsPerPel == 32) i++;
1321 break;
1322 case WINED3DFMT_R5G6B5:
1323 if (DevModeW.dmBitsPerPel == 16) i++;
1324 break;
1325 case WINED3DFMT_P8:
1326 if (DevModeW.dmBitsPerPel == 8) i++;
1327 break;
1328 default:
1329 /* Skip other modes as they do not match the requested format */
1330 break;
1333 } else {
1334 i = 1;
1335 j = 1;
1338 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1339 return i;
1340 } else {
1341 FIXME_(d3d_caps)("Adapter not primary display\n");
1343 return 0;
1346 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1347 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1348 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1349 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1351 /* Validate the parameters as much as possible */
1352 if (NULL == pMode ||
1353 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1354 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1355 return WINED3DERR_INVALIDCALL;
1358 /* TODO: Store modes per adapter and read it from the adapter structure */
1359 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1360 DEVMODEW DevModeW;
1361 int ModeIdx = 0;
1362 int i = 0;
1363 int j = 0;
1365 ZeroMemory(&DevModeW, sizeof(DevModeW));
1366 DevModeW.dmSize = sizeof(DevModeW);
1368 /* If we are filtering to a specific format (D3D9), then need to skip
1369 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1370 just count through the ones with valid bit depths */
1371 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1372 switch (Format)
1374 case WINED3DFMT_UNKNOWN:
1375 /* This is D3D8. Do not enumerate P8 here */
1376 if (DevModeW.dmBitsPerPel == 32 ||
1377 DevModeW.dmBitsPerPel == 16) i++;
1378 break;
1379 case WINED3DFMT_X8R8G8B8:
1380 if (DevModeW.dmBitsPerPel == 32) i++;
1381 break;
1382 case WINED3DFMT_R5G6B5:
1383 if (DevModeW.dmBitsPerPel == 16) i++;
1384 break;
1385 case WINED3DFMT_P8:
1386 if (DevModeW.dmBitsPerPel == 8) i++;
1387 break;
1388 default:
1389 /* Modes that don't match what we support can get an early-out */
1390 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1391 return WINED3DERR_INVALIDCALL;
1395 if (i == 0) {
1396 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1397 return WINED3DERR_INVALIDCALL;
1399 ModeIdx = j - 1;
1401 /* Now get the display mode via the calculated index */
1402 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1403 pMode->Width = DevModeW.dmPelsWidth;
1404 pMode->Height = DevModeW.dmPelsHeight;
1405 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1406 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1407 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1409 if (Format == WINED3DFMT_UNKNOWN)
1411 switch (DevModeW.dmBitsPerPel)
1413 case 8:
1414 pMode->Format = WINED3DFMT_P8;
1415 break;
1416 case 16:
1417 pMode->Format = WINED3DFMT_R5G6B5;
1418 break;
1419 case 32:
1420 pMode->Format = WINED3DFMT_X8R8G8B8;
1421 break;
1422 default:
1423 pMode->Format = WINED3DFMT_UNKNOWN;
1424 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1426 } else {
1427 pMode->Format = Format;
1429 } else {
1430 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1431 return WINED3DERR_INVALIDCALL;
1434 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1435 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1436 DevModeW.dmBitsPerPel);
1438 } else if (DEBUG_SINGLE_MODE) {
1439 /* Return one setting of the format requested */
1440 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1441 pMode->Width = 800;
1442 pMode->Height = 600;
1443 pMode->RefreshRate = 60;
1444 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1445 } else {
1446 FIXME_(d3d_caps)("Adapter not primary display\n");
1449 return WINED3D_OK;
1452 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1453 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1454 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1456 if (NULL == pMode ||
1457 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1458 return WINED3DERR_INVALIDCALL;
1461 if (Adapter == 0) { /* Display */
1462 int bpp = 0;
1463 DEVMODEW DevModeW;
1465 ZeroMemory(&DevModeW, sizeof(DevModeW));
1466 DevModeW.dmSize = sizeof(DevModeW);
1468 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1469 pMode->Width = DevModeW.dmPelsWidth;
1470 pMode->Height = DevModeW.dmPelsHeight;
1471 bpp = DevModeW.dmBitsPerPel;
1472 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1473 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1475 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1478 switch (bpp) {
1479 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1480 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1481 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1482 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1483 default: pMode->Format = WINED3DFMT_UNKNOWN;
1486 } else {
1487 FIXME_(d3d_caps)("Adapter not primary display\n");
1490 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1491 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1492 return WINED3D_OK;
1495 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1496 and fields being inserted in the middle, a new structure is used in place */
1497 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1498 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1499 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1501 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1503 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1504 return WINED3DERR_INVALIDCALL;
1507 /* Return the information requested */
1508 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1509 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1510 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1512 /* Note dx8 doesn't supply a DeviceName */
1513 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1514 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1515 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1516 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1517 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1518 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1519 *(pIdentifier->SubSysId) = 0;
1520 *(pIdentifier->Revision) = 0;
1522 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1523 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1524 *(pIdentifier->WHQLLevel) = 0;
1525 } else {
1526 *(pIdentifier->WHQLLevel) = 1;
1529 return WINED3D_OK;
1532 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1533 short redSize, greenSize, blueSize, alphaSize, colorBits;
1535 if(!cfg)
1536 return FALSE;
1538 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1539 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1540 return FALSE;
1543 if(cfg->redSize < redSize)
1544 return FALSE;
1546 if(cfg->greenSize < greenSize)
1547 return FALSE;
1549 if(cfg->blueSize < blueSize)
1550 return FALSE;
1552 if(cfg->alphaSize < alphaSize)
1553 return FALSE;
1555 return TRUE;
1558 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1559 short depthSize, stencilSize;
1561 if(!cfg)
1562 return FALSE;
1564 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1565 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1566 return FALSE;
1569 if(cfg->depthSize < depthSize)
1570 return FALSE;
1572 if(cfg->stencilSize < stencilSize)
1573 return FALSE;
1575 return TRUE;
1578 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1579 WINED3DFORMAT AdapterFormat,
1580 WINED3DFORMAT RenderTargetFormat,
1581 WINED3DFORMAT DepthStencilFormat) {
1582 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1583 int nCfgs;
1584 WineD3D_PixelFormat *cfgs;
1585 int it;
1587 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1588 This, Adapter,
1589 DeviceType, debug_d3ddevicetype(DeviceType),
1590 AdapterFormat, debug_d3dformat(AdapterFormat),
1591 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1592 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1594 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1595 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1596 return WINED3DERR_INVALIDCALL;
1599 cfgs = Adapters[Adapter].cfgs;
1600 nCfgs = Adapters[Adapter].nCfgs;
1601 for (it = 0; it < nCfgs; ++it) {
1602 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1603 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1604 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1605 return WINED3D_OK;
1609 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1611 return WINED3DERR_NOTAVAILABLE;
1614 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1615 WINED3DFORMAT SurfaceFormat,
1616 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1618 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1619 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1620 This,
1621 Adapter,
1622 DeviceType, debug_d3ddevicetype(DeviceType),
1623 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1624 Windowed,
1625 MultiSampleType,
1626 pQualityLevels);
1628 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1629 return WINED3DERR_INVALIDCALL;
1632 /* TODO: Store in Adapter structure */
1633 if (pQualityLevels != NULL) {
1634 static int s_single_shot = 0;
1635 if (!s_single_shot) {
1636 FIXME("Quality levels unsupported at present\n");
1637 s_single_shot = 1;
1639 *pQualityLevels = 1; /* Guess at a value! */
1642 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1643 return WINED3DERR_NOTAVAILABLE;
1646 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1647 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1649 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1650 int nCfgs = 0;
1651 WineD3D_PixelFormat *cfgs;
1652 int it;
1653 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1655 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1656 This,
1657 Adapter,
1658 CheckType, debug_d3ddevicetype(CheckType),
1659 DisplayFormat, debug_d3dformat(DisplayFormat),
1660 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1661 Windowed);
1663 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1664 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1665 return WINED3DERR_INVALIDCALL;
1668 cfgs = Adapters[Adapter].cfgs;
1669 nCfgs = Adapters[Adapter].nCfgs;
1670 for (it = 0; it < nCfgs; ++it) {
1671 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1672 hr = WINED3D_OK;
1673 TRACE_(d3d_caps)("OK\n");
1674 break ;
1678 if(hr != WINED3D_OK)
1679 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1681 if(hr != WINED3D_OK)
1682 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1684 return hr;
1687 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1688 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1689 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1690 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1691 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1692 This,
1693 Adapter,
1694 DeviceType, debug_d3ddevicetype(DeviceType),
1695 AdapterFormat, debug_d3dformat(AdapterFormat),
1696 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1697 RType, debug_d3dresourcetype(RType),
1698 CheckFormat, debug_d3dformat(CheckFormat));
1700 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1701 return WINED3DERR_INVALIDCALL;
1704 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1705 switch (CheckFormat) {
1706 /* Filtering not supported */
1707 case WINED3DFMT_R32F:
1708 case WINED3DFMT_A32B32G32R32F:
1709 TRACE_(d3d_caps)("[FAILED]\n");
1710 return WINED3DERR_NOTAVAILABLE;
1711 default:
1712 break;
1716 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1717 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1718 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1719 return WINED3DERR_NOTAVAILABLE;
1723 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1724 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1725 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1726 return WINED3DERR_NOTAVAILABLE;
1728 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1729 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1730 * app needing one of those formats, don't advertize them to avoid leading apps into
1731 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1732 * except of R32F.
1734 switch(CheckFormat) {
1735 case WINED3DFMT_P8:
1736 case WINED3DFMT_A4L4:
1737 case WINED3DFMT_R32F:
1738 case WINED3DFMT_R16F:
1739 case WINED3DFMT_X8L8V8U8:
1740 case WINED3DFMT_L6V5U5:
1741 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1742 return WINED3DERR_NOTAVAILABLE;
1744 case WINED3DFMT_Q8W8V8U8:
1745 case WINED3DFMT_V16U16:
1746 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1747 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1748 return WINED3DERR_NOTAVAILABLE;
1750 break;
1752 case WINED3DFMT_V8U8:
1753 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1754 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1755 return WINED3DERR_NOTAVAILABLE;
1757 break;
1759 case WINED3DFMT_DXT1:
1760 case WINED3DFMT_DXT2:
1761 case WINED3DFMT_DXT3:
1762 case WINED3DFMT_DXT4:
1763 case WINED3DFMT_DXT5:
1764 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1765 * compressed texture results in an error. While the D3D refrast does
1766 * support s3tc volumes, at least the nvidia windows driver does not, so
1767 * we're free not to support this format.
1769 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1770 return WINED3DERR_NOTAVAILABLE;
1772 default:
1773 /* Do nothing, continue with checking the format below */
1774 break;
1777 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1778 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1779 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1780 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1781 if (!GL_LIMITS(vertex_samplers)) {
1782 TRACE_(d3d_caps)("[FAILED]\n");
1783 return WINED3DERR_NOTAVAILABLE;
1786 switch (CheckFormat) {
1787 case WINED3DFMT_A32B32G32R32F:
1788 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1789 TRACE_(d3d_caps)("[FAILED]\n");
1790 return WINED3DERR_NOTAVAILABLE;
1792 TRACE_(d3d_caps)("[OK]\n");
1793 return WINED3D_OK;
1795 default:
1796 TRACE_(d3d_caps)("[FAILED]\n");
1797 return WINED3DERR_NOTAVAILABLE;
1801 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1802 switch (CheckFormat) {
1803 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1804 * Windows supports only those 3, and enumerating the other formats confuses applications
1806 case WINED3DFMT_D24S8:
1807 case WINED3DFMT_D24X8:
1808 case WINED3DFMT_D16:
1809 TRACE_(d3d_caps)("[OK]\n");
1810 return WINED3D_OK;
1811 case WINED3DFMT_D16_LOCKABLE:
1812 case WINED3DFMT_D24FS8:
1813 case WINED3DFMT_D32F_LOCKABLE:
1814 case WINED3DFMT_D24X4S4:
1815 case WINED3DFMT_D15S1:
1816 case WINED3DFMT_D32:
1817 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1818 return WINED3DERR_NOTAVAILABLE;
1819 default:
1820 TRACE_(d3d_caps)("[FAILED]\n");
1821 return WINED3DERR_NOTAVAILABLE;
1823 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1824 switch (CheckFormat) {
1825 case WINED3DFMT_R8G8B8:
1826 case WINED3DFMT_A8R8G8B8:
1827 case WINED3DFMT_X8R8G8B8:
1828 case WINED3DFMT_R5G6B5:
1829 case WINED3DFMT_X1R5G5B5:
1830 case WINED3DFMT_A1R5G5B5:
1831 case WINED3DFMT_A4R4G4B4:
1832 case WINED3DFMT_R3G3B2:
1833 case WINED3DFMT_X4R4G4B4:
1834 case WINED3DFMT_A8B8G8R8:
1835 case WINED3DFMT_X8B8G8R8:
1836 case WINED3DFMT_P8:
1837 TRACE_(d3d_caps)("[OK]\n");
1838 return WINED3D_OK;
1839 case WINED3DFMT_R16F:
1840 case WINED3DFMT_A16B16G16R16F:
1841 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1842 TRACE_(d3d_caps)("[FAILED]\n");
1843 return WINED3DERR_NOTAVAILABLE;
1845 TRACE_(d3d_caps)("[OK]\n");
1846 return WINED3D_OK;
1847 case WINED3DFMT_A32B32G32R32F:
1848 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1849 TRACE_(d3d_caps)("[FAILED]\n");
1850 return WINED3DERR_NOTAVAILABLE;
1852 TRACE_(d3d_caps)("[OK]\n");
1853 return WINED3D_OK;
1854 default:
1855 TRACE_(d3d_caps)("[FAILED]\n");
1856 return WINED3DERR_NOTAVAILABLE;
1858 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1859 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1860 switch (CheckFormat) {
1861 case WINED3DFMT_V8U8:
1862 TRACE_(d3d_caps)("[OK]\n");
1863 return WINED3D_OK;
1864 /* TODO: Other bump map formats */
1865 default:
1866 TRACE_(d3d_caps)("[FAILED]\n");
1867 return WINED3DERR_NOTAVAILABLE;
1870 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1871 switch (CheckFormat) {
1872 case WINED3DFMT_V8U8:
1873 TRACE_(d3d_caps)("[OK]\n");
1874 return WINED3D_OK;
1875 default:
1876 TRACE_(d3d_caps)("[FAILED]\n");
1877 return WINED3DERR_NOTAVAILABLE;
1880 TRACE_(d3d_caps)("[FAILED]\n");
1881 return WINED3DERR_NOTAVAILABLE;
1884 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1885 switch (CheckFormat) {
1886 case WINED3DFMT_DXT1:
1887 case WINED3DFMT_DXT2:
1888 case WINED3DFMT_DXT3:
1889 case WINED3DFMT_DXT4:
1890 case WINED3DFMT_DXT5:
1891 TRACE_(d3d_caps)("[OK]\n");
1892 return WINED3D_OK;
1893 default:
1894 break; /* Avoid compiler warnings */
1898 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1899 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1900 switch (CheckFormat) {
1901 case WINED3DFMT_A8R8G8B8:
1902 case WINED3DFMT_X8R8G8B8:
1903 case WINED3DFMT_A4R4G4B4:
1904 case WINED3DFMT_L8:
1905 case WINED3DFMT_A8L8:
1906 case WINED3DFMT_DXT1:
1907 case WINED3DFMT_DXT2:
1908 case WINED3DFMT_DXT3:
1909 case WINED3DFMT_DXT4:
1910 case WINED3DFMT_DXT5:
1911 TRACE_(d3d_caps)("[OK]\n");
1912 return WINED3D_OK;
1914 default:
1915 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1916 return WINED3DERR_NOTAVAILABLE;
1920 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1922 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1924 switch (CheckFormat) {
1925 case WINED3DFMT_R16F:
1926 case WINED3DFMT_A16B16G16R16F:
1927 if (!half_pixel_support) break;
1928 case WINED3DFMT_R32F:
1929 case WINED3DFMT_A32B32G32R32F:
1930 TRACE_(d3d_caps)("[OK]\n");
1931 return WINED3D_OK;
1932 default:
1933 break; /* Avoid compiler warnings */
1937 /* This format is nothing special and it is supported perfectly.
1938 * However, ati and nvidia driver on windows do not mark this format as
1939 * supported (tested with the dxCapsViewer) and pretending to
1940 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1941 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1942 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1944 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1945 TRACE_(d3d_caps)("[FAILED]\n");
1946 return WINED3DERR_NOTAVAILABLE;
1949 switch (CheckFormat) {
1951 /*****
1952 * supported: RGB(A) formats
1954 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1955 case WINED3DFMT_A8R8G8B8:
1956 case WINED3DFMT_X8R8G8B8:
1957 case WINED3DFMT_R5G6B5:
1958 case WINED3DFMT_X1R5G5B5:
1959 case WINED3DFMT_A1R5G5B5:
1960 case WINED3DFMT_A4R4G4B4:
1961 case WINED3DFMT_R3G3B2:
1962 case WINED3DFMT_A8:
1963 case WINED3DFMT_X4R4G4B4:
1964 case WINED3DFMT_A8B8G8R8:
1965 case WINED3DFMT_X8B8G8R8:
1966 case WINED3DFMT_A2R10G10B10:
1967 case WINED3DFMT_A2B10G10R10:
1968 TRACE_(d3d_caps)("[OK]\n");
1969 return WINED3D_OK;
1971 /*****
1972 * supported: Palettized
1974 case WINED3DFMT_P8:
1975 TRACE_(d3d_caps)("[OK]\n");
1976 return WINED3D_OK;
1978 /*****
1979 * Supported: (Alpha)-Luminance
1981 case WINED3DFMT_L8:
1982 case WINED3DFMT_A8L8:
1983 case WINED3DFMT_A4L4:
1984 TRACE_(d3d_caps)("[OK]\n");
1985 return WINED3D_OK;
1987 /*****
1988 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1989 * GL_NV_texture_shader), but advertized to make apps happy.
1990 * Enable some because games often fail when they are not available
1991 * and are still playable even without bump mapping
1993 case WINED3DFMT_V8U8:
1994 case WINED3DFMT_V16U16:
1995 case WINED3DFMT_L6V5U5:
1996 case WINED3DFMT_X8L8V8U8:
1997 case WINED3DFMT_Q8W8V8U8:
1998 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1999 return WINED3D_OK;
2001 /* Those are not advertized by the nvidia windows driver, and not
2002 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
2003 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
2004 * ARGB format if needed
2006 case WINED3DFMT_W11V11U10:
2007 case WINED3DFMT_A2W10V10U10:
2008 WARN_(d3d_caps)("[FAILED]\n");
2009 return WINED3DERR_NOTAVAILABLE;
2011 /*****
2012 * DXTN Formats: Handled above
2013 * WINED3DFMT_DXT1
2014 * WINED3DFMT_DXT2
2015 * WINED3DFMT_DXT3
2016 * WINED3DFMT_DXT4
2017 * WINED3DFMT_DXT5
2020 /*****
2021 * Odd formats - not supported
2023 case WINED3DFMT_VERTEXDATA:
2024 case WINED3DFMT_INDEX16:
2025 case WINED3DFMT_INDEX32:
2026 case WINED3DFMT_Q16W16V16U16:
2027 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2028 return WINED3DERR_NOTAVAILABLE;
2030 /*****
2031 * Float formats: Not supported right now
2033 case WINED3DFMT_G16R16F:
2034 case WINED3DFMT_G32R32F:
2035 case WINED3DFMT_CxV8U8:
2036 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2037 return WINED3DERR_NOTAVAILABLE;
2039 /* Not supported */
2040 case WINED3DFMT_G16R16:
2041 case WINED3DFMT_A16B16G16R16:
2042 case WINED3DFMT_A8R3G3B2:
2043 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2044 return WINED3DERR_NOTAVAILABLE;
2046 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2047 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2048 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2049 * We can do instancing with all shader versions, but we need vertex shaders.
2051 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2052 * to enable instancing. WineD3D doesn't need that and just ignores it.
2054 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2056 case WINEMAKEFOURCC('I','N','S','T'):
2057 TRACE("ATI Instancing check hack\n");
2058 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2059 TRACE_(d3d_caps)("[OK]\n");
2060 return WINED3D_OK;
2061 } else {
2062 TRACE_(d3d_caps)("[FAILED]\n");
2063 return WINED3DERR_NOTAVAILABLE;
2066 default:
2067 break;
2070 TRACE_(d3d_caps)("[FAILED]\n");
2071 return WINED3DERR_NOTAVAILABLE;
2074 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2075 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2076 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2078 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2079 This,
2080 Adapter,
2081 DeviceType, debug_d3ddevicetype(DeviceType),
2082 SourceFormat, debug_d3dformat(SourceFormat),
2083 TargetFormat, debug_d3dformat(TargetFormat));
2084 return WINED3D_OK;
2087 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2088 subset of a D3DCAPS9 structure. However, it has to come via a void *
2089 as the d3d8 interface cannot import the d3d9 header */
2090 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2092 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2093 int vs_selected_mode;
2094 int ps_selected_mode;
2096 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2098 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2099 return WINED3DERR_INVALIDCALL;
2102 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2104 /* This function should *not* be modifying GL caps
2105 * TODO: move the functionality where it belongs */
2106 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2108 /* ------------------------------------------------
2109 The following fields apply to both d3d8 and d3d9
2110 ------------------------------------------------ */
2111 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2112 *pCaps->AdapterOrdinal = Adapter;
2114 *pCaps->Caps = 0;
2115 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2116 WINED3DCAPS2_FULLSCREENGAMMA |
2117 WINED3DCAPS2_DYNAMICTEXTURES;
2118 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2119 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2121 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2122 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2123 WINED3DPRESENT_INTERVAL_ONE;
2125 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2126 WINED3DCURSORCAPS_LOWRES;
2128 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2129 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2130 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2131 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2132 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2133 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2134 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2135 WINED3DDEVCAPS_PUREDEVICE |
2136 WINED3DDEVCAPS_HWRASTERIZATION |
2137 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2138 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2139 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2140 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2141 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2142 WINED3DDEVCAPS_RTPATCHES;
2144 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2145 WINED3DPMISCCAPS_CULLCCW |
2146 WINED3DPMISCCAPS_CULLCW |
2147 WINED3DPMISCCAPS_COLORWRITEENABLE |
2148 WINED3DPMISCCAPS_CLIPTLVERTS |
2149 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2150 WINED3DPMISCCAPS_MASKZ |
2151 WINED3DPMISCCAPS_BLENDOP;
2152 /* TODO:
2153 WINED3DPMISCCAPS_NULLREFERENCE
2154 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2155 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2156 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2157 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2158 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2159 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2161 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2162 #if 0
2163 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2164 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2165 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2166 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2167 #endif
2169 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2170 WINED3DPRASTERCAPS_PAT |
2171 WINED3DPRASTERCAPS_WFOG |
2172 WINED3DPRASTERCAPS_ZFOG |
2173 WINED3DPRASTERCAPS_FOGVERTEX |
2174 WINED3DPRASTERCAPS_FOGTABLE |
2175 WINED3DPRASTERCAPS_STIPPLE |
2176 WINED3DPRASTERCAPS_SUBPIXEL |
2177 WINED3DPRASTERCAPS_ZTEST |
2178 WINED3DPRASTERCAPS_SCISSORTEST |
2179 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2180 WINED3DPRASTERCAPS_DEPTHBIAS;
2182 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2183 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2184 WINED3DPRASTERCAPS_ZBIAS |
2185 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2187 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2188 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2190 /* FIXME Add:
2191 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2192 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2193 WINED3DPRASTERCAPS_ANTIALIASEDGES
2194 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2195 WINED3DPRASTERCAPS_WBUFFER */
2197 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2198 WINED3DPCMPCAPS_EQUAL |
2199 WINED3DPCMPCAPS_GREATER |
2200 WINED3DPCMPCAPS_GREATEREQUAL |
2201 WINED3DPCMPCAPS_LESS |
2202 WINED3DPCMPCAPS_LESSEQUAL |
2203 WINED3DPCMPCAPS_NEVER |
2204 WINED3DPCMPCAPS_NOTEQUAL;
2206 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2207 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2208 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2209 WINED3DPBLENDCAPS_DESTALPHA |
2210 WINED3DPBLENDCAPS_DESTCOLOR |
2211 WINED3DPBLENDCAPS_INVDESTALPHA |
2212 WINED3DPBLENDCAPS_INVDESTCOLOR |
2213 WINED3DPBLENDCAPS_INVSRCALPHA |
2214 WINED3DPBLENDCAPS_INVSRCCOLOR |
2215 WINED3DPBLENDCAPS_ONE |
2216 WINED3DPBLENDCAPS_SRCALPHA |
2217 WINED3DPBLENDCAPS_SRCALPHASAT |
2218 WINED3DPBLENDCAPS_SRCCOLOR |
2219 WINED3DPBLENDCAPS_ZERO;
2221 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2222 WINED3DPBLENDCAPS_DESTALPHA |
2223 WINED3DPBLENDCAPS_DESTCOLOR |
2224 WINED3DPBLENDCAPS_INVDESTALPHA |
2225 WINED3DPBLENDCAPS_INVDESTCOLOR |
2226 WINED3DPBLENDCAPS_INVSRCALPHA |
2227 WINED3DPBLENDCAPS_INVSRCCOLOR |
2228 WINED3DPBLENDCAPS_ONE |
2229 WINED3DPBLENDCAPS_SRCALPHA |
2230 WINED3DPBLENDCAPS_SRCCOLOR |
2231 WINED3DPBLENDCAPS_ZERO;
2232 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2233 * according to the glBlendFunc manpage
2235 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2236 * legacy settings for srcblend only
2239 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2240 WINED3DPCMPCAPS_EQUAL |
2241 WINED3DPCMPCAPS_GREATER |
2242 WINED3DPCMPCAPS_GREATEREQUAL |
2243 WINED3DPCMPCAPS_LESS |
2244 WINED3DPCMPCAPS_LESSEQUAL |
2245 WINED3DPCMPCAPS_NEVER |
2246 WINED3DPCMPCAPS_NOTEQUAL;
2248 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2249 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2250 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2251 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2252 WINED3DPSHADECAPS_COLORFLATRGB |
2253 WINED3DPSHADECAPS_FOGFLAT |
2254 WINED3DPSHADECAPS_FOGGOURAUD |
2255 WINED3DPSHADECAPS_SPECULARFLATRGB;
2257 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2258 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2259 WINED3DPTEXTURECAPS_BORDER |
2260 WINED3DPTEXTURECAPS_MIPMAP |
2261 WINED3DPTEXTURECAPS_PROJECTED |
2262 WINED3DPTEXTURECAPS_PERSPECTIVE;
2264 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2265 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2266 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2269 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2270 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2271 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2272 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2275 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2276 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2277 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2278 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2282 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2283 WINED3DPTFILTERCAPS_MAGFPOINT |
2284 WINED3DPTFILTERCAPS_MINFLINEAR |
2285 WINED3DPTFILTERCAPS_MINFPOINT |
2286 WINED3DPTFILTERCAPS_MIPFLINEAR |
2287 WINED3DPTFILTERCAPS_MIPFPOINT |
2288 WINED3DPTFILTERCAPS_LINEAR |
2289 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2290 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2291 WINED3DPTFILTERCAPS_MIPLINEAR |
2292 WINED3DPTFILTERCAPS_MIPNEAREST |
2293 WINED3DPTFILTERCAPS_NEAREST;
2295 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2296 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2297 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2300 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2301 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2302 WINED3DPTFILTERCAPS_MAGFPOINT |
2303 WINED3DPTFILTERCAPS_MINFLINEAR |
2304 WINED3DPTFILTERCAPS_MINFPOINT |
2305 WINED3DPTFILTERCAPS_MIPFLINEAR |
2306 WINED3DPTFILTERCAPS_MIPFPOINT |
2307 WINED3DPTFILTERCAPS_LINEAR |
2308 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2309 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2310 WINED3DPTFILTERCAPS_MIPLINEAR |
2311 WINED3DPTFILTERCAPS_MIPNEAREST |
2312 WINED3DPTFILTERCAPS_NEAREST;
2314 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2315 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2316 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2318 } else
2319 *pCaps->CubeTextureFilterCaps = 0;
2321 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2322 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2323 WINED3DPTFILTERCAPS_MAGFPOINT |
2324 WINED3DPTFILTERCAPS_MINFLINEAR |
2325 WINED3DPTFILTERCAPS_MINFPOINT |
2326 WINED3DPTFILTERCAPS_MIPFLINEAR |
2327 WINED3DPTFILTERCAPS_MIPFPOINT |
2328 WINED3DPTFILTERCAPS_LINEAR |
2329 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2330 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2331 WINED3DPTFILTERCAPS_MIPLINEAR |
2332 WINED3DPTFILTERCAPS_MIPNEAREST |
2333 WINED3DPTFILTERCAPS_NEAREST;
2334 } else
2335 *pCaps->VolumeTextureFilterCaps = 0;
2337 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2338 WINED3DPTADDRESSCAPS_CLAMP |
2339 WINED3DPTADDRESSCAPS_WRAP;
2341 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2342 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2344 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2345 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2347 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2348 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2351 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2352 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2353 WINED3DPTADDRESSCAPS_CLAMP |
2354 WINED3DPTADDRESSCAPS_WRAP;
2355 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2356 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2358 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2359 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2361 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2362 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2364 } else
2365 *pCaps->VolumeTextureAddressCaps = 0;
2367 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2368 WINED3DLINECAPS_ZTEST;
2369 /* FIXME: Add
2370 WINED3DLINECAPS_BLEND
2371 WINED3DLINECAPS_ALPHACMP
2372 WINED3DLINECAPS_FOG */
2374 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2375 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2377 if(GL_SUPPORT(EXT_TEXTURE3D))
2378 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2379 else
2380 *pCaps->MaxVolumeExtent = 0;
2382 *pCaps->MaxTextureRepeat = 32768;
2383 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2384 *pCaps->MaxVertexW = 1.0;
2386 *pCaps->GuardBandLeft = 0;
2387 *pCaps->GuardBandTop = 0;
2388 *pCaps->GuardBandRight = 0;
2389 *pCaps->GuardBandBottom = 0;
2391 *pCaps->ExtentsAdjust = 0;
2393 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2394 WINED3DSTENCILCAPS_INCRSAT |
2395 WINED3DSTENCILCAPS_INVERT |
2396 WINED3DSTENCILCAPS_KEEP |
2397 WINED3DSTENCILCAPS_REPLACE |
2398 WINED3DSTENCILCAPS_ZERO;
2399 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2400 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2401 WINED3DSTENCILCAPS_INCR;
2403 if ( This->dxVersion > 8 &&
2404 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2405 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2406 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2409 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2411 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2412 WINED3DTEXOPCAPS_ADDSIGNED |
2413 WINED3DTEXOPCAPS_ADDSIGNED2X |
2414 WINED3DTEXOPCAPS_MODULATE |
2415 WINED3DTEXOPCAPS_MODULATE2X |
2416 WINED3DTEXOPCAPS_MODULATE4X |
2417 WINED3DTEXOPCAPS_SELECTARG1 |
2418 WINED3DTEXOPCAPS_SELECTARG2 |
2419 WINED3DTEXOPCAPS_DISABLE;
2421 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2422 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2423 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2424 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2425 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2426 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2427 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2428 WINED3DTEXOPCAPS_LERP |
2429 WINED3DTEXOPCAPS_SUBTRACT;
2431 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2432 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2433 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2434 WINED3DTEXOPCAPS_MULTIPLYADD |
2435 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2436 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2437 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2439 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2440 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2442 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2443 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2444 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2447 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2448 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2449 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2450 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2451 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2452 * and 3D textures. It also allows us to keep the code simpler by having texture
2453 * shaders constantly enabled.
2455 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2456 /* TODO: Luminance bump map? */
2458 #if 0
2459 /* FIXME: Add
2460 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2461 WINED3DTEXOPCAPS_PREMODULATE */
2462 #endif
2464 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2465 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2466 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2467 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2469 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2470 *pCaps->MaxVertexBlendMatrixIndex = 0;
2472 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2473 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2476 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2477 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2478 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2479 WINED3DVTXPCAPS_LOCALVIEWER |
2480 WINED3DVTXPCAPS_VERTEXFOG |
2481 WINED3DVTXPCAPS_TEXGEN;
2482 /* FIXME: Add
2483 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2485 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2486 *pCaps->MaxVertexIndex = 0xFFFFF;
2487 *pCaps->MaxStreams = MAX_STREAMS;
2488 *pCaps->MaxStreamStride = 1024;
2490 if (vs_selected_mode == SHADER_GLSL) {
2491 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2492 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2493 * vs_nv_version which is based on NV_vertex_program.
2494 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2495 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2496 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2497 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2498 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2499 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2500 else
2501 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2502 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2503 } else if (vs_selected_mode == SHADER_ARB) {
2504 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2505 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2506 } else {
2507 *pCaps->VertexShaderVersion = 0;
2508 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2511 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2513 if (ps_selected_mode == SHADER_GLSL) {
2514 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2515 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2516 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2517 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2518 * in max native instructions. Intel and others also offer the info in this extension but they
2519 * don't support GLSL (at least on Windows).
2521 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number
2522 * of instructions is 512 or less we have to do with ps2.0 hardware.
2523 * 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.
2525 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2526 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2527 else
2528 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2529 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2530 * Direct3D minimum requirement.
2532 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2533 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2535 * The problem is that the refrast clamps temporary results in the shader to
2536 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2537 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2538 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2539 * offer a way to query this.
2541 *pCaps->PixelShader1xMaxValue = 8.0;
2542 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2543 } else if (ps_selected_mode == SHADER_ARB) {
2544 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2545 *pCaps->PixelShader1xMaxValue = 8.0;
2546 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2547 } else {
2548 *pCaps->PixelShaderVersion = 0;
2549 *pCaps->PixelShader1xMaxValue = 0.0;
2550 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2553 /* ------------------------------------------------
2554 The following fields apply to d3d9 only
2555 ------------------------------------------------ */
2556 if (This->dxVersion > 8) {
2557 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2558 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2559 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2560 *pCaps->MaxNpatchTessellationLevel = 0;
2561 *pCaps->MasterAdapterOrdinal = 0;
2562 *pCaps->AdapterOrdinalInGroup = 0;
2563 *pCaps->NumberOfAdaptersInGroup = 1;
2565 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2566 /* OpenGL supports all the formats below, perhaps not always
2567 * without conversion, but it supports them.
2568 * Further GLSL doesn't seem to have an official unsigned type so
2569 * don't advertise it yet as I'm not sure how we handle it.
2570 * We might need to add some clamping in the shader engine to
2571 * support it.
2572 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2573 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2574 WINED3DDTCAPS_UBYTE4N |
2575 WINED3DDTCAPS_SHORT2N |
2576 WINED3DDTCAPS_SHORT4N;
2577 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2578 *pCaps->DeclTypes |=
2579 WINED3DDTCAPS_FLOAT16_2 |
2580 WINED3DDTCAPS_FLOAT16_4;
2582 } else
2583 *pCaps->DeclTypes = 0;
2585 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2588 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2589 WINED3DPTFILTERCAPS_MAGFPOINT |
2590 WINED3DPTFILTERCAPS_MINFLINEAR |
2591 WINED3DPTFILTERCAPS_MAGFLINEAR;
2592 *pCaps->VertexTextureFilterCaps = 0;
2594 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2595 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2596 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2597 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2598 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2599 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2600 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2602 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2603 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2604 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2605 *pCaps->VS20Caps.Caps = 0;
2606 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2607 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2608 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2610 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2611 *pCaps->MaxVertexShader30InstructionSlots = 0;
2612 } else { /* VS 1.x */
2613 *pCaps->VS20Caps.Caps = 0;
2614 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2615 *pCaps->VS20Caps.NumTemps = 0;
2616 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2618 *pCaps->MaxVShaderInstructionsExecuted = 0;
2619 *pCaps->MaxVertexShader30InstructionSlots = 0;
2622 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2623 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2624 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2626 /* 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 */
2627 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2628 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2629 WINED3DPS20CAPS_PREDICATION |
2630 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2631 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2632 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2633 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2634 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2635 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2637 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2638 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2639 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2640 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2641 *pCaps->PS20Caps.Caps = 0;
2642 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2643 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2644 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2645 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2647 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2648 *pCaps->MaxPixelShader30InstructionSlots = 0;
2649 } else { /* PS 1.x */
2650 *pCaps->PS20Caps.Caps = 0;
2651 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2652 *pCaps->PS20Caps.NumTemps = 0;
2653 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2654 *pCaps->PS20Caps.NumInstructionSlots = 0;
2656 *pCaps->MaxPShaderInstructionsExecuted = 0;
2657 *pCaps->MaxPixelShader30InstructionSlots = 0;
2661 return WINED3D_OK;
2664 static unsigned int glsl_program_key_hash(void *key) {
2665 glsl_program_key_t *k = (glsl_program_key_t *)key;
2667 unsigned int hash = k->vshader | k->pshader << 16;
2668 hash += ~(hash << 15);
2669 hash ^= (hash >> 10);
2670 hash += (hash << 3);
2671 hash ^= (hash >> 6);
2672 hash += ~(hash << 11);
2673 hash ^= (hash >> 16);
2675 return hash;
2678 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2679 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2680 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2682 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2685 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2686 and fields being inserted in the middle, a new structure is used in place */
2687 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2688 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2689 IUnknown *parent) {
2691 IWineD3DDeviceImpl *object = NULL;
2692 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2693 HDC hDC;
2694 int i;
2696 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2697 * number and create a device without a 3D adapter for 2D only operation.
2699 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2700 return WINED3DERR_INVALIDCALL;
2703 /* Create a WineD3DDevice object */
2704 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2705 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2706 TRACE("Created WineD3DDevice object @ %p\n", object);
2707 if (NULL == object) {
2708 return WINED3DERR_OUTOFVIDEOMEMORY;
2711 /* Set up initial COM information */
2712 object->lpVtbl = &IWineD3DDevice_Vtbl;
2713 object->ref = 1;
2714 object->wineD3D = iface;
2715 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2716 IWineD3D_AddRef(object->wineD3D);
2717 object->parent = parent;
2718 list_init(&object->resources);
2720 if(This->dxVersion == 7) {
2721 object->surface_alignment = 8;
2722 } else {
2723 object->surface_alignment = 4;
2725 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2727 /* Set the state up as invalid until the device is fully created */
2728 object->state = WINED3DERR_DRIVERINTERNALERROR;
2730 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2731 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2733 /* Save the creation parameters */
2734 object->createParms.AdapterOrdinal = Adapter;
2735 object->createParms.DeviceType = DeviceType;
2736 object->createParms.hFocusWindow = hFocusWindow;
2737 object->createParms.BehaviorFlags = BehaviourFlags;
2739 /* Initialize other useful values */
2740 object->adapterNo = Adapter;
2741 object->devType = DeviceType;
2743 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2744 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2745 object->shader_backend = &glsl_shader_backend;
2746 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2747 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2748 object->shader_backend = &arb_program_shader_backend;
2749 } else {
2750 object->shader_backend = &none_shader_backend;
2753 /* set the state of the device to valid */
2754 object->state = WINED3D_OK;
2756 /* Get the initial screen setup for ddraw */
2757 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2758 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2759 hDC = GetDC(0);
2760 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2761 ReleaseDC(0, hDC);
2763 for(i = 0; i < PATCHMAP_SIZE; i++) {
2764 list_init(&object->patches[i]);
2766 return WINED3D_OK;
2768 #undef GLINFO_LOCATION
2770 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2771 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2772 IUnknown_AddRef(This->parent);
2773 *pParent = This->parent;
2774 return WINED3D_OK;
2777 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2778 IUnknown* surfaceParent;
2779 TRACE("(%p) call back\n", pSurface);
2781 /* Now, release the parent, which will take care of cleaning up the surface for us */
2782 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2783 IUnknown_Release(surfaceParent);
2784 return IUnknown_Release(surfaceParent);
2787 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2788 IUnknown* volumeParent;
2789 TRACE("(%p) call back\n", pVolume);
2791 /* Now, release the parent, which will take care of cleaning up the volume for us */
2792 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2793 IUnknown_Release(volumeParent);
2794 return IUnknown_Release(volumeParent);
2797 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2798 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2799 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2800 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2802 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2803 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2804 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2805 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2806 * is specific to the MacOS window management, and GL_APPLE_ycbcr_422 is a Quicktime specific, so
2807 * it the chance that other implementations support it is rather rare since Win32 Quicktime uses
2808 * DirectDraw, not OpenGL.
2810 if(gl_info->supported[APPLE_FENCE] &&
2811 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2812 gl_info->supported[APPLE_FLUSH_RENDER] &&
2813 gl_info->supported[APPLE_YCBCR_422]) {
2814 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2815 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2816 return TRUE;
2817 } else {
2818 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2819 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2820 return FALSE;
2824 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2825 if(implementation_is_apple(gl_info)) {
2826 /* MacOS advertises more GLSL vertex shader uniforms than support on hardware, and if more are
2827 * used it falls back to software. While the compiler can detect if the shader uses all declared
2828 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2829 * using relative addressing falls back to software.
2831 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2833 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2834 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2835 } else {
2836 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2837 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
2838 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
2841 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2842 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2843 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2844 * flag for this extension
2846 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
2847 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
2848 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
2849 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
2850 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2851 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
2852 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
2858 #define PUSH1(att) attribs[nAttribs++] = (att);
2859 #define GLINFO_LOCATION (Adapters[0].gl_info)
2860 BOOL InitAdapters(void) {
2861 static HMODULE mod_gl;
2862 BOOL ret;
2863 int ps_selected_mode, vs_selected_mode;
2865 /* No need to hold any lock. The calling library makes sure only one thread calls
2866 * wined3d simultaneously
2868 if(numAdapters > 0) return TRUE;
2870 TRACE("Initializing adapters\n");
2872 if(!mod_gl) {
2873 #ifdef USE_WIN32_OPENGL
2874 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2875 mod_gl = LoadLibraryA("opengl32.dll");
2876 if(!mod_gl) {
2877 ERR("Can't load opengl32.dll!\n");
2878 return FALSE;
2880 #else
2881 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2882 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2883 mod_gl = GetModuleHandleA("gdi32.dll");
2884 #endif
2887 /* Load WGL core functions from opengl32.dll */
2888 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2889 WGL_FUNCS_GEN;
2890 #undef USE_WGL_FUNC
2892 if(!pwglGetProcAddress) {
2893 ERR("Unable to load wglGetProcAddress!\n");
2894 return FALSE;
2897 /* Dynamically load all GL core functions */
2898 GL_FUNCS_GEN;
2899 #undef USE_GL_FUNC
2901 /* For now only one default adapter */
2903 int iPixelFormat;
2904 int attribs[8];
2905 int values[8];
2906 int nAttribs = 0;
2907 int res;
2908 WineD3D_PixelFormat *cfgs;
2909 int attribute;
2910 DISPLAY_DEVICEW DisplayDevice;
2911 HDC hdc;
2913 TRACE("Initializing default adapter\n");
2914 Adapters[0].monitorPoint.x = -1;
2915 Adapters[0].monitorPoint.y = -1;
2917 if (!WineD3D_CreateFakeGLContext()) {
2918 ERR("Failed to get a gl context for default adapter\n");
2919 HeapFree(GetProcessHeap(), 0, Adapters);
2920 WineD3D_ReleaseFakeGLContext();
2921 return FALSE;
2924 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2925 if(!ret) {
2926 ERR("Failed to initialize gl caps for default adapter\n");
2927 HeapFree(GetProcessHeap(), 0, Adapters);
2928 WineD3D_ReleaseFakeGLContext();
2929 return FALSE;
2931 ret = initPixelFormats(&Adapters[0].gl_info);
2932 if(!ret) {
2933 ERR("Failed to init gl formats\n");
2934 HeapFree(GetProcessHeap(), 0, Adapters);
2935 WineD3D_ReleaseFakeGLContext();
2936 return FALSE;
2939 hdc = pwglGetCurrentDC();
2940 if(!hdc) {
2941 ERR("Failed to get gl HDC\n");
2942 HeapFree(GetProcessHeap(), 0, Adapters);
2943 WineD3D_ReleaseFakeGLContext();
2944 return FALSE;
2947 Adapters[0].driver = "Display";
2948 Adapters[0].description = "Direct3D HAL";
2950 /* Use the VideoRamSize registry setting when set */
2951 if(wined3d_settings.emulated_textureram)
2952 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
2953 else
2954 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
2955 Adapters[0].UsedTextureRam = 0;
2956 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
2958 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2959 DisplayDevice.cb = sizeof(DisplayDevice);
2960 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2961 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2962 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2964 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2965 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2967 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2968 cfgs = Adapters[0].cfgs;
2969 PUSH1(WGL_RED_BITS_ARB)
2970 PUSH1(WGL_GREEN_BITS_ARB)
2971 PUSH1(WGL_BLUE_BITS_ARB)
2972 PUSH1(WGL_ALPHA_BITS_ARB)
2973 PUSH1(WGL_DEPTH_BITS_ARB)
2974 PUSH1(WGL_STENCIL_BITS_ARB)
2976 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2977 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
2979 if(!res)
2980 continue;
2982 /* Cache the pixel format */
2983 cfgs->iPixelFormat = iPixelFormat;
2984 cfgs->redSize = values[0];
2985 cfgs->greenSize = values[1];
2986 cfgs->blueSize = values[2];
2987 cfgs->alphaSize = values[3];
2988 cfgs->depthSize = values[4];
2989 cfgs->stencilSize = values[5];
2991 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);
2992 cfgs++;
2994 WineD3D_ReleaseFakeGLContext();
2996 fixup_extensions(&Adapters[0].gl_info);
2998 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2999 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
3002 numAdapters = 1;
3003 TRACE("%d adapters successfully initialized\n", numAdapters);
3005 return TRUE;
3007 #undef PUSH1
3008 #undef GLINFO_LOCATION
3010 /**********************************************************
3011 * IWineD3D VTbl follows
3012 **********************************************************/
3014 const IWineD3DVtbl IWineD3D_Vtbl =
3016 /* IUnknown */
3017 IWineD3DImpl_QueryInterface,
3018 IWineD3DImpl_AddRef,
3019 IWineD3DImpl_Release,
3020 /* IWineD3D */
3021 IWineD3DImpl_GetParent,
3022 IWineD3DImpl_GetAdapterCount,
3023 IWineD3DImpl_RegisterSoftwareDevice,
3024 IWineD3DImpl_GetAdapterMonitor,
3025 IWineD3DImpl_GetAdapterModeCount,
3026 IWineD3DImpl_EnumAdapterModes,
3027 IWineD3DImpl_GetAdapterDisplayMode,
3028 IWineD3DImpl_GetAdapterIdentifier,
3029 IWineD3DImpl_CheckDeviceMultiSampleType,
3030 IWineD3DImpl_CheckDepthStencilMatch,
3031 IWineD3DImpl_CheckDeviceType,
3032 IWineD3DImpl_CheckDeviceFormat,
3033 IWineD3DImpl_CheckDeviceFormatConversion,
3034 IWineD3DImpl_GetDeviceCaps,
3035 IWineD3DImpl_CreateDevice