push 421a6d0d1068c98851feb4eb01bb0e754f615ce9
[wine/hacks.git] / dlls / wined3d / directx.c
blob01e6138c1973643cb18038944e0837070a99ddfe
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
29 #endif
32 #include "config.h"
33 #include <assert.h>
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 /* Extension detection */
40 static const struct {
41 const char *extension_string;
42 GL_SupportedExt extension;
43 } EXTENSION_MAP[] = {
44 /* APPLE */
45 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE},
46 {"GL_APPLE_fence", APPLE_FENCE},
48 /* ATI */
49 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL},
50 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3},
51 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE},
52 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP},
54 /* ARB */
55 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS},
56 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM},
57 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER},
58 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL},
59 {"GL_ARB_imaging", ARB_IMAGING},
60 {"GL_ARB_multisample", ARB_MULTISAMPLE}, /* needs GLX_ARB_MULTISAMPLE as well */
61 {"GL_ARB_multitexture", ARB_MULTITEXTURE},
62 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY},
63 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT},
64 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS},
65 {"GL_ARB_point_sprite", ARB_POINT_SPRITE},
66 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP},
67 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION},
68 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP},
69 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD},
70 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE},
71 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3},
72 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT},
73 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT},
74 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO},
75 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND},
76 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT},
77 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM},
78 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER},
80 /* EXT */
81 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX},
82 {"GL_EXT_fog_coord", EXT_FOG_COORD},
83 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT},
84 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT},
85 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE},
86 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS},
87 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR},
88 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE},
89 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP},
90 {"GL_EXT_texture3D", EXT_TEXTURE3D},
91 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC},
92 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD},
93 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE},
94 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3},
95 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB},
96 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC},
97 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD},
98 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS},
99 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER},
100 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING},
102 /* NV */
103 {"GL_NV_half_float", NV_HALF_FLOAT},
104 {"GL_NV_fence", NV_FENCE},
105 {"GL_NV_fog_distance", NV_FOG_DISTANCE},
106 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM},
107 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2},
108 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS},
109 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2},
110 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION},
111 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4},
112 {"GL_NV_texture_shader", NV_TEXTURE_SHADER},
113 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2},
114 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3},
115 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY},
116 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM},
117 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1},
118 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2},
119 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3},
122 /**********************************************************
123 * Utility functions follow
124 **********************************************************/
126 /* Adapters */
127 static int numAdapters = 0;
128 static struct WineD3DAdapter Adapters[1];
130 /* lookup tables */
131 int minLookup[MAX_LOOKUPS];
132 int maxLookup[MAX_LOOKUPS];
133 DWORD *stateLookup[MAX_LOOKUPS];
135 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
139 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
140 * ie there is no GL Context - Get a default rendering context to enable the
141 * function query some info from GL
144 static int wined3d_fake_gl_context_ref = 0;
145 static BOOL wined3d_fake_gl_context_foreign;
146 static BOOL wined3d_fake_gl_context_available = FALSE;
147 static HDC wined3d_fake_gl_context_hdc = NULL;
148 static HWND wined3d_fake_gl_context_hwnd = NULL;
150 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
151 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
153 0, 0, &wined3d_fake_gl_context_cs,
154 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
155 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
156 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
158 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
160 static void WineD3D_ReleaseFakeGLContext(void) {
161 HGLRC glCtx;
163 EnterCriticalSection(&wined3d_fake_gl_context_cs);
165 if(!wined3d_fake_gl_context_available) {
166 TRACE_(d3d_caps)("context not available\n");
167 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
168 return;
171 glCtx = pwglGetCurrentContext();
173 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
174 if (0 == (--wined3d_fake_gl_context_ref) ) {
175 if(!wined3d_fake_gl_context_foreign && glCtx) {
176 TRACE_(d3d_caps)("destroying fake GL context\n");
177 pwglMakeCurrent(NULL, NULL);
178 pwglDeleteContext(glCtx);
180 if(wined3d_fake_gl_context_hdc)
181 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
182 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
183 if(wined3d_fake_gl_context_hwnd)
184 DestroyWindow(wined3d_fake_gl_context_hwnd);
185 wined3d_fake_gl_context_hwnd = NULL;
186 wined3d_fake_gl_context_available = FALSE;
188 assert(wined3d_fake_gl_context_ref >= 0);
190 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
191 LEAVE_GL();
194 static BOOL WineD3D_CreateFakeGLContext(void) {
195 HGLRC glCtx = NULL;
197 ENTER_GL();
198 EnterCriticalSection(&wined3d_fake_gl_context_cs);
200 TRACE("getting context...\n");
201 if(wined3d_fake_gl_context_ref > 0) goto ret;
202 assert(0 == wined3d_fake_gl_context_ref);
204 wined3d_fake_gl_context_foreign = TRUE;
206 glCtx = pwglGetCurrentContext();
207 if (!glCtx) {
208 PIXELFORMATDESCRIPTOR pfd;
209 int iPixelFormat;
211 wined3d_fake_gl_context_foreign = FALSE;
213 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
214 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
215 if(!wined3d_fake_gl_context_hwnd) {
216 ERR("HWND creation failed!\n");
217 goto fail;
219 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
220 if(!wined3d_fake_gl_context_hdc) {
221 ERR("GetDC failed!\n");
222 goto fail;
225 /* PixelFormat selection */
226 ZeroMemory(&pfd, sizeof(pfd));
227 pfd.nSize = sizeof(pfd);
228 pfd.nVersion = 1;
229 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
230 pfd.iPixelType = PFD_TYPE_RGBA;
231 pfd.cColorBits = 32;
232 pfd.iLayerType = PFD_MAIN_PLANE;
234 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
235 if(!iPixelFormat) {
236 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
237 ERR("Can't find a suitable iPixelFormat\n");
238 goto fail;
240 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
241 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
243 /* Create a GL context */
244 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
245 if (!glCtx) {
246 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
247 goto fail;
250 /* Make it the current GL context */
251 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
252 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
253 goto fail;
257 ret:
258 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
259 wined3d_fake_gl_context_ref++;
260 wined3d_fake_gl_context_available = TRUE;
261 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
262 return TRUE;
263 fail:
264 if(wined3d_fake_gl_context_hdc)
265 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
266 wined3d_fake_gl_context_hdc = NULL;
267 if(wined3d_fake_gl_context_hwnd)
268 DestroyWindow(wined3d_fake_gl_context_hwnd);
269 wined3d_fake_gl_context_hwnd = NULL;
270 if(glCtx) pwglDeleteContext(glCtx);
271 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
272 LEAVE_GL();
273 return FALSE;
277 /**********************************************************
278 * IUnknown parts follows
279 **********************************************************/
281 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
283 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
285 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
286 if (IsEqualGUID(riid, &IID_IUnknown)
287 || IsEqualGUID(riid, &IID_IWineD3DBase)
288 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
289 IUnknown_AddRef(iface);
290 *ppobj = This;
291 return S_OK;
293 *ppobj = NULL;
294 return E_NOINTERFACE;
297 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
298 IWineD3DImpl *This = (IWineD3DImpl *)iface;
299 ULONG refCount = InterlockedIncrement(&This->ref);
301 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
302 return refCount;
305 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
306 IWineD3DImpl *This = (IWineD3DImpl *)iface;
307 ULONG ref;
308 TRACE("(%p) : Releasing from %d\n", This, This->ref);
309 ref = InterlockedDecrement(&This->ref);
310 if (ref == 0) {
311 HeapFree(GetProcessHeap(), 0, This);
314 return ref;
317 /* Set the shader type for this device, depending on the given capabilities,
318 * the device type, and the user preferences in wined3d_settings */
320 static void select_shader_mode(
321 WineD3D_GL_Info *gl_info,
322 WINED3DDEVTYPE DeviceType,
323 int* ps_selected,
324 int* vs_selected) {
326 if (wined3d_settings.vs_mode == VS_NONE) {
327 *vs_selected = SHADER_NONE;
328 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
329 *vs_selected = SHADER_GLSL;
330 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
331 *vs_selected = SHADER_ARB;
332 } else {
333 *vs_selected = SHADER_NONE;
336 if (wined3d_settings.ps_mode == PS_NONE) {
337 *ps_selected = SHADER_NONE;
338 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
339 *ps_selected = SHADER_GLSL;
340 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
341 *ps_selected = SHADER_ARB;
342 } else {
343 *ps_selected = SHADER_NONE;
347 /** Select the number of report maximum shader constants based on the selected shader modes */
348 static void select_shader_max_constants(
349 int ps_selected_mode,
350 int vs_selected_mode,
351 WineD3D_GL_Info *gl_info) {
353 switch (vs_selected_mode) {
354 case SHADER_GLSL:
355 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
356 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
357 break;
358 case SHADER_ARB:
359 /* We have to subtract any other PARAMs that we might use in our shader programs.
360 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
361 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
362 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
363 break;
364 default:
365 gl_info->max_vshader_constantsF = 0;
366 break;
369 switch (ps_selected_mode) {
370 case SHADER_GLSL:
371 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
372 * In theory the texbem instruction may need one more shader constant too. But lets assume
373 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
374 * and lets not take away a uniform needlessly from all other shaders.
376 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
377 break;
378 case SHADER_ARB:
379 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
380 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
382 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
383 break;
384 default:
385 gl_info->max_pshader_constantsF = 0;
386 break;
390 /**********************************************************
391 * IWineD3D parts follows
392 **********************************************************/
394 #define GLINFO_LOCATION (*gl_info)
395 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
396 const char *GL_Extensions = NULL;
397 const char *WGL_Extensions = NULL;
398 const char *gl_string = NULL;
399 const char *gl_string_cursor = NULL;
400 GLint gl_max;
401 GLfloat gl_floatv[2];
402 int major = 1, minor = 0;
403 BOOL return_value = TRUE;
404 int i;
405 HDC hdc;
406 HMODULE mod_gl;
408 #ifdef USE_WIN32_OPENGL
409 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
410 mod_gl = LoadLibraryA("opengl32.dll");
411 if(!mod_gl) {
412 ERR("Can't load opengl32.dll!\n");
413 return FALSE;
415 #else
416 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
417 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
418 mod_gl = GetModuleHandleA("gdi32.dll");
419 #endif
421 /* Load WGL core functions from opengl32.dll */
422 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
423 WGL_FUNCS_GEN;
424 #undef USE_WGL_FUNC
426 if(!pwglGetProcAddress) {
427 ERR("Unable to load wglGetProcAddress!\n");
428 return FALSE;
431 /* Dynamicly load all GL core functions */
432 GL_FUNCS_GEN;
433 #undef USE_GL_FUNC
435 /* Make sure that we've got a context */
436 /* TODO: CreateFakeGLContext should really take a display as a parameter */
437 /* Only save the values obtained when a display is provided */
438 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
439 return_value = FALSE;
441 TRACE_(d3d_caps)("(%p)\n", gl_info);
443 gl_string = (const char *) glGetString(GL_RENDERER);
444 if (NULL == gl_string)
445 gl_string = "None";
446 strcpy(gl_info->gl_renderer, gl_string);
448 gl_string = (const char *) glGetString(GL_VENDOR);
449 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
450 if (gl_string != NULL) {
451 /* Fill in the GL vendor */
452 if (strstr(gl_string, "NVIDIA")) {
453 gl_info->gl_vendor = VENDOR_NVIDIA;
454 } else if (strstr(gl_string, "ATI")) {
455 gl_info->gl_vendor = VENDOR_ATI;
456 } else if (strstr(gl_string, "Intel(R)") ||
457 strstr(gl_info->gl_renderer, "Intel(R)")) {
458 gl_info->gl_vendor = VENDOR_INTEL;
459 } else if (strstr(gl_string, "Mesa")) {
460 gl_info->gl_vendor = VENDOR_MESA;
461 } else {
462 gl_info->gl_vendor = VENDOR_WINE;
464 } else {
465 gl_info->gl_vendor = VENDOR_WINE;
469 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
471 /* Parse the GL_VERSION field into major and minor information */
472 gl_string = (const char *) glGetString(GL_VERSION);
473 if (gl_string != NULL) {
475 switch (gl_info->gl_vendor) {
476 case VENDOR_NVIDIA:
477 gl_string_cursor = strstr(gl_string, "NVIDIA");
478 if (!gl_string_cursor) {
479 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
480 break;
483 gl_string_cursor = strstr(gl_string_cursor, " ");
484 if (!gl_string_cursor) {
485 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
486 break;
489 while (*gl_string_cursor == ' ') {
490 ++gl_string_cursor;
493 if (!*gl_string_cursor) {
494 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
495 break;
498 major = atoi(gl_string_cursor);
499 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
500 ++gl_string_cursor;
503 if (*gl_string_cursor++ != '.') {
504 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
505 break;
508 minor = atoi(gl_string_cursor);
509 minor = major*100+minor;
510 major = 10;
512 break;
514 case VENDOR_ATI:
515 major = minor = 0;
516 gl_string_cursor = strchr(gl_string, '-');
517 if (gl_string_cursor) {
518 int error = 0;
519 gl_string_cursor++;
521 /* Check if version number is of the form x.y.z */
522 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
523 error = 1;
524 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
525 error = 1;
526 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
527 error = 1;
528 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
529 error = 1;
531 /* Mark version number as malformed */
532 if (error)
533 gl_string_cursor = 0;
536 if (!gl_string_cursor)
537 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
538 else {
539 major = *gl_string_cursor - '0';
540 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
542 break;
544 case VENDOR_INTEL:
545 case VENDOR_MESA:
546 gl_string_cursor = strstr(gl_string, "Mesa");
547 gl_string_cursor = strstr(gl_string_cursor, " ");
548 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
549 if (*gl_string_cursor) {
550 char tmp[16];
551 int cursor = 0;
553 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
554 tmp[cursor++] = *gl_string_cursor;
555 ++gl_string_cursor;
557 tmp[cursor] = 0;
558 major = atoi(tmp);
560 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
561 ++gl_string_cursor;
563 cursor = 0;
564 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
565 tmp[cursor++] = *gl_string_cursor;
566 ++gl_string_cursor;
568 tmp[cursor] = 0;
569 minor = atoi(tmp);
571 break;
573 default:
574 major = 0;
575 minor = 9;
577 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
578 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
581 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
584 * Initialize openGL extension related variables
585 * with Default values
587 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
588 gl_info->max_buffers = 1;
589 gl_info->max_textures = 1;
590 gl_info->max_texture_stages = 1;
591 gl_info->max_fragment_samplers = 1;
592 gl_info->max_vertex_samplers = 0;
593 gl_info->max_combined_samplers = 0;
594 gl_info->max_sampler_stages = 1;
595 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
596 gl_info->ps_arb_max_temps = 0;
597 gl_info->ps_arb_max_instructions = 0;
598 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
599 gl_info->vs_arb_max_temps = 0;
600 gl_info->vs_arb_max_instructions = 0;
601 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
602 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
603 gl_info->vs_glsl_constantsF = 0;
604 gl_info->ps_glsl_constantsF = 0;
605 gl_info->vs_arb_constantsF = 0;
606 gl_info->ps_arb_constantsF = 0;
608 /* Now work out what GL support this card really has */
609 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
610 GL_EXT_FUNCS_GEN;
611 WGL_EXT_FUNCS_GEN;
612 #undef USE_GL_FUNC
614 /* Retrieve opengl defaults */
615 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
616 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
617 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
619 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
620 gl_info->max_lights = gl_max;
621 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
623 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
624 gl_info->max_texture_size = gl_max;
625 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
627 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
628 gl_info->max_pointsize = gl_floatv[1];
629 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
631 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
632 gl_info->max_aux_buffers = gl_max;
633 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
635 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
636 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
637 TRACE_(d3d_caps)("GL_Extensions reported:\n");
639 if (NULL == GL_Extensions) {
640 ERR(" GL_Extensions returns NULL\n");
641 } else {
642 while (*GL_Extensions != 0x00) {
643 const char *Start;
644 char ThisExtn[256];
645 size_t len;
647 while (isspace(*GL_Extensions)) GL_Extensions++;
648 Start = GL_Extensions;
649 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
650 GL_Extensions++;
653 len = GL_Extensions - Start;
654 if (len == 0 || len >= sizeof(ThisExtn))
655 continue;
657 memcpy(ThisExtn, Start, len);
658 ThisExtn[len] = '\0';
659 TRACE_(d3d_caps)("- %s\n", ThisExtn);
661 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
662 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
663 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
664 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
665 break;
670 if (gl_info->supported[APPLE_FENCE]) {
671 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
672 * The apple extension interacts with some other apple exts. Disable the NV
673 * extension if the apple one is support to prevent confusion in other parts
674 * of the code
676 gl_info->supported[NV_FENCE] = FALSE;
678 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
679 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
680 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
682 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
683 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
684 * Won't occur in any real world situation though
686 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
688 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
689 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
690 gl_info->max_buffers = gl_max;
691 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
693 if (gl_info->supported[ARB_MULTITEXTURE]) {
694 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
695 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
696 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
698 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
699 GLint tmp;
700 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
701 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
702 } else {
703 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
705 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
707 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
708 GLint tmp;
709 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
710 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
711 } else {
712 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
714 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
716 if (gl_info->supported[ARB_VERTEX_SHADER]) {
717 GLint tmp;
718 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
719 gl_info->max_vertex_samplers = tmp;
720 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
721 gl_info->max_combined_samplers = tmp;
722 } else {
723 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
725 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
726 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
728 if (gl_info->supported[ARB_VERTEX_BLEND]) {
729 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
730 gl_info->max_blends = gl_max;
731 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
733 if (gl_info->supported[EXT_TEXTURE3D]) {
734 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
735 gl_info->max_texture3d_size = gl_max;
736 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
738 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
739 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
740 gl_info->max_anisotropy = gl_max;
741 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
743 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
744 gl_info->ps_arb_version = PS_VERSION_11;
745 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
746 gl_info->ps_arb_constantsF = gl_max;
747 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
748 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
749 gl_info->ps_arb_max_temps = gl_max;
750 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info->ps_arb_max_temps);
751 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
752 gl_info->ps_arb_max_instructions = gl_max;
753 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info->ps_arb_max_instructions);
755 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
756 gl_info->vs_arb_version = VS_VERSION_11;
757 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
758 gl_info->vs_arb_constantsF = gl_max;
759 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
760 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
761 gl_info->vs_arb_max_temps = gl_max;
762 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info->vs_arb_max_temps);
763 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
764 gl_info->vs_arb_max_instructions = gl_max;
765 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info->vs_arb_max_instructions);
767 if (gl_info->supported[ARB_VERTEX_SHADER]) {
768 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
769 gl_info->vs_glsl_constantsF = gl_max / 4;
770 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
772 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
773 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
774 gl_info->ps_glsl_constantsF = gl_max / 4;
775 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
777 if (gl_info->supported[EXT_VERTEX_SHADER]) {
778 gl_info->vs_ati_version = VS_VERSION_11;
780 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
781 gl_info->vs_nv_version = VS_VERSION_30;
782 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
783 gl_info->vs_nv_version = VS_VERSION_20;
784 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
785 gl_info->vs_nv_version = VS_VERSION_11;
786 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
787 gl_info->vs_nv_version = VS_VERSION_10;
789 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
790 gl_info->ps_nv_version = PS_VERSION_30;
791 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
792 gl_info->ps_nv_version = PS_VERSION_20;
796 checkGLcall("extension detection\n");
798 /* In some cases the number of texture stages can be larger than the number
799 * of samplers. The GF4 for example can use only 2 samplers (no fragment
800 * shaders), but 8 texture stages (register combiners). */
801 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
803 /* We can only use ORM_FBO when the hardware supports it. */
804 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
805 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
806 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
809 /* MRTs are currently only supported when FBOs are used. */
810 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
811 gl_info->max_buffers = 1;
814 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
815 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
816 * in case of the latest videocards in the number of pixel/vertex pipelines.
818 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
819 * rendering. Various games use this information to get a rough estimation of the features of the card
820 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
821 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
822 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
823 * not the PCI id.
825 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
826 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
827 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
828 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
829 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
830 * is used for rendering which is not always the case). This would work but it is not very portable. Second
831 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
832 * is limited.
834 * As said most games only use the PCI id to get an indication of the capabilities of the card.
835 * It doesn't really matter if the given id is the correct one if we return the id of a card with
836 * similar 3d features.
838 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
839 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
840 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
841 * won't pass we return a default card. This way is better than maintaining a full card database as even
842 * without a full database we can return a card with similar features. Second the size of the database
843 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
844 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
845 * to distinguishes between different models from that family.
847 switch (gl_info->gl_vendor) {
848 case VENDOR_NVIDIA:
849 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
850 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
852 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
853 if (strstr(gl_info->gl_renderer, "7800") ||
854 strstr(gl_info->gl_renderer, "7900") ||
855 strstr(gl_info->gl_renderer, "7950") ||
856 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
857 strstr(gl_info->gl_renderer, "Quadro FX 5"))
858 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
859 else if(strstr(gl_info->gl_renderer, "6800") ||
860 strstr(gl_info->gl_renderer, "7600"))
861 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
862 else if(strstr(gl_info->gl_renderer, "6600") ||
863 strstr(gl_info->gl_renderer, "6610") ||
864 strstr(gl_info->gl_renderer, "6700"))
865 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
866 else
867 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
868 } else if(WINE_D3D9_CAPABLE(gl_info)) {
869 if (strstr(gl_info->gl_renderer, "5800") ||
870 strstr(gl_info->gl_renderer, "5900") ||
871 strstr(gl_info->gl_renderer, "5950") ||
872 strstr(gl_info->gl_renderer, "Quadro FX"))
873 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
874 else if(strstr(gl_info->gl_renderer, "5600") ||
875 strstr(gl_info->gl_renderer, "5650") ||
876 strstr(gl_info->gl_renderer, "5700") ||
877 strstr(gl_info->gl_renderer, "5750"))
878 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
879 else
880 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
881 } else if(WINE_D3D8_CAPABLE(gl_info)) {
882 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
883 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
884 else
885 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
886 } else if(WINE_D3D7_CAPABLE(gl_info)) {
887 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
888 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
889 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
890 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
891 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
892 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
893 else
894 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
895 } else {
896 if (strstr(gl_info->gl_renderer, "TNT2"))
897 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
898 else
899 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
901 break;
902 case VENDOR_ATI:
903 if(WINE_D3D9_CAPABLE(gl_info)) {
904 /* Radeon R5xx */
905 if (strstr(gl_info->gl_renderer, "X1600") ||
906 strstr(gl_info->gl_renderer, "X1800") ||
907 strstr(gl_info->gl_renderer, "X1900") ||
908 strstr(gl_info->gl_renderer, "X1950"))
909 gl_info->gl_card = CARD_ATI_RADEON_X1600;
910 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
911 else if(strstr(gl_info->gl_renderer, "X700") ||
912 strstr(gl_info->gl_renderer, "X800") ||
913 strstr(gl_info->gl_renderer, "X850") ||
914 strstr(gl_info->gl_renderer, "X1300") ||
915 strstr(gl_info->gl_renderer, "X1400"))
916 gl_info->gl_card = CARD_ATI_RADEON_X700;
917 /* Radeon R3xx */
918 else
919 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
920 } else if(WINE_D3D8_CAPABLE(gl_info)) {
921 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
922 } else if(WINE_D3D7_CAPABLE(gl_info)) {
923 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
924 } else
925 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
926 break;
927 case VENDOR_INTEL:
928 if (strstr(gl_info->gl_renderer, "915GM")) {
929 gl_info->gl_card = CARD_INTEL_I915GM;
930 } else if (strstr(gl_info->gl_renderer, "915G")) {
931 gl_info->gl_card = CARD_INTEL_I915G;
932 } else if (strstr(gl_info->gl_renderer, "865G")) {
933 gl_info->gl_card = CARD_INTEL_I865G;
934 } else if (strstr(gl_info->gl_renderer, "855G")) {
935 gl_info->gl_card = CARD_INTEL_I855G;
936 } else if (strstr(gl_info->gl_renderer, "830G")) {
937 gl_info->gl_card = CARD_INTEL_I830G;
938 } else {
939 gl_info->gl_card = CARD_INTEL_I915G;
941 break;
942 case VENDOR_MESA:
943 case VENDOR_WINE:
944 default:
945 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
946 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
947 * them a good generic choice.
949 gl_info->gl_vendor = VENDOR_NVIDIA;
950 if(WINE_D3D9_CAPABLE(gl_info))
951 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
952 else if(WINE_D3D8_CAPABLE(gl_info))
953 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
954 else if(WINE_D3D7_CAPABLE(gl_info))
955 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
956 else if(WINE_D3D6_CAPABLE(gl_info))
957 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
958 else
959 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
961 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
963 /* Load all the lookup tables
964 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
965 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
966 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
968 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
969 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
972 for (i = 0; i < MAX_LOOKUPS; i++) {
973 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
976 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
977 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
978 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
979 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
980 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
981 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
982 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
983 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
984 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
985 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
987 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
988 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
989 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
990 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
991 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
994 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
995 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
996 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
997 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
998 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
999 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1000 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1001 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1002 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1003 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1004 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1005 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1006 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1008 /* TODO: config lookups */
1010 /* Make sure there's an active HDC else the WGL extensions will fail */
1011 hdc = pwglGetCurrentDC();
1012 if (hdc) {
1013 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1014 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1016 if (NULL == WGL_Extensions) {
1017 ERR(" WGL_Extensions returns NULL\n");
1018 } else {
1019 while (*WGL_Extensions != 0x00) {
1020 const char *Start;
1021 char ThisExtn[256];
1022 size_t len;
1024 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1025 Start = WGL_Extensions;
1026 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1027 WGL_Extensions++;
1030 len = WGL_Extensions - Start;
1031 if (len == 0 || len >= sizeof(ThisExtn))
1032 continue;
1034 memcpy(ThisExtn, Start, len);
1035 ThisExtn[len] = '\0';
1036 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1038 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1039 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1040 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1047 WineD3D_ReleaseFakeGLContext();
1048 return return_value;
1050 #undef GLINFO_LOCATION
1052 /**********************************************************
1053 * IWineD3D implementation follows
1054 **********************************************************/
1056 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1057 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1059 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1060 return numAdapters;
1063 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1064 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1065 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1066 return WINED3D_OK;
1069 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1070 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1072 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1073 return NULL;
1076 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1077 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1080 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1081 of the same bpp but different resolutions */
1083 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1084 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1085 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1086 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1088 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1089 return 0;
1092 /* TODO: Store modes per adapter and read it from the adapter structure */
1093 if (Adapter == 0) { /* Display */
1094 int i = 0;
1095 int j = 0;
1097 if (!DEBUG_SINGLE_MODE) {
1098 DEVMODEW DevModeW;
1100 ZeroMemory(&DevModeW, sizeof(DevModeW));
1101 DevModeW.dmSize = sizeof(DevModeW);
1102 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1103 j++;
1104 switch (Format)
1106 case WINED3DFMT_UNKNOWN:
1107 /* This is for D3D8, do not enumerate P8 here */
1108 if (DevModeW.dmBitsPerPel == 32 ||
1109 DevModeW.dmBitsPerPel == 16) i++;
1110 break;
1111 case WINED3DFMT_X8R8G8B8:
1112 if (DevModeW.dmBitsPerPel == 32) i++;
1113 break;
1114 case WINED3DFMT_R5G6B5:
1115 if (DevModeW.dmBitsPerPel == 16) i++;
1116 break;
1117 case WINED3DFMT_P8:
1118 if (DevModeW.dmBitsPerPel == 8) i++;
1119 break;
1120 default:
1121 /* Skip other modes as they do not match the requested format */
1122 break;
1125 } else {
1126 i = 1;
1127 j = 1;
1130 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1131 return i;
1132 } else {
1133 FIXME_(d3d_caps)("Adapter not primary display\n");
1135 return 0;
1138 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1139 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1140 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1141 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1143 /* Validate the parameters as much as possible */
1144 if (NULL == pMode ||
1145 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1146 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1147 return WINED3DERR_INVALIDCALL;
1150 /* TODO: Store modes per adapter and read it from the adapter structure */
1151 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1152 DEVMODEW DevModeW;
1153 int ModeIdx = 0;
1154 int i = 0;
1155 int j = 0;
1157 ZeroMemory(&DevModeW, sizeof(DevModeW));
1158 DevModeW.dmSize = sizeof(DevModeW);
1160 /* If we are filtering to a specific format (D3D9), then need to skip
1161 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1162 just count through the ones with valid bit depths */
1163 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1164 switch (Format)
1166 case WINED3DFMT_UNKNOWN:
1167 /* This is D3D8. Do not enumerate P8 here */
1168 if (DevModeW.dmBitsPerPel == 32 ||
1169 DevModeW.dmBitsPerPel == 16) i++;
1170 break;
1171 case WINED3DFMT_X8R8G8B8:
1172 if (DevModeW.dmBitsPerPel == 32) i++;
1173 break;
1174 case WINED3DFMT_R5G6B5:
1175 if (DevModeW.dmBitsPerPel == 16) i++;
1176 break;
1177 case WINED3DFMT_P8:
1178 if (DevModeW.dmBitsPerPel == 8) i++;
1179 break;
1180 default:
1181 /* Modes that don't match what we support can get an early-out */
1182 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1183 return WINED3DERR_INVALIDCALL;
1187 if (i == 0) {
1188 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1189 return WINED3DERR_INVALIDCALL;
1191 ModeIdx = j - 1;
1193 /* Now get the display mode via the calculated index */
1194 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1195 pMode->Width = DevModeW.dmPelsWidth;
1196 pMode->Height = DevModeW.dmPelsHeight;
1197 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1198 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1199 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1201 if (Format == WINED3DFMT_UNKNOWN)
1203 switch (DevModeW.dmBitsPerPel)
1205 case 8:
1206 pMode->Format = WINED3DFMT_P8;
1207 break;
1208 case 16:
1209 pMode->Format = WINED3DFMT_R5G6B5;
1210 break;
1211 case 32:
1212 pMode->Format = WINED3DFMT_X8R8G8B8;
1213 break;
1214 default:
1215 pMode->Format = WINED3DFMT_UNKNOWN;
1216 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1218 } else {
1219 pMode->Format = Format;
1221 } else {
1222 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1223 return WINED3DERR_INVALIDCALL;
1226 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1227 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1228 DevModeW.dmBitsPerPel);
1230 } else if (DEBUG_SINGLE_MODE) {
1231 /* Return one setting of the format requested */
1232 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1233 pMode->Width = 800;
1234 pMode->Height = 600;
1235 pMode->RefreshRate = 60;
1236 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1237 } else {
1238 FIXME_(d3d_caps)("Adapter not primary display\n");
1241 return WINED3D_OK;
1244 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1245 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1246 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1248 if (NULL == pMode ||
1249 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1250 return WINED3DERR_INVALIDCALL;
1253 if (Adapter == 0) { /* Display */
1254 int bpp = 0;
1255 DEVMODEW DevModeW;
1257 ZeroMemory(&DevModeW, sizeof(DevModeW));
1258 DevModeW.dmSize = sizeof(DevModeW);
1260 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1261 pMode->Width = DevModeW.dmPelsWidth;
1262 pMode->Height = DevModeW.dmPelsHeight;
1263 bpp = DevModeW.dmBitsPerPel;
1264 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1265 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1267 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1270 switch (bpp) {
1271 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1272 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1273 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1274 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1275 default: pMode->Format = WINED3DFMT_UNKNOWN;
1278 } else {
1279 FIXME_(d3d_caps)("Adapter not primary display\n");
1282 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1283 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1284 return WINED3D_OK;
1287 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1288 and fields being inserted in the middle, a new structure is used in place */
1289 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1290 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1291 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1293 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1295 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1296 return WINED3DERR_INVALIDCALL;
1299 /* Return the information requested */
1300 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1301 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1302 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1304 /* Note dx8 doesn't supply a DeviceName */
1305 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1306 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1307 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1308 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1309 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1310 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1311 *(pIdentifier->SubSysId) = 0;
1312 *(pIdentifier->Revision) = 0;
1314 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1315 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1316 *(pIdentifier->WHQLLevel) = 0;
1317 } else {
1318 *(pIdentifier->WHQLLevel) = 1;
1321 return WINED3D_OK;
1324 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1325 short redSize, greenSize, blueSize, alphaSize, colorBits;
1327 if(!cfg)
1328 return FALSE;
1330 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1331 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1332 return FALSE;
1335 if(cfg->redSize < redSize)
1336 return FALSE;
1338 if(cfg->greenSize < greenSize)
1339 return FALSE;
1341 if(cfg->blueSize < blueSize)
1342 return FALSE;
1344 if(cfg->alphaSize < alphaSize)
1345 return FALSE;
1347 return TRUE;
1350 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1351 short depthSize, stencilSize;
1353 if(!cfg)
1354 return FALSE;
1356 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1357 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1358 return FALSE;
1361 if(cfg->depthSize < depthSize)
1362 return FALSE;
1364 if(cfg->stencilSize < stencilSize)
1365 return FALSE;
1367 return TRUE;
1370 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1371 WINED3DFORMAT AdapterFormat,
1372 WINED3DFORMAT RenderTargetFormat,
1373 WINED3DFORMAT DepthStencilFormat) {
1374 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1375 int nCfgs;
1376 WineD3D_PixelFormat *cfgs;
1377 int it;
1379 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1380 This, Adapter,
1381 DeviceType, debug_d3ddevicetype(DeviceType),
1382 AdapterFormat, debug_d3dformat(AdapterFormat),
1383 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1384 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1386 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1387 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1388 return WINED3DERR_INVALIDCALL;
1391 cfgs = Adapters[Adapter].cfgs;
1392 nCfgs = Adapters[Adapter].nCfgs;
1393 for (it = 0; it < nCfgs; ++it) {
1394 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1395 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1396 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1397 return WINED3D_OK;
1401 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1403 return WINED3DERR_NOTAVAILABLE;
1406 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1407 WINED3DFORMAT SurfaceFormat,
1408 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1410 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1411 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1412 This,
1413 Adapter,
1414 DeviceType, debug_d3ddevicetype(DeviceType),
1415 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1416 Windowed,
1417 MultiSampleType,
1418 pQualityLevels);
1420 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1421 return WINED3DERR_INVALIDCALL;
1424 /* TODO: Store in Adapter structure */
1425 if (pQualityLevels != NULL) {
1426 static int s_single_shot = 0;
1427 if (!s_single_shot) {
1428 FIXME("Quality levels unsupported at present\n");
1429 s_single_shot = 1;
1431 *pQualityLevels = 1; /* Guess at a value! */
1434 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1435 return WINED3DERR_NOTAVAILABLE;
1438 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1439 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1441 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1442 int nCfgs = 0;
1443 WineD3D_PixelFormat *cfgs;
1444 int it;
1445 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1447 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1448 This,
1449 Adapter,
1450 CheckType, debug_d3ddevicetype(CheckType),
1451 DisplayFormat, debug_d3dformat(DisplayFormat),
1452 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1453 Windowed);
1455 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1456 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1457 return WINED3DERR_INVALIDCALL;
1460 cfgs = Adapters[Adapter].cfgs;
1461 nCfgs = Adapters[Adapter].nCfgs;
1462 for (it = 0; it < nCfgs; ++it) {
1463 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1464 hr = WINED3D_OK;
1465 TRACE_(d3d_caps)("OK\n");
1466 break ;
1470 if(hr != WINED3D_OK)
1471 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1473 if(hr != WINED3D_OK)
1474 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1476 return hr;
1479 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1480 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1481 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1482 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1483 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1484 This,
1485 Adapter,
1486 DeviceType, debug_d3ddevicetype(DeviceType),
1487 AdapterFormat, debug_d3dformat(AdapterFormat),
1488 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1489 RType, debug_d3dresourcetype(RType),
1490 CheckFormat, debug_d3dformat(CheckFormat));
1492 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1493 return WINED3DERR_INVALIDCALL;
1496 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1497 switch (CheckFormat) {
1498 /* Filtering not supported */
1499 case WINED3DFMT_A32B32G32R32F:
1500 TRACE_(d3d_caps)("[FAILED]\n");
1501 return WINED3DERR_NOTAVAILABLE;
1502 default:
1503 break;
1507 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1508 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1509 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1510 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1511 if (!GL_LIMITS(vertex_samplers)) {
1512 TRACE_(d3d_caps)("[FAILED]\n");
1513 return WINED3DERR_NOTAVAILABLE;
1516 switch (CheckFormat) {
1517 case WINED3DFMT_A32B32G32R32F:
1518 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1519 TRACE_(d3d_caps)("[FAILED]\n");
1520 return WINED3DERR_NOTAVAILABLE;
1522 TRACE_(d3d_caps)("[OK]\n");
1523 return WINED3D_OK;
1525 default:
1526 TRACE_(d3d_caps)("[FAILED]\n");
1527 return WINED3DERR_NOTAVAILABLE;
1531 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1532 switch (CheckFormat) {
1533 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1534 * Windows supports only those 3, and enumerating the other formats confuses applications
1536 case WINED3DFMT_D24S8:
1537 case WINED3DFMT_D24X8:
1538 case WINED3DFMT_D16:
1539 TRACE_(d3d_caps)("[OK]\n");
1540 return WINED3D_OK;
1541 case WINED3DFMT_D16_LOCKABLE:
1542 case WINED3DFMT_D24FS8:
1543 case WINED3DFMT_D32F_LOCKABLE:
1544 case WINED3DFMT_D24X4S4:
1545 case WINED3DFMT_D15S1:
1546 case WINED3DFMT_D32:
1547 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1548 return WINED3DERR_NOTAVAILABLE;
1549 default:
1550 TRACE_(d3d_caps)("[FAILED]\n");
1551 return WINED3DERR_NOTAVAILABLE;
1553 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1554 switch (CheckFormat) {
1555 case WINED3DFMT_R8G8B8:
1556 case WINED3DFMT_A8R8G8B8:
1557 case WINED3DFMT_X8R8G8B8:
1558 case WINED3DFMT_R5G6B5:
1559 case WINED3DFMT_X1R5G5B5:
1560 case WINED3DFMT_A1R5G5B5:
1561 case WINED3DFMT_A4R4G4B4:
1562 case WINED3DFMT_R3G3B2:
1563 case WINED3DFMT_X4R4G4B4:
1564 case WINED3DFMT_A8B8G8R8:
1565 case WINED3DFMT_X8B8G8R8:
1566 case WINED3DFMT_P8:
1567 TRACE_(d3d_caps)("[OK]\n");
1568 return WINED3D_OK;
1569 case WINED3DFMT_R16F:
1570 case WINED3DFMT_A16B16G16R16F:
1571 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1572 TRACE_(d3d_caps)("[FAILED]\n");
1573 return WINED3DERR_NOTAVAILABLE;
1575 TRACE_(d3d_caps)("[OK]\n");
1576 return WINED3D_OK;
1577 case WINED3DFMT_A32B32G32R32F:
1578 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1579 TRACE_(d3d_caps)("[FAILED]\n");
1580 return WINED3DERR_NOTAVAILABLE;
1582 TRACE_(d3d_caps)("[OK]\n");
1583 return WINED3D_OK;
1584 default:
1585 TRACE_(d3d_caps)("[FAILED]\n");
1586 return WINED3DERR_NOTAVAILABLE;
1588 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1589 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1590 switch (CheckFormat) {
1591 case WINED3DFMT_V8U8:
1592 TRACE_(d3d_caps)("[OK]\n");
1593 return WINED3D_OK;
1594 /* TODO: Other bump map formats */
1595 default:
1596 TRACE_(d3d_caps)("[FAILED]\n");
1597 return WINED3DERR_NOTAVAILABLE;
1600 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1601 switch (CheckFormat) {
1602 case WINED3DFMT_V8U8:
1603 TRACE_(d3d_caps)("[OK]\n");
1604 return WINED3D_OK;
1605 default:
1606 TRACE_(d3d_caps)("[FAILED]\n");
1607 return WINED3DERR_NOTAVAILABLE;
1610 TRACE_(d3d_caps)("[FAILED]\n");
1611 return WINED3DERR_NOTAVAILABLE;
1614 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1615 switch (CheckFormat) {
1616 case WINED3DFMT_DXT1:
1617 case WINED3DFMT_DXT2:
1618 case WINED3DFMT_DXT3:
1619 case WINED3DFMT_DXT4:
1620 case WINED3DFMT_DXT5:
1621 TRACE_(d3d_caps)("[OK]\n");
1622 return WINED3D_OK;
1623 default:
1624 break; /* Avoid compiler warnings */
1628 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1629 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1630 switch (CheckFormat) {
1631 case WINED3DFMT_A8R8G8B8:
1632 case WINED3DFMT_X8R8G8B8:
1633 case WINED3DFMT_A4R4G4B4:
1634 case WINED3DFMT_L8:
1635 case WINED3DFMT_A8L8:
1636 case WINED3DFMT_DXT1:
1637 case WINED3DFMT_DXT2:
1638 case WINED3DFMT_DXT3:
1639 case WINED3DFMT_DXT4:
1640 case WINED3DFMT_DXT5:
1641 TRACE_(d3d_caps)("[OK]\n");
1642 return WINED3D_OK;
1644 default:
1645 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1646 return WINED3DERR_NOTAVAILABLE;
1650 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1652 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1654 switch (CheckFormat) {
1655 case WINED3DFMT_R16F:
1656 case WINED3DFMT_A16B16G16R16F:
1657 if (!half_pixel_support) break;
1658 case WINED3DFMT_R32F:
1659 case WINED3DFMT_A32B32G32R32F:
1660 TRACE_(d3d_caps)("[OK]\n");
1661 return WINED3D_OK;
1662 default:
1663 break; /* Avoid compiler warnings */
1667 /* This format is nothing special and it is supported perfectly.
1668 * However, ati and nvidia driver on windows do not mark this format as
1669 * supported (tested with the dxCapsViewer) and pretending to
1670 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1671 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1672 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1674 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1675 TRACE_(d3d_caps)("[FAILED]\n");
1676 return WINED3DERR_NOTAVAILABLE;
1679 switch (CheckFormat) {
1681 /*****
1682 * supported: RGB(A) formats
1684 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1685 case WINED3DFMT_A8R8G8B8:
1686 case WINED3DFMT_X8R8G8B8:
1687 case WINED3DFMT_R5G6B5:
1688 case WINED3DFMT_X1R5G5B5:
1689 case WINED3DFMT_A1R5G5B5:
1690 case WINED3DFMT_A4R4G4B4:
1691 case WINED3DFMT_R3G3B2:
1692 case WINED3DFMT_A8:
1693 case WINED3DFMT_X4R4G4B4:
1694 case WINED3DFMT_A8B8G8R8:
1695 case WINED3DFMT_X8B8G8R8:
1696 case WINED3DFMT_A2R10G10B10:
1697 case WINED3DFMT_A2B10G10R10:
1698 TRACE_(d3d_caps)("[OK]\n");
1699 return WINED3D_OK;
1701 /*****
1702 * supported: Palettized
1704 case WINED3DFMT_P8:
1705 TRACE_(d3d_caps)("[OK]\n");
1706 return WINED3D_OK;
1708 /*****
1709 * Supported: (Alpha)-Luminance
1711 case WINED3DFMT_L8:
1712 case WINED3DFMT_A8L8:
1713 case WINED3DFMT_A4L4:
1714 TRACE_(d3d_caps)("[OK]\n");
1715 return WINED3D_OK;
1717 /*****
1718 * Not supported for now: Bump mapping formats
1719 * Enable some because games often fail when they are not available
1720 * and are still playable even without bump mapping
1722 case WINED3DFMT_V8U8:
1723 case WINED3DFMT_V16U16:
1724 case WINED3DFMT_L6V5U5:
1725 case WINED3DFMT_X8L8V8U8:
1726 case WINED3DFMT_Q8W8V8U8:
1727 case WINED3DFMT_W11V11U10:
1728 case WINED3DFMT_A2W10V10U10:
1729 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1730 return WINED3D_OK;
1732 /*****
1733 * DXTN Formats: Handled above
1734 * WINED3DFMT_DXT1
1735 * WINED3DFMT_DXT2
1736 * WINED3DFMT_DXT3
1737 * WINED3DFMT_DXT4
1738 * WINED3DFMT_DXT5
1741 /*****
1742 * Odd formats - not supported
1744 case WINED3DFMT_VERTEXDATA:
1745 case WINED3DFMT_INDEX16:
1746 case WINED3DFMT_INDEX32:
1747 case WINED3DFMT_Q16W16V16U16:
1748 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1749 return WINED3DERR_NOTAVAILABLE;
1751 /*****
1752 * Float formats: Not supported right now
1754 case WINED3DFMT_G16R16F:
1755 case WINED3DFMT_G32R32F:
1756 case WINED3DFMT_CxV8U8:
1757 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1758 return WINED3DERR_NOTAVAILABLE;
1760 /* Not supported */
1761 case WINED3DFMT_G16R16:
1762 case WINED3DFMT_A16B16G16R16:
1763 case WINED3DFMT_A8R3G3B2:
1764 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1765 return WINED3DERR_NOTAVAILABLE;
1767 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1768 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1769 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1770 * We can do instancing with all shader versions, but we need vertex shaders.
1772 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1773 * to enable instancing. WineD3D doesn't need that and just ignores it.
1775 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1777 case WINEMAKEFOURCC('I','N','S','T'):
1778 TRACE("ATI Instancing check hack\n");
1779 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1780 TRACE_(d3d_caps)("[OK]\n");
1781 return WINED3D_OK;
1782 } else {
1783 TRACE_(d3d_caps)("[FAILED]\n");
1784 return WINED3DERR_NOTAVAILABLE;
1787 default:
1788 break;
1791 TRACE_(d3d_caps)("[FAILED]\n");
1792 return WINED3DERR_NOTAVAILABLE;
1795 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1796 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1797 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1799 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1800 This,
1801 Adapter,
1802 DeviceType, debug_d3ddevicetype(DeviceType),
1803 SourceFormat, debug_d3dformat(SourceFormat),
1804 TargetFormat, debug_d3dformat(TargetFormat));
1805 return WINED3D_OK;
1808 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1809 subset of a D3DCAPS9 structure. However, it has to come via a void *
1810 as the d3d8 interface cannot import the d3d9 header */
1811 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1813 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1814 int vs_selected_mode;
1815 int ps_selected_mode;
1817 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1819 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1820 return WINED3DERR_INVALIDCALL;
1823 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1825 /* This function should *not* be modifying GL caps
1826 * TODO: move the functionality where it belongs */
1827 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1829 /* ------------------------------------------------
1830 The following fields apply to both d3d8 and d3d9
1831 ------------------------------------------------ */
1832 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1833 *pCaps->AdapterOrdinal = Adapter;
1835 *pCaps->Caps = 0;
1836 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1837 WINED3DCAPS2_FULLSCREENGAMMA |
1838 WINED3DCAPS2_DYNAMICTEXTURES;
1839 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1840 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1842 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1843 WINED3DCURSORCAPS_LOWRES;
1845 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1846 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1847 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1848 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1849 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1850 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1851 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1852 WINED3DDEVCAPS_PUREDEVICE |
1853 WINED3DDEVCAPS_HWRASTERIZATION |
1854 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1855 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1856 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1857 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1858 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1859 WINED3DDEVCAPS_RTPATCHES;
1861 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1862 WINED3DPMISCCAPS_CULLCCW |
1863 WINED3DPMISCCAPS_CULLCW |
1864 WINED3DPMISCCAPS_COLORWRITEENABLE |
1865 WINED3DPMISCCAPS_CLIPTLVERTS |
1866 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1867 WINED3DPMISCCAPS_MASKZ |
1868 WINED3DPMISCCAPS_BLENDOP;
1869 /* TODO:
1870 WINED3DPMISCCAPS_NULLREFERENCE
1871 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1872 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1873 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1874 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1875 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1876 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1878 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1879 #if 0
1880 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1881 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1882 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1883 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1884 #endif
1886 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1887 WINED3DPRASTERCAPS_PAT |
1888 WINED3DPRASTERCAPS_WFOG |
1889 WINED3DPRASTERCAPS_ZFOG |
1890 WINED3DPRASTERCAPS_FOGVERTEX |
1891 WINED3DPRASTERCAPS_FOGTABLE |
1892 WINED3DPRASTERCAPS_STIPPLE |
1893 WINED3DPRASTERCAPS_SUBPIXEL |
1894 WINED3DPRASTERCAPS_ZTEST |
1895 WINED3DPRASTERCAPS_SCISSORTEST |
1896 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1897 WINED3DPRASTERCAPS_DEPTHBIAS;
1899 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1900 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1901 WINED3DPRASTERCAPS_ZBIAS |
1902 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1904 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
1905 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
1907 /* FIXME Add:
1908 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1909 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1910 WINED3DPRASTERCAPS_ANTIALIASEDGES
1911 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1912 WINED3DPRASTERCAPS_WBUFFER */
1914 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1915 WINED3DPCMPCAPS_EQUAL |
1916 WINED3DPCMPCAPS_GREATER |
1917 WINED3DPCMPCAPS_GREATEREQUAL |
1918 WINED3DPCMPCAPS_LESS |
1919 WINED3DPCMPCAPS_LESSEQUAL |
1920 WINED3DPCMPCAPS_NEVER |
1921 WINED3DPCMPCAPS_NOTEQUAL;
1923 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1924 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1925 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1926 WINED3DPBLENDCAPS_DESTALPHA |
1927 WINED3DPBLENDCAPS_DESTCOLOR |
1928 WINED3DPBLENDCAPS_INVDESTALPHA |
1929 WINED3DPBLENDCAPS_INVDESTCOLOR |
1930 WINED3DPBLENDCAPS_INVSRCALPHA |
1931 WINED3DPBLENDCAPS_INVSRCCOLOR |
1932 WINED3DPBLENDCAPS_ONE |
1933 WINED3DPBLENDCAPS_SRCALPHA |
1934 WINED3DPBLENDCAPS_SRCALPHASAT |
1935 WINED3DPBLENDCAPS_SRCCOLOR |
1936 WINED3DPBLENDCAPS_ZERO;
1938 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1939 WINED3DPBLENDCAPS_DESTALPHA |
1940 WINED3DPBLENDCAPS_DESTCOLOR |
1941 WINED3DPBLENDCAPS_INVDESTALPHA |
1942 WINED3DPBLENDCAPS_INVDESTCOLOR |
1943 WINED3DPBLENDCAPS_INVSRCALPHA |
1944 WINED3DPBLENDCAPS_INVSRCCOLOR |
1945 WINED3DPBLENDCAPS_ONE |
1946 WINED3DPBLENDCAPS_SRCALPHA |
1947 WINED3DPBLENDCAPS_SRCCOLOR |
1948 WINED3DPBLENDCAPS_ZERO;
1949 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
1950 * according to the glBlendFunc manpage
1952 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
1953 * legacy settings for srcblend only
1956 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1957 WINED3DPCMPCAPS_EQUAL |
1958 WINED3DPCMPCAPS_GREATER |
1959 WINED3DPCMPCAPS_GREATEREQUAL |
1960 WINED3DPCMPCAPS_LESS |
1961 WINED3DPCMPCAPS_LESSEQUAL |
1962 WINED3DPCMPCAPS_NEVER |
1963 WINED3DPCMPCAPS_NOTEQUAL;
1965 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1966 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1967 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1968 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1969 WINED3DPSHADECAPS_COLORFLATRGB |
1970 WINED3DPSHADECAPS_FOGFLAT |
1971 WINED3DPSHADECAPS_FOGGOURAUD |
1972 WINED3DPSHADECAPS_SPECULARFLATRGB;
1974 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1975 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1976 WINED3DPTEXTURECAPS_BORDER |
1977 WINED3DPTEXTURECAPS_MIPMAP |
1978 WINED3DPTEXTURECAPS_PROJECTED |
1979 WINED3DPTEXTURECAPS_PERSPECTIVE;
1981 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
1982 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
1983 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1986 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1987 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1988 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1989 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1992 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1993 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1994 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1995 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1999 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2000 WINED3DPTFILTERCAPS_MAGFPOINT |
2001 WINED3DPTFILTERCAPS_MINFLINEAR |
2002 WINED3DPTFILTERCAPS_MINFPOINT |
2003 WINED3DPTFILTERCAPS_MIPFLINEAR |
2004 WINED3DPTFILTERCAPS_MIPFPOINT |
2005 WINED3DPTFILTERCAPS_LINEAR |
2006 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2007 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2008 WINED3DPTFILTERCAPS_MIPLINEAR |
2009 WINED3DPTFILTERCAPS_MIPNEAREST |
2010 WINED3DPTFILTERCAPS_NEAREST;
2012 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2013 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2014 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2017 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2018 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2019 WINED3DPTFILTERCAPS_MAGFPOINT |
2020 WINED3DPTFILTERCAPS_MINFLINEAR |
2021 WINED3DPTFILTERCAPS_MINFPOINT |
2022 WINED3DPTFILTERCAPS_MIPFLINEAR |
2023 WINED3DPTFILTERCAPS_MIPFPOINT |
2024 WINED3DPTFILTERCAPS_LINEAR |
2025 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2026 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2027 WINED3DPTFILTERCAPS_MIPLINEAR |
2028 WINED3DPTFILTERCAPS_MIPNEAREST |
2029 WINED3DPTFILTERCAPS_NEAREST;
2031 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2032 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2033 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2035 } else
2036 *pCaps->CubeTextureFilterCaps = 0;
2038 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2039 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2040 WINED3DPTFILTERCAPS_MAGFPOINT |
2041 WINED3DPTFILTERCAPS_MINFLINEAR |
2042 WINED3DPTFILTERCAPS_MINFPOINT |
2043 WINED3DPTFILTERCAPS_MIPFLINEAR |
2044 WINED3DPTFILTERCAPS_MIPFPOINT |
2045 WINED3DPTFILTERCAPS_LINEAR |
2046 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2047 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2048 WINED3DPTFILTERCAPS_MIPLINEAR |
2049 WINED3DPTFILTERCAPS_MIPNEAREST |
2050 WINED3DPTFILTERCAPS_NEAREST;
2051 } else
2052 *pCaps->VolumeTextureFilterCaps = 0;
2054 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2055 WINED3DPTADDRESSCAPS_CLAMP |
2056 WINED3DPTADDRESSCAPS_WRAP;
2058 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2059 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2061 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2062 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2064 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2065 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2068 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2069 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2070 WINED3DPTADDRESSCAPS_CLAMP |
2071 WINED3DPTADDRESSCAPS_WRAP;
2072 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2073 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2075 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2076 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2078 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2079 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2081 } else
2082 *pCaps->VolumeTextureAddressCaps = 0;
2084 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2085 WINED3DLINECAPS_ZTEST;
2086 /* FIXME: Add
2087 WINED3DLINECAPS_BLEND
2088 WINED3DLINECAPS_ALPHACMP
2089 WINED3DLINECAPS_FOG */
2091 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2092 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2094 if(GL_SUPPORT(EXT_TEXTURE3D))
2095 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2096 else
2097 *pCaps->MaxVolumeExtent = 0;
2099 *pCaps->MaxTextureRepeat = 32768;
2100 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2101 *pCaps->MaxVertexW = 1.0;
2103 *pCaps->GuardBandLeft = 0;
2104 *pCaps->GuardBandTop = 0;
2105 *pCaps->GuardBandRight = 0;
2106 *pCaps->GuardBandBottom = 0;
2108 *pCaps->ExtentsAdjust = 0;
2110 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2111 WINED3DSTENCILCAPS_INCRSAT |
2112 WINED3DSTENCILCAPS_INVERT |
2113 WINED3DSTENCILCAPS_KEEP |
2114 WINED3DSTENCILCAPS_REPLACE |
2115 WINED3DSTENCILCAPS_ZERO;
2116 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2117 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2118 WINED3DSTENCILCAPS_INCR;
2120 if ( This->dxVersion > 8 &&
2121 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2122 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2123 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2126 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2128 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2129 WINED3DTEXOPCAPS_ADDSIGNED |
2130 WINED3DTEXOPCAPS_ADDSIGNED2X |
2131 WINED3DTEXOPCAPS_MODULATE |
2132 WINED3DTEXOPCAPS_MODULATE2X |
2133 WINED3DTEXOPCAPS_MODULATE4X |
2134 WINED3DTEXOPCAPS_SELECTARG1 |
2135 WINED3DTEXOPCAPS_SELECTARG2 |
2136 WINED3DTEXOPCAPS_DISABLE;
2138 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2139 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2140 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2141 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2142 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2143 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2144 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2145 WINED3DTEXOPCAPS_LERP |
2146 WINED3DTEXOPCAPS_SUBTRACT;
2148 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2149 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2150 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2151 WINED3DTEXOPCAPS_MULTIPLYADD |
2152 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2153 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2154 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2156 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2157 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2159 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2160 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2161 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2164 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2165 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2166 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2167 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2168 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2169 * and 3D textures. It also allows us to keep the code simpler by having texture
2170 * shaders constantly enabled.
2172 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2173 /* TODO: Luminance bump map? */
2175 #if 0
2176 /* FIXME: Add
2177 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2178 WINED3DTEXOPCAPS_PREMODULATE */
2179 #endif
2181 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2182 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2183 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2184 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2186 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2187 *pCaps->MaxVertexBlendMatrixIndex = 0;
2189 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2190 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2193 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2194 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2195 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2196 WINED3DVTXPCAPS_LOCALVIEWER |
2197 WINED3DVTXPCAPS_VERTEXFOG |
2198 WINED3DVTXPCAPS_TEXGEN;
2199 /* FIXME: Add
2200 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2202 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2203 *pCaps->MaxVertexIndex = 0xFFFFF;
2204 *pCaps->MaxStreams = MAX_STREAMS;
2205 *pCaps->MaxStreamStride = 1024;
2207 if (vs_selected_mode == SHADER_GLSL) {
2208 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2209 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2210 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2211 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2212 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2213 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2214 else
2215 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2216 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2217 } else if (vs_selected_mode == SHADER_ARB) {
2218 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2219 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2220 } else {
2221 *pCaps->VertexShaderVersion = 0;
2222 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2225 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2227 if (ps_selected_mode == SHADER_GLSL) {
2228 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2229 in case of GeforceFX cards. */
2230 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2231 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2232 else
2233 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2234 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2235 *pCaps->PixelShader1xMaxValue = 1.0;
2236 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2237 } else if (ps_selected_mode == SHADER_ARB) {
2238 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2239 *pCaps->PixelShader1xMaxValue = 1.0;
2240 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2241 } else {
2242 *pCaps->PixelShaderVersion = 0;
2243 *pCaps->PixelShader1xMaxValue = 0.0;
2244 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2247 /* ------------------------------------------------
2248 The following fields apply to d3d9 only
2249 ------------------------------------------------ */
2250 if (This->dxVersion > 8) {
2251 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2252 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2253 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2254 *pCaps->MaxNpatchTessellationLevel = 0;
2255 *pCaps->MasterAdapterOrdinal = 0;
2256 *pCaps->AdapterOrdinalInGroup = 0;
2257 *pCaps->NumberOfAdaptersInGroup = 1;
2259 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2260 /* OpenGL supports all the formats below, perhaps not always
2261 * without conversion, but it supports them.
2262 * Further GLSL doesn't seem to have an official unsigned type so
2263 * don't advertise it yet as I'm not sure how we handle it.
2264 * We might need to add some clamping in the shader engine to
2265 * support it.
2266 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2267 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2268 WINED3DDTCAPS_UBYTE4N |
2269 WINED3DDTCAPS_SHORT2N |
2270 WINED3DDTCAPS_SHORT4N;
2271 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2272 *pCaps->DeclTypes |=
2273 WINED3DDTCAPS_FLOAT16_2 |
2274 WINED3DDTCAPS_FLOAT16_4;
2276 } else
2277 *pCaps->DeclTypes = 0;
2279 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2282 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2283 WINED3DPTFILTERCAPS_MAGFPOINT |
2284 WINED3DPTFILTERCAPS_MINFLINEAR |
2285 WINED3DPTFILTERCAPS_MAGFLINEAR;
2286 *pCaps->VertexTextureFilterCaps = 0;
2288 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2289 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2290 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2291 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2292 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2293 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2294 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2296 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2297 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2298 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2299 *pCaps->VS20Caps.Caps = 0;
2300 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2301 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2302 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2304 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2305 *pCaps->MaxVertexShader30InstructionSlots = 0;
2306 } else { /* VS 1.x */
2307 *pCaps->VS20Caps.Caps = 0;
2308 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2309 *pCaps->VS20Caps.NumTemps = 0;
2310 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2312 *pCaps->MaxVShaderInstructionsExecuted = 0;
2313 *pCaps->MaxVertexShader30InstructionSlots = 0;
2316 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2317 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2318 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2320 /* 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 */
2321 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2322 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2323 WINED3DPS20CAPS_PREDICATION |
2324 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2325 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2326 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2327 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2328 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2329 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2331 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2332 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2333 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2334 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2335 *pCaps->PS20Caps.Caps = 0;
2336 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2337 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2338 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2339 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2341 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2342 *pCaps->MaxPixelShader30InstructionSlots = 0;
2343 } else { /* PS 1.x */
2344 *pCaps->PS20Caps.Caps = 0;
2345 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2346 *pCaps->PS20Caps.NumTemps = 0;
2347 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2348 *pCaps->PS20Caps.NumInstructionSlots = 0;
2350 *pCaps->MaxPShaderInstructionsExecuted = 0;
2351 *pCaps->MaxPixelShader30InstructionSlots = 0;
2355 return WINED3D_OK;
2358 static unsigned int glsl_program_key_hash(void *key) {
2359 glsl_program_key_t *k = (glsl_program_key_t *)key;
2361 unsigned int hash = k->vshader | k->pshader << 16;
2362 hash += ~(hash << 15);
2363 hash ^= (hash >> 10);
2364 hash += (hash << 3);
2365 hash ^= (hash >> 6);
2366 hash += ~(hash << 11);
2367 hash ^= (hash >> 16);
2369 return hash;
2372 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2373 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2374 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2376 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2379 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2380 and fields being inserted in the middle, a new structure is used in place */
2381 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2382 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2383 IUnknown *parent) {
2385 IWineD3DDeviceImpl *object = NULL;
2386 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2387 HDC hDC;
2388 int i;
2390 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2391 * number and create a device without a 3D adapter for 2D only operation.
2393 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2394 return WINED3DERR_INVALIDCALL;
2397 /* Create a WineD3DDevice object */
2398 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2399 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2400 TRACE("Created WineD3DDevice object @ %p\n", object);
2401 if (NULL == object) {
2402 return WINED3DERR_OUTOFVIDEOMEMORY;
2405 /* Set up initial COM information */
2406 object->lpVtbl = &IWineD3DDevice_Vtbl;
2407 object->ref = 1;
2408 object->wineD3D = iface;
2409 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2410 IWineD3D_AddRef(object->wineD3D);
2411 object->parent = parent;
2413 if(This->dxVersion == 7) {
2414 object->surface_alignment = 8;
2415 } else {
2416 object->surface_alignment = 4;
2419 /* Set the state up as invalid until the device is fully created */
2420 object->state = WINED3DERR_DRIVERINTERNALERROR;
2422 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2423 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2425 /* Save the creation parameters */
2426 object->createParms.AdapterOrdinal = Adapter;
2427 object->createParms.DeviceType = DeviceType;
2428 object->createParms.hFocusWindow = hFocusWindow;
2429 object->createParms.BehaviorFlags = BehaviourFlags;
2431 /* Initialize other useful values */
2432 object->adapterNo = Adapter;
2433 object->devType = DeviceType;
2435 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2436 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2437 object->shader_backend = &glsl_shader_backend;
2438 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2439 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2440 object->shader_backend = &arb_program_shader_backend;
2441 } else {
2442 object->shader_backend = &none_shader_backend;
2445 /* set the state of the device to valid */
2446 object->state = WINED3D_OK;
2448 /* Get the initial screen setup for ddraw */
2449 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2450 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2451 hDC = GetDC(0);
2452 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2453 ReleaseDC(0, hDC);
2455 for(i = 0; i < PATCHMAP_SIZE; i++) {
2456 list_init(&object->patches[i]);
2458 return WINED3D_OK;
2460 #undef GLINFO_LOCATION
2462 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2463 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2464 IUnknown_AddRef(This->parent);
2465 *pParent = This->parent;
2466 return WINED3D_OK;
2469 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2470 IUnknown* surfaceParent;
2471 TRACE("(%p) call back\n", pSurface);
2473 /* Now, release the parent, which will take care of cleaning up the surface for us */
2474 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2475 IUnknown_Release(surfaceParent);
2476 return IUnknown_Release(surfaceParent);
2479 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2480 IUnknown* volumeParent;
2481 TRACE("(%p) call back\n", pVolume);
2483 /* Now, release the parent, which will take care of cleaning up the volume for us */
2484 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2485 IUnknown_Release(volumeParent);
2486 return IUnknown_Release(volumeParent);
2489 #define PUSH1(att) attribs[nAttribs++] = (att);
2490 #define GLINFO_LOCATION (Adapters[0].gl_info)
2491 BOOL InitAdapters(void) {
2492 BOOL ret;
2493 int ps_selected_mode, vs_selected_mode;
2495 /* No need to hold any lock. The calling library makes sure only one thread calls
2496 * wined3d simultaneously
2498 if(numAdapters > 0) return TRUE;
2500 TRACE("Initializing adapters\n");
2501 /* For now only one default adapter */
2503 int attribute;
2504 DISPLAY_DEVICEW DisplayDevice;
2506 TRACE("Initializing default adapter\n");
2507 Adapters[0].monitorPoint.x = -1;
2508 Adapters[0].monitorPoint.y = -1;
2510 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2511 if(!ret) {
2512 ERR("Failed to initialize gl caps for default adapter\n");
2513 HeapFree(GetProcessHeap(), 0, Adapters);
2514 return FALSE;
2516 ret = initPixelFormats(&Adapters[0].gl_info);
2517 if(!ret) {
2518 ERR("Failed to init gl formats\n");
2519 HeapFree(GetProcessHeap(), 0, Adapters);
2520 return FALSE;
2523 Adapters[0].driver = "Display";
2524 Adapters[0].description = "Direct3D HAL";
2526 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2527 DisplayDevice.cb = sizeof(DisplayDevice);
2528 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2529 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2530 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2532 if (WineD3D_CreateFakeGLContext()) {
2533 int iPixelFormat;
2534 int attribs[8];
2535 int values[8];
2536 int nAttribs = 0;
2537 int res;
2538 WineD3D_PixelFormat *cfgs;
2540 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2541 GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2543 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2544 cfgs = Adapters[0].cfgs;
2545 PUSH1(WGL_RED_BITS_ARB)
2546 PUSH1(WGL_GREEN_BITS_ARB)
2547 PUSH1(WGL_BLUE_BITS_ARB)
2548 PUSH1(WGL_ALPHA_BITS_ARB)
2549 PUSH1(WGL_DEPTH_BITS_ARB)
2550 PUSH1(WGL_STENCIL_BITS_ARB)
2552 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2553 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, iPixelFormat, 0, nAttribs, attribs, values));
2555 if(!res)
2556 continue;
2558 /* Cache the pixel format */
2559 cfgs->iPixelFormat = iPixelFormat;
2560 cfgs->redSize = values[0];
2561 cfgs->greenSize = values[1];
2562 cfgs->blueSize = values[2];
2563 cfgs->alphaSize = values[3];
2564 cfgs->depthSize = values[4];
2565 cfgs->stencilSize = values[5];
2567 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);
2568 cfgs++;
2570 WineD3D_ReleaseFakeGLContext();
2573 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2574 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2577 numAdapters = 1;
2578 TRACE("%d adapters successfully initialized\n", numAdapters);
2580 return TRUE;
2582 #undef PUSH1
2583 #undef GLINFO_LOCATION
2585 /**********************************************************
2586 * IWineD3D VTbl follows
2587 **********************************************************/
2589 const IWineD3DVtbl IWineD3D_Vtbl =
2591 /* IUnknown */
2592 IWineD3DImpl_QueryInterface,
2593 IWineD3DImpl_AddRef,
2594 IWineD3DImpl_Release,
2595 /* IWineD3D */
2596 IWineD3DImpl_GetParent,
2597 IWineD3DImpl_GetAdapterCount,
2598 IWineD3DImpl_RegisterSoftwareDevice,
2599 IWineD3DImpl_GetAdapterMonitor,
2600 IWineD3DImpl_GetAdapterModeCount,
2601 IWineD3DImpl_EnumAdapterModes,
2602 IWineD3DImpl_GetAdapterDisplayMode,
2603 IWineD3DImpl_GetAdapterIdentifier,
2604 IWineD3DImpl_CheckDeviceMultiSampleType,
2605 IWineD3DImpl_CheckDepthStencilMatch,
2606 IWineD3DImpl_CheckDeviceType,
2607 IWineD3DImpl_CheckDeviceFormat,
2608 IWineD3DImpl_CheckDeviceFormatConversion,
2609 IWineD3DImpl_GetDeviceCaps,
2610 IWineD3DImpl_CreateDevice