push 4d5485f9b89f417d46b39b93e8d940437007f325
[wine/hacks.git] / dlls / wined3d / directx.c
blobbef0c3fe34d33a1c28ab766d37a1bd8e70e9f466
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 = wglGetCurrentContext();
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 wglMakeCurrent(NULL, NULL);
178 wglDeleteContext(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 = wglGetCurrentContext();
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 = wglCreateContext(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 (!wglMakeCurrent(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) wglDeleteContext(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;
407 PROC (WINAPI *p_wglGetProcAddress)(LPCSTR lpszProc);
409 /* Make sure that we've got a context */
410 /* TODO: CreateFakeGLContext should really take a display as a parameter */
411 /* Only save the values obtained when a display is provided */
412 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
413 return_value = FALSE;
415 TRACE_(d3d_caps)("(%p)\n", gl_info);
417 #ifdef USE_WIN32_OPENGL
418 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, (const char *) #pfn);
419 mod_gl = LoadLibraryA("opengl32.dll");
420 if(!mod_gl) {
421 ERR("Can't load opengl32.dll!\n");
422 return FALSE;
424 #else
425 #define USE_GL_FUNC(pfn) pfn = (void*)p_wglGetProcAddress( (const char *) #pfn);
426 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
427 mod_gl = LoadLibraryA("gdi32.dll");
428 if(!mod_gl) {
429 ERR("Can't load gdi32.dll!\n");
430 return FALSE;
432 #endif
434 p_wglGetProcAddress = (void*)GetProcAddress(mod_gl, "wglGetProcAddress");
435 if(!p_wglGetProcAddress) {
436 ERR("Unable to load wglGetProcAddress!\n");
437 return FALSE;
440 /* Dynamicly load all GL core functions */
441 GL_FUNCS_GEN;
442 #undef USE_GL_FUNC
444 gl_string = (const char *) glGetString(GL_RENDERER);
445 if (NULL == gl_string)
446 gl_string = "None";
447 strcpy(gl_info->gl_renderer, gl_string);
449 gl_string = (const char *) glGetString(GL_VENDOR);
450 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
451 if (gl_string != NULL) {
452 /* Fill in the GL vendor */
453 if (strstr(gl_string, "NVIDIA")) {
454 gl_info->gl_vendor = VENDOR_NVIDIA;
455 } else if (strstr(gl_string, "ATI")) {
456 gl_info->gl_vendor = VENDOR_ATI;
457 } else if (strstr(gl_string, "Intel(R)") ||
458 strstr(gl_info->gl_renderer, "Intel(R)")) {
459 gl_info->gl_vendor = VENDOR_INTEL;
460 } else if (strstr(gl_string, "Mesa")) {
461 gl_info->gl_vendor = VENDOR_MESA;
462 } else {
463 gl_info->gl_vendor = VENDOR_WINE;
465 } else {
466 gl_info->gl_vendor = VENDOR_WINE;
470 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
472 /* Parse the GL_VERSION field into major and minor information */
473 gl_string = (const char *) glGetString(GL_VERSION);
474 if (gl_string != NULL) {
476 switch (gl_info->gl_vendor) {
477 case VENDOR_NVIDIA:
478 gl_string_cursor = strstr(gl_string, "NVIDIA");
479 if (!gl_string_cursor) {
480 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
481 break;
484 gl_string_cursor = strstr(gl_string_cursor, " ");
485 if (!gl_string_cursor) {
486 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
487 break;
490 while (*gl_string_cursor == ' ') {
491 ++gl_string_cursor;
494 if (!*gl_string_cursor) {
495 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
496 break;
499 major = atoi(gl_string_cursor);
500 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
501 ++gl_string_cursor;
504 if (*gl_string_cursor++ != '.') {
505 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
506 break;
509 minor = atoi(gl_string_cursor);
510 minor = major*100+minor;
511 major = 10;
513 break;
515 case VENDOR_ATI:
516 major = minor = 0;
517 gl_string_cursor = strchr(gl_string, '-');
518 if (gl_string_cursor) {
519 int error = 0;
520 gl_string_cursor++;
522 /* Check if version number is of the form x.y.z */
523 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
524 error = 1;
525 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
526 error = 1;
527 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
528 error = 1;
529 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
530 error = 1;
532 /* Mark version number as malformed */
533 if (error)
534 gl_string_cursor = 0;
537 if (!gl_string_cursor)
538 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
539 else {
540 major = *gl_string_cursor - '0';
541 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
543 break;
545 case VENDOR_INTEL:
546 case VENDOR_MESA:
547 gl_string_cursor = strstr(gl_string, "Mesa");
548 gl_string_cursor = strstr(gl_string_cursor, " ");
549 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
550 if (*gl_string_cursor) {
551 char tmp[16];
552 int cursor = 0;
554 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
555 tmp[cursor++] = *gl_string_cursor;
556 ++gl_string_cursor;
558 tmp[cursor] = 0;
559 major = atoi(tmp);
561 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
562 ++gl_string_cursor;
564 cursor = 0;
565 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
566 tmp[cursor++] = *gl_string_cursor;
567 ++gl_string_cursor;
569 tmp[cursor] = 0;
570 minor = atoi(tmp);
572 break;
574 default:
575 major = 0;
576 minor = 9;
578 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
579 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
582 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
585 * Initialize openGL extension related variables
586 * with Default values
588 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
589 gl_info->max_buffers = 1;
590 gl_info->max_textures = 1;
591 gl_info->max_texture_stages = 1;
592 gl_info->max_fragment_samplers = 1;
593 gl_info->max_vertex_samplers = 0;
594 gl_info->max_combined_samplers = 0;
595 gl_info->max_sampler_stages = 1;
596 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
597 gl_info->ps_arb_max_temps = 0;
598 gl_info->ps_arb_max_instructions = 0;
599 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
600 gl_info->vs_arb_max_temps = 0;
601 gl_info->vs_arb_max_instructions = 0;
602 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
603 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
604 gl_info->vs_glsl_constantsF = 0;
605 gl_info->ps_glsl_constantsF = 0;
606 gl_info->vs_arb_constantsF = 0;
607 gl_info->ps_arb_constantsF = 0;
609 /* Now work out what GL support this card really has */
610 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) p_wglGetProcAddress( (const char *) #pfn);
611 GL_EXT_FUNCS_GEN;
612 WGL_EXT_FUNCS_GEN;
613 #undef USE_GL_FUNC
615 /* Retrieve opengl defaults */
616 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
617 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
618 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
620 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
621 gl_info->max_lights = gl_max;
622 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
624 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
625 gl_info->max_texture_size = gl_max;
626 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
628 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
629 gl_info->max_pointsize = gl_floatv[1];
630 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
632 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
633 gl_info->max_aux_buffers = gl_max;
634 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
636 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
637 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
638 TRACE_(d3d_caps)("GL_Extensions reported:\n");
640 if (NULL == GL_Extensions) {
641 ERR(" GL_Extensions returns NULL\n");
642 } else {
643 while (*GL_Extensions != 0x00) {
644 const char *Start;
645 char ThisExtn[256];
646 size_t len;
648 while (isspace(*GL_Extensions)) GL_Extensions++;
649 Start = GL_Extensions;
650 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
651 GL_Extensions++;
654 len = GL_Extensions - Start;
655 if (len == 0 || len >= sizeof(ThisExtn))
656 continue;
658 memcpy(ThisExtn, Start, len);
659 ThisExtn[len] = '\0';
660 TRACE_(d3d_caps)("- %s\n", ThisExtn);
662 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
663 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
664 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
665 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
666 break;
671 if (gl_info->supported[APPLE_FENCE]) {
672 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
673 * The apple extension interacts with some other apple exts. Disable the NV
674 * extension if the apple one is support to prevent confusion in other parts
675 * of the code
677 gl_info->supported[NV_FENCE] = FALSE;
679 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
680 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
681 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
683 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
684 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
685 * Won't occur in any real world situation though
687 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
689 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
690 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
691 gl_info->max_buffers = gl_max;
692 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
694 if (gl_info->supported[ARB_MULTITEXTURE]) {
695 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
696 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
697 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
699 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
700 GLint tmp;
701 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
702 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
703 } else {
704 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
706 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
708 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
709 GLint tmp;
710 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
711 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
712 } else {
713 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
715 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
717 if (gl_info->supported[ARB_VERTEX_SHADER]) {
718 GLint tmp;
719 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
720 gl_info->max_vertex_samplers = tmp;
721 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
722 gl_info->max_combined_samplers = tmp;
723 } else {
724 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
726 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
727 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
729 if (gl_info->supported[ARB_VERTEX_BLEND]) {
730 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
731 gl_info->max_blends = gl_max;
732 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
734 if (gl_info->supported[EXT_TEXTURE3D]) {
735 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
736 gl_info->max_texture3d_size = gl_max;
737 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
739 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
740 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
741 gl_info->max_anisotropy = gl_max;
742 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
744 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
745 gl_info->ps_arb_version = PS_VERSION_11;
746 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
747 gl_info->ps_arb_constantsF = gl_max;
748 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
749 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
750 gl_info->ps_arb_max_temps = gl_max;
751 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info->ps_arb_max_temps);
752 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
753 gl_info->ps_arb_max_instructions = gl_max;
754 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info->ps_arb_max_instructions);
756 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
757 gl_info->vs_arb_version = VS_VERSION_11;
758 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
759 gl_info->vs_arb_constantsF = gl_max;
760 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
761 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
762 gl_info->vs_arb_max_temps = gl_max;
763 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info->vs_arb_max_temps);
764 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
765 gl_info->vs_arb_max_instructions = gl_max;
766 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info->vs_arb_max_instructions);
768 if (gl_info->supported[ARB_VERTEX_SHADER]) {
769 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
770 gl_info->vs_glsl_constantsF = gl_max / 4;
771 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
773 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
774 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
775 gl_info->ps_glsl_constantsF = gl_max / 4;
776 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
778 if (gl_info->supported[EXT_VERTEX_SHADER]) {
779 gl_info->vs_ati_version = VS_VERSION_11;
781 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
782 gl_info->vs_nv_version = VS_VERSION_30;
783 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
784 gl_info->vs_nv_version = VS_VERSION_20;
785 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
786 gl_info->vs_nv_version = VS_VERSION_11;
787 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
788 gl_info->vs_nv_version = VS_VERSION_10;
790 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
791 gl_info->ps_nv_version = PS_VERSION_30;
792 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
793 gl_info->ps_nv_version = PS_VERSION_20;
797 checkGLcall("extension detection\n");
799 /* In some cases the number of texture stages can be larger than the number
800 * of samplers. The GF4 for example can use only 2 samplers (no fragment
801 * shaders), but 8 texture stages (register combiners). */
802 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
804 /* We can only use ORM_FBO when the hardware supports it. */
805 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
806 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
807 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
810 /* MRTs are currently only supported when FBOs are used. */
811 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
812 gl_info->max_buffers = 1;
815 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
816 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
817 * in case of the latest videocards in the number of pixel/vertex pipelines.
819 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
820 * rendering. Various games use this information to get a rough estimation of the features of the card
821 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
822 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
823 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
824 * not the PCI id.
826 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
827 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
828 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
829 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
830 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
831 * is used for rendering which is not always the case). This would work but it is not very portable. Second
832 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
833 * is limited.
835 * As said most games only use the PCI id to get an indication of the capabilities of the card.
836 * It doesn't really matter if the given id is the correct one if we return the id of a card with
837 * similar 3d features.
839 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
840 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
841 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
842 * won't pass we return a default card. This way is better than maintaining a full card database as even
843 * without a full database we can return a card with similar features. Second the size of the database
844 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
845 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
846 * to distinguishes between different models from that family.
848 switch (gl_info->gl_vendor) {
849 case VENDOR_NVIDIA:
850 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
851 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
853 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
854 if (strstr(gl_info->gl_renderer, "7800") ||
855 strstr(gl_info->gl_renderer, "7900") ||
856 strstr(gl_info->gl_renderer, "7950") ||
857 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
858 strstr(gl_info->gl_renderer, "Quadro FX 5"))
859 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
860 else if(strstr(gl_info->gl_renderer, "6800") ||
861 strstr(gl_info->gl_renderer, "7600"))
862 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
863 else if(strstr(gl_info->gl_renderer, "6600") ||
864 strstr(gl_info->gl_renderer, "6610") ||
865 strstr(gl_info->gl_renderer, "6700"))
866 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
867 else
868 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
869 } else if(WINE_D3D9_CAPABLE(gl_info)) {
870 if (strstr(gl_info->gl_renderer, "5800") ||
871 strstr(gl_info->gl_renderer, "5900") ||
872 strstr(gl_info->gl_renderer, "5950") ||
873 strstr(gl_info->gl_renderer, "Quadro FX"))
874 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
875 else if(strstr(gl_info->gl_renderer, "5600") ||
876 strstr(gl_info->gl_renderer, "5650") ||
877 strstr(gl_info->gl_renderer, "5700") ||
878 strstr(gl_info->gl_renderer, "5750"))
879 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
880 else
881 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
882 } else if(WINE_D3D8_CAPABLE(gl_info)) {
883 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
884 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
885 else
886 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
887 } else if(WINE_D3D7_CAPABLE(gl_info)) {
888 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
889 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
890 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
891 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
892 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
893 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
894 else
895 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
896 } else {
897 if (strstr(gl_info->gl_renderer, "TNT2"))
898 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
899 else
900 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
902 break;
903 case VENDOR_ATI:
904 if(WINE_D3D9_CAPABLE(gl_info)) {
905 /* Radeon R5xx */
906 if (strstr(gl_info->gl_renderer, "X1600") ||
907 strstr(gl_info->gl_renderer, "X1800") ||
908 strstr(gl_info->gl_renderer, "X1900") ||
909 strstr(gl_info->gl_renderer, "X1950"))
910 gl_info->gl_card = CARD_ATI_RADEON_X1600;
911 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
912 else if(strstr(gl_info->gl_renderer, "X700") ||
913 strstr(gl_info->gl_renderer, "X800") ||
914 strstr(gl_info->gl_renderer, "X850") ||
915 strstr(gl_info->gl_renderer, "X1300") ||
916 strstr(gl_info->gl_renderer, "X1400"))
917 gl_info->gl_card = CARD_ATI_RADEON_X700;
918 /* Radeon R3xx */
919 else
920 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
921 } else if(WINE_D3D8_CAPABLE(gl_info)) {
922 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
923 } else if(WINE_D3D7_CAPABLE(gl_info)) {
924 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
925 } else
926 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
927 break;
928 case VENDOR_INTEL:
929 if (strstr(gl_info->gl_renderer, "915GM")) {
930 gl_info->gl_card = CARD_INTEL_I915GM;
931 } else if (strstr(gl_info->gl_renderer, "915G")) {
932 gl_info->gl_card = CARD_INTEL_I915G;
933 } else if (strstr(gl_info->gl_renderer, "865G")) {
934 gl_info->gl_card = CARD_INTEL_I865G;
935 } else if (strstr(gl_info->gl_renderer, "855G")) {
936 gl_info->gl_card = CARD_INTEL_I855G;
937 } else if (strstr(gl_info->gl_renderer, "830G")) {
938 gl_info->gl_card = CARD_INTEL_I830G;
939 } else {
940 gl_info->gl_card = CARD_INTEL_I915G;
942 break;
943 case VENDOR_MESA:
944 case VENDOR_WINE:
945 default:
946 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
947 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
948 * them a good generic choice.
950 gl_info->gl_vendor = VENDOR_NVIDIA;
951 if(WINE_D3D9_CAPABLE(gl_info))
952 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
953 else if(WINE_D3D8_CAPABLE(gl_info))
954 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
955 else if(WINE_D3D7_CAPABLE(gl_info))
956 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
957 else if(WINE_D3D6_CAPABLE(gl_info))
958 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
959 else
960 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
962 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
964 /* Load all the lookup tables
965 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
966 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
967 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
969 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
970 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
973 for (i = 0; i < MAX_LOOKUPS; i++) {
974 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
977 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
978 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
979 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
980 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
981 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
982 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
983 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
984 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
985 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
986 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
988 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
989 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
990 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
991 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
992 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
995 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
996 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
997 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
998 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
999 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1000 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1001 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1002 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1003 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1004 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1005 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1006 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1007 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1009 /* TODO: config lookups */
1011 /* Make sure there's an active HDC else the WGL extensions will fail */
1012 hdc = wglGetCurrentDC();
1013 if (hdc) {
1014 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1015 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1017 if (NULL == WGL_Extensions) {
1018 ERR(" WGL_Extensions returns NULL\n");
1019 } else {
1020 while (*WGL_Extensions != 0x00) {
1021 const char *Start;
1022 char ThisExtn[256];
1023 size_t len;
1025 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1026 Start = WGL_Extensions;
1027 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1028 WGL_Extensions++;
1031 len = WGL_Extensions - Start;
1032 if (len == 0 || len >= sizeof(ThisExtn))
1033 continue;
1035 memcpy(ThisExtn, Start, len);
1036 ThisExtn[len] = '\0';
1037 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1039 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1040 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1041 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1048 WineD3D_ReleaseFakeGLContext();
1049 return return_value;
1051 #undef GLINFO_LOCATION
1053 /**********************************************************
1054 * IWineD3D implementation follows
1055 **********************************************************/
1057 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1058 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1060 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1061 return numAdapters;
1064 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1065 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1066 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1067 return WINED3D_OK;
1070 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1071 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1073 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1074 return NULL;
1077 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1078 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1081 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1082 of the same bpp but different resolutions */
1084 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1085 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1086 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1087 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1089 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1090 return 0;
1093 /* TODO: Store modes per adapter and read it from the adapter structure */
1094 if (Adapter == 0) { /* Display */
1095 int i = 0;
1096 int j = 0;
1098 if (!DEBUG_SINGLE_MODE) {
1099 DEVMODEW DevModeW;
1101 ZeroMemory(&DevModeW, sizeof(DevModeW));
1102 DevModeW.dmSize = sizeof(DevModeW);
1103 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1104 j++;
1105 switch (Format)
1107 case WINED3DFMT_UNKNOWN:
1108 /* This is for D3D8, do not enumerate P8 here */
1109 if (DevModeW.dmBitsPerPel == 32 ||
1110 DevModeW.dmBitsPerPel == 16) i++;
1111 break;
1112 case WINED3DFMT_X8R8G8B8:
1113 if (DevModeW.dmBitsPerPel == 32) i++;
1114 break;
1115 case WINED3DFMT_R5G6B5:
1116 if (DevModeW.dmBitsPerPel == 16) i++;
1117 break;
1118 case WINED3DFMT_P8:
1119 if (DevModeW.dmBitsPerPel == 8) i++;
1120 break;
1121 default:
1122 /* Skip other modes as they do not match the requested format */
1123 break;
1126 } else {
1127 i = 1;
1128 j = 1;
1131 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1132 return i;
1133 } else {
1134 FIXME_(d3d_caps)("Adapter not primary display\n");
1136 return 0;
1139 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1140 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1141 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1142 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1144 /* Validate the parameters as much as possible */
1145 if (NULL == pMode ||
1146 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1147 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1148 return WINED3DERR_INVALIDCALL;
1151 /* TODO: Store modes per adapter and read it from the adapter structure */
1152 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1153 DEVMODEW DevModeW;
1154 int ModeIdx = 0;
1155 int i = 0;
1156 int j = 0;
1158 ZeroMemory(&DevModeW, sizeof(DevModeW));
1159 DevModeW.dmSize = sizeof(DevModeW);
1161 /* If we are filtering to a specific format (D3D9), then need to skip
1162 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1163 just count through the ones with valid bit depths */
1164 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1165 switch (Format)
1167 case WINED3DFMT_UNKNOWN:
1168 /* This is D3D8. Do not enumerate P8 here */
1169 if (DevModeW.dmBitsPerPel == 32 ||
1170 DevModeW.dmBitsPerPel == 16) i++;
1171 break;
1172 case WINED3DFMT_X8R8G8B8:
1173 if (DevModeW.dmBitsPerPel == 32) i++;
1174 break;
1175 case WINED3DFMT_R5G6B5:
1176 if (DevModeW.dmBitsPerPel == 16) i++;
1177 break;
1178 case WINED3DFMT_P8:
1179 if (DevModeW.dmBitsPerPel == 8) i++;
1180 break;
1181 default:
1182 /* Modes that don't match what we support can get an early-out */
1183 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1184 return WINED3DERR_INVALIDCALL;
1188 if (i == 0) {
1189 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1190 return WINED3DERR_INVALIDCALL;
1192 ModeIdx = j - 1;
1194 /* Now get the display mode via the calculated index */
1195 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1196 pMode->Width = DevModeW.dmPelsWidth;
1197 pMode->Height = DevModeW.dmPelsHeight;
1198 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1199 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1200 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1202 if (Format == WINED3DFMT_UNKNOWN)
1204 switch (DevModeW.dmBitsPerPel)
1206 case 8:
1207 pMode->Format = WINED3DFMT_P8;
1208 break;
1209 case 16:
1210 pMode->Format = WINED3DFMT_R5G6B5;
1211 break;
1212 case 32:
1213 pMode->Format = WINED3DFMT_X8R8G8B8;
1214 break;
1215 default:
1216 pMode->Format = WINED3DFMT_UNKNOWN;
1217 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1219 } else {
1220 pMode->Format = Format;
1222 } else {
1223 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1224 return WINED3DERR_INVALIDCALL;
1227 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1228 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1229 DevModeW.dmBitsPerPel);
1231 } else if (DEBUG_SINGLE_MODE) {
1232 /* Return one setting of the format requested */
1233 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1234 pMode->Width = 800;
1235 pMode->Height = 600;
1236 pMode->RefreshRate = 60;
1237 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1238 } else {
1239 FIXME_(d3d_caps)("Adapter not primary display\n");
1242 return WINED3D_OK;
1245 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1246 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1247 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1249 if (NULL == pMode ||
1250 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1251 return WINED3DERR_INVALIDCALL;
1254 if (Adapter == 0) { /* Display */
1255 int bpp = 0;
1256 DEVMODEW DevModeW;
1258 ZeroMemory(&DevModeW, sizeof(DevModeW));
1259 DevModeW.dmSize = sizeof(DevModeW);
1261 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1262 pMode->Width = DevModeW.dmPelsWidth;
1263 pMode->Height = DevModeW.dmPelsHeight;
1264 bpp = DevModeW.dmBitsPerPel;
1265 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1266 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1268 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1271 switch (bpp) {
1272 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1273 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1274 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1275 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1276 default: pMode->Format = WINED3DFMT_UNKNOWN;
1279 } else {
1280 FIXME_(d3d_caps)("Adapter not primary display\n");
1283 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1284 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1285 return WINED3D_OK;
1288 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1289 and fields being inserted in the middle, a new structure is used in place */
1290 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1291 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1292 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1294 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1296 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1297 return WINED3DERR_INVALIDCALL;
1300 /* Return the information requested */
1301 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1302 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1303 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1305 /* Note dx8 doesn't supply a DeviceName */
1306 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1307 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1308 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1309 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1310 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1311 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1312 *(pIdentifier->SubSysId) = 0;
1313 *(pIdentifier->Revision) = 0;
1315 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1316 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1317 *(pIdentifier->WHQLLevel) = 0;
1318 } else {
1319 *(pIdentifier->WHQLLevel) = 1;
1322 return WINED3D_OK;
1325 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1326 short redSize, greenSize, blueSize, alphaSize, colorBits;
1328 if(!cfg)
1329 return FALSE;
1331 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1332 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1333 return FALSE;
1336 if(cfg->redSize < redSize)
1337 return FALSE;
1339 if(cfg->greenSize < greenSize)
1340 return FALSE;
1342 if(cfg->blueSize < blueSize)
1343 return FALSE;
1345 if(cfg->alphaSize < alphaSize)
1346 return FALSE;
1348 return TRUE;
1351 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1352 short depthSize, stencilSize;
1354 if(!cfg)
1355 return FALSE;
1357 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1358 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1359 return FALSE;
1362 if(cfg->depthSize < depthSize)
1363 return FALSE;
1365 if(cfg->stencilSize < stencilSize)
1366 return FALSE;
1368 return TRUE;
1371 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1372 WINED3DFORMAT AdapterFormat,
1373 WINED3DFORMAT RenderTargetFormat,
1374 WINED3DFORMAT DepthStencilFormat) {
1375 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1376 int nCfgs;
1377 WineD3D_PixelFormat *cfgs;
1378 int it;
1380 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1381 This, Adapter,
1382 DeviceType, debug_d3ddevicetype(DeviceType),
1383 AdapterFormat, debug_d3dformat(AdapterFormat),
1384 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1385 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1387 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1388 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1389 return WINED3DERR_INVALIDCALL;
1392 cfgs = Adapters[Adapter].cfgs;
1393 nCfgs = Adapters[Adapter].nCfgs;
1394 for (it = 0; it < nCfgs; ++it) {
1395 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1396 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1397 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1398 return WINED3D_OK;
1402 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1404 return WINED3DERR_NOTAVAILABLE;
1407 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1408 WINED3DFORMAT SurfaceFormat,
1409 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1411 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1412 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1413 This,
1414 Adapter,
1415 DeviceType, debug_d3ddevicetype(DeviceType),
1416 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1417 Windowed,
1418 MultiSampleType,
1419 pQualityLevels);
1421 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1422 return WINED3DERR_INVALIDCALL;
1425 /* TODO: Store in Adapter structure */
1426 if (pQualityLevels != NULL) {
1427 static int s_single_shot = 0;
1428 if (!s_single_shot) {
1429 FIXME("Quality levels unsupported at present\n");
1430 s_single_shot = 1;
1432 *pQualityLevels = 1; /* Guess at a value! */
1435 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1436 return WINED3DERR_NOTAVAILABLE;
1439 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1440 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1442 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1443 int nCfgs = 0;
1444 WineD3D_PixelFormat *cfgs;
1445 int it;
1446 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1448 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1449 This,
1450 Adapter,
1451 CheckType, debug_d3ddevicetype(CheckType),
1452 DisplayFormat, debug_d3dformat(DisplayFormat),
1453 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1454 Windowed);
1456 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1457 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1458 return WINED3DERR_INVALIDCALL;
1461 cfgs = Adapters[Adapter].cfgs;
1462 nCfgs = Adapters[Adapter].nCfgs;
1463 for (it = 0; it < nCfgs; ++it) {
1464 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1465 hr = WINED3D_OK;
1466 TRACE_(d3d_caps)("OK\n");
1467 break ;
1471 if(hr != WINED3D_OK)
1472 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1474 if(hr != WINED3D_OK)
1475 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1477 return hr;
1480 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1481 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1482 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1483 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1484 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1485 This,
1486 Adapter,
1487 DeviceType, debug_d3ddevicetype(DeviceType),
1488 AdapterFormat, debug_d3dformat(AdapterFormat),
1489 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1490 RType, debug_d3dresourcetype(RType),
1491 CheckFormat, debug_d3dformat(CheckFormat));
1493 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1494 return WINED3DERR_INVALIDCALL;
1497 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1498 switch (CheckFormat) {
1499 /* Filtering not supported */
1500 case WINED3DFMT_A32B32G32R32F:
1501 TRACE_(d3d_caps)("[FAILED]\n");
1502 return WINED3DERR_NOTAVAILABLE;
1503 default:
1504 break;
1508 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1509 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1510 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1511 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1512 if (!GL_LIMITS(vertex_samplers)) {
1513 TRACE_(d3d_caps)("[FAILED]\n");
1514 return WINED3DERR_NOTAVAILABLE;
1517 switch (CheckFormat) {
1518 case WINED3DFMT_A32B32G32R32F:
1519 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1520 TRACE_(d3d_caps)("[FAILED]\n");
1521 return WINED3DERR_NOTAVAILABLE;
1523 TRACE_(d3d_caps)("[OK]\n");
1524 return WINED3D_OK;
1526 default:
1527 TRACE_(d3d_caps)("[FAILED]\n");
1528 return WINED3DERR_NOTAVAILABLE;
1532 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1533 switch (CheckFormat) {
1534 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1535 * Windows supports only those 3, and enumerating the other formats confuses applications
1537 case WINED3DFMT_D24S8:
1538 case WINED3DFMT_D24X8:
1539 case WINED3DFMT_D16:
1540 TRACE_(d3d_caps)("[OK]\n");
1541 return WINED3D_OK;
1542 case WINED3DFMT_D16_LOCKABLE:
1543 case WINED3DFMT_D24FS8:
1544 case WINED3DFMT_D32F_LOCKABLE:
1545 case WINED3DFMT_D24X4S4:
1546 case WINED3DFMT_D15S1:
1547 case WINED3DFMT_D32:
1548 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1549 return WINED3DERR_NOTAVAILABLE;
1550 default:
1551 TRACE_(d3d_caps)("[FAILED]\n");
1552 return WINED3DERR_NOTAVAILABLE;
1554 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1555 switch (CheckFormat) {
1556 case WINED3DFMT_R8G8B8:
1557 case WINED3DFMT_A8R8G8B8:
1558 case WINED3DFMT_X8R8G8B8:
1559 case WINED3DFMT_R5G6B5:
1560 case WINED3DFMT_X1R5G5B5:
1561 case WINED3DFMT_A1R5G5B5:
1562 case WINED3DFMT_A4R4G4B4:
1563 case WINED3DFMT_R3G3B2:
1564 case WINED3DFMT_X4R4G4B4:
1565 case WINED3DFMT_A8B8G8R8:
1566 case WINED3DFMT_X8B8G8R8:
1567 case WINED3DFMT_P8:
1568 TRACE_(d3d_caps)("[OK]\n");
1569 return WINED3D_OK;
1570 case WINED3DFMT_R16F:
1571 case WINED3DFMT_A16B16G16R16F:
1572 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1573 TRACE_(d3d_caps)("[FAILED]\n");
1574 return WINED3DERR_NOTAVAILABLE;
1576 TRACE_(d3d_caps)("[OK]\n");
1577 return WINED3D_OK;
1578 case WINED3DFMT_A32B32G32R32F:
1579 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1580 TRACE_(d3d_caps)("[FAILED]\n");
1581 return WINED3DERR_NOTAVAILABLE;
1583 TRACE_(d3d_caps)("[OK]\n");
1584 return WINED3D_OK;
1585 default:
1586 TRACE_(d3d_caps)("[FAILED]\n");
1587 return WINED3DERR_NOTAVAILABLE;
1589 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1590 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1591 switch (CheckFormat) {
1592 case WINED3DFMT_V8U8:
1593 TRACE_(d3d_caps)("[OK]\n");
1594 return WINED3D_OK;
1595 /* TODO: Other bump map formats */
1596 default:
1597 TRACE_(d3d_caps)("[FAILED]\n");
1598 return WINED3DERR_NOTAVAILABLE;
1601 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1602 switch (CheckFormat) {
1603 case WINED3DFMT_V8U8:
1604 TRACE_(d3d_caps)("[OK]\n");
1605 return WINED3D_OK;
1606 default:
1607 TRACE_(d3d_caps)("[FAILED]\n");
1608 return WINED3DERR_NOTAVAILABLE;
1611 TRACE_(d3d_caps)("[FAILED]\n");
1612 return WINED3DERR_NOTAVAILABLE;
1615 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1616 switch (CheckFormat) {
1617 case WINED3DFMT_DXT1:
1618 case WINED3DFMT_DXT2:
1619 case WINED3DFMT_DXT3:
1620 case WINED3DFMT_DXT4:
1621 case WINED3DFMT_DXT5:
1622 TRACE_(d3d_caps)("[OK]\n");
1623 return WINED3D_OK;
1624 default:
1625 break; /* Avoid compiler warnings */
1629 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1630 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1631 switch (CheckFormat) {
1632 case WINED3DFMT_A8R8G8B8:
1633 case WINED3DFMT_X8R8G8B8:
1634 case WINED3DFMT_A4R4G4B4:
1635 case WINED3DFMT_L8:
1636 case WINED3DFMT_A8L8:
1637 case WINED3DFMT_DXT1:
1638 case WINED3DFMT_DXT2:
1639 case WINED3DFMT_DXT3:
1640 case WINED3DFMT_DXT4:
1641 case WINED3DFMT_DXT5:
1642 TRACE_(d3d_caps)("[OK]\n");
1643 return WINED3D_OK;
1645 default:
1646 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1647 return WINED3DERR_NOTAVAILABLE;
1651 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1653 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1655 switch (CheckFormat) {
1656 case WINED3DFMT_R16F:
1657 case WINED3DFMT_A16B16G16R16F:
1658 if (!half_pixel_support) break;
1659 case WINED3DFMT_R32F:
1660 case WINED3DFMT_A32B32G32R32F:
1661 TRACE_(d3d_caps)("[OK]\n");
1662 return WINED3D_OK;
1663 default:
1664 break; /* Avoid compiler warnings */
1668 /* This format is nothing special and it is supported perfectly.
1669 * However, ati and nvidia driver on windows do not mark this format as
1670 * supported (tested with the dxCapsViewer) and pretending to
1671 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1672 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1673 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1675 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1676 TRACE_(d3d_caps)("[FAILED]\n");
1677 return WINED3DERR_NOTAVAILABLE;
1680 switch (CheckFormat) {
1682 /*****
1683 * supported: RGB(A) formats
1685 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1686 case WINED3DFMT_A8R8G8B8:
1687 case WINED3DFMT_X8R8G8B8:
1688 case WINED3DFMT_R5G6B5:
1689 case WINED3DFMT_X1R5G5B5:
1690 case WINED3DFMT_A1R5G5B5:
1691 case WINED3DFMT_A4R4G4B4:
1692 case WINED3DFMT_R3G3B2:
1693 case WINED3DFMT_A8:
1694 case WINED3DFMT_A8R3G3B2:
1695 case WINED3DFMT_X4R4G4B4:
1696 case WINED3DFMT_A8B8G8R8:
1697 case WINED3DFMT_X8B8G8R8:
1698 case WINED3DFMT_A2R10G10B10:
1699 case WINED3DFMT_A2B10G10R10:
1700 TRACE_(d3d_caps)("[OK]\n");
1701 return WINED3D_OK;
1703 /*****
1704 * supported: Palettized
1706 case WINED3DFMT_P8:
1707 TRACE_(d3d_caps)("[OK]\n");
1708 return WINED3D_OK;
1710 /*****
1711 * Supported: (Alpha)-Luminance
1713 case WINED3DFMT_L8:
1714 case WINED3DFMT_A8L8:
1715 case WINED3DFMT_A4L4:
1716 TRACE_(d3d_caps)("[OK]\n");
1717 return WINED3D_OK;
1719 /*****
1720 * Not supported for now: Bump mapping formats
1721 * Enable some because games often fail when they are not available
1722 * and are still playable even without bump mapping
1724 case WINED3DFMT_V8U8:
1725 case WINED3DFMT_V16U16:
1726 case WINED3DFMT_L6V5U5:
1727 case WINED3DFMT_X8L8V8U8:
1728 case WINED3DFMT_Q8W8V8U8:
1729 case WINED3DFMT_W11V11U10:
1730 case WINED3DFMT_A2W10V10U10:
1731 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1732 return WINED3D_OK;
1734 /*****
1735 * DXTN Formats: Handled above
1736 * WINED3DFMT_DXT1
1737 * WINED3DFMT_DXT2
1738 * WINED3DFMT_DXT3
1739 * WINED3DFMT_DXT4
1740 * WINED3DFMT_DXT5
1743 /*****
1744 * Odd formats - not supported
1746 case WINED3DFMT_VERTEXDATA:
1747 case WINED3DFMT_INDEX16:
1748 case WINED3DFMT_INDEX32:
1749 case WINED3DFMT_Q16W16V16U16:
1750 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1751 return WINED3DERR_NOTAVAILABLE;
1753 /*****
1754 * Float formats: Not supported right now
1756 case WINED3DFMT_G16R16F:
1757 case WINED3DFMT_G32R32F:
1758 case WINED3DFMT_CxV8U8:
1759 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1760 return WINED3DERR_NOTAVAILABLE;
1762 /* Not supported */
1763 case WINED3DFMT_G16R16:
1764 case WINED3DFMT_A16B16G16R16:
1765 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1766 return WINED3DERR_NOTAVAILABLE;
1768 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1769 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1770 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1771 * We can do instancing with all shader versions, but we need vertex shaders.
1773 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1774 * to enable instancing. WineD3D doesn't need that and just ignores it.
1776 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1778 case WINEMAKEFOURCC('I','N','S','T'):
1779 TRACE("ATI Instancing check hack\n");
1780 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1781 TRACE_(d3d_caps)("[OK]\n");
1782 return WINED3D_OK;
1783 } else {
1784 TRACE_(d3d_caps)("[FAILED]\n");
1785 return WINED3DERR_NOTAVAILABLE;
1788 default:
1789 break;
1792 TRACE_(d3d_caps)("[FAILED]\n");
1793 return WINED3DERR_NOTAVAILABLE;
1796 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1797 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1798 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1800 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1801 This,
1802 Adapter,
1803 DeviceType, debug_d3ddevicetype(DeviceType),
1804 SourceFormat, debug_d3dformat(SourceFormat),
1805 TargetFormat, debug_d3dformat(TargetFormat));
1806 return WINED3D_OK;
1809 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1810 subset of a D3DCAPS9 structure. However, it has to come via a void *
1811 as the d3d8 interface cannot import the d3d9 header */
1812 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1814 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1815 int vs_selected_mode;
1816 int ps_selected_mode;
1818 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1820 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1821 return WINED3DERR_INVALIDCALL;
1824 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1826 /* This function should *not* be modifying GL caps
1827 * TODO: move the functionality where it belongs */
1828 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1830 /* ------------------------------------------------
1831 The following fields apply to both d3d8 and d3d9
1832 ------------------------------------------------ */
1833 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1834 *pCaps->AdapterOrdinal = Adapter;
1836 *pCaps->Caps = 0;
1837 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1838 WINED3DCAPS2_FULLSCREENGAMMA |
1839 WINED3DCAPS2_DYNAMICTEXTURES;
1840 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1841 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1843 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1844 WINED3DCURSORCAPS_LOWRES;
1846 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1847 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1848 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1849 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1850 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1851 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1852 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1853 WINED3DDEVCAPS_PUREDEVICE |
1854 WINED3DDEVCAPS_HWRASTERIZATION |
1855 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1856 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1857 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1858 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1859 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1860 WINED3DDEVCAPS_RTPATCHES;
1862 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1863 WINED3DPMISCCAPS_CULLCCW |
1864 WINED3DPMISCCAPS_CULLCW |
1865 WINED3DPMISCCAPS_COLORWRITEENABLE |
1866 WINED3DPMISCCAPS_CLIPTLVERTS |
1867 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1868 WINED3DPMISCCAPS_MASKZ |
1869 WINED3DPMISCCAPS_BLENDOP;
1870 /* TODO:
1871 WINED3DPMISCCAPS_NULLREFERENCE
1872 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1873 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1874 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1875 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1876 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1877 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1879 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1880 #if 0
1881 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1882 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1883 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1884 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1885 #endif
1887 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1888 WINED3DPRASTERCAPS_PAT |
1889 WINED3DPRASTERCAPS_WFOG |
1890 WINED3DPRASTERCAPS_ZFOG |
1891 WINED3DPRASTERCAPS_FOGVERTEX |
1892 WINED3DPRASTERCAPS_FOGTABLE |
1893 WINED3DPRASTERCAPS_FOGRANGE |
1894 WINED3DPRASTERCAPS_STIPPLE |
1895 WINED3DPRASTERCAPS_SUBPIXEL |
1896 WINED3DPRASTERCAPS_ZTEST |
1897 WINED3DPRASTERCAPS_SCISSORTEST |
1898 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1899 WINED3DPRASTERCAPS_DEPTHBIAS;
1901 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1902 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1903 WINED3DPRASTERCAPS_ZBIAS |
1904 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1906 /* FIXME Add:
1907 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1908 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1909 WINED3DPRASTERCAPS_ANTIALIASEDGES
1910 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1911 WINED3DPRASTERCAPS_WBUFFER */
1913 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1914 WINED3DPCMPCAPS_EQUAL |
1915 WINED3DPCMPCAPS_GREATER |
1916 WINED3DPCMPCAPS_GREATEREQUAL |
1917 WINED3DPCMPCAPS_LESS |
1918 WINED3DPCMPCAPS_LESSEQUAL |
1919 WINED3DPCMPCAPS_NEVER |
1920 WINED3DPCMPCAPS_NOTEQUAL;
1922 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1923 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1924 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1925 WINED3DPBLENDCAPS_DESTALPHA |
1926 WINED3DPBLENDCAPS_DESTCOLOR |
1927 WINED3DPBLENDCAPS_INVDESTALPHA |
1928 WINED3DPBLENDCAPS_INVDESTCOLOR |
1929 WINED3DPBLENDCAPS_INVSRCALPHA |
1930 WINED3DPBLENDCAPS_INVSRCCOLOR |
1931 WINED3DPBLENDCAPS_ONE |
1932 WINED3DPBLENDCAPS_SRCALPHA |
1933 WINED3DPBLENDCAPS_SRCALPHASAT |
1934 WINED3DPBLENDCAPS_SRCCOLOR |
1935 WINED3DPBLENDCAPS_ZERO;
1937 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1938 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1939 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1940 WINED3DPBLENDCAPS_DESTALPHA |
1941 WINED3DPBLENDCAPS_DESTCOLOR |
1942 WINED3DPBLENDCAPS_INVDESTALPHA |
1943 WINED3DPBLENDCAPS_INVDESTCOLOR |
1944 WINED3DPBLENDCAPS_INVSRCALPHA |
1945 WINED3DPBLENDCAPS_INVSRCCOLOR |
1946 WINED3DPBLENDCAPS_ONE |
1947 WINED3DPBLENDCAPS_SRCALPHA |
1948 WINED3DPBLENDCAPS_SRCALPHASAT |
1949 WINED3DPBLENDCAPS_SRCCOLOR |
1950 WINED3DPBLENDCAPS_ZERO;
1952 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1953 WINED3DPCMPCAPS_EQUAL |
1954 WINED3DPCMPCAPS_GREATER |
1955 WINED3DPCMPCAPS_GREATEREQUAL |
1956 WINED3DPCMPCAPS_LESS |
1957 WINED3DPCMPCAPS_LESSEQUAL |
1958 WINED3DPCMPCAPS_NEVER |
1959 WINED3DPCMPCAPS_NOTEQUAL;
1961 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1962 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1963 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1964 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1965 WINED3DPSHADECAPS_COLORFLATRGB |
1966 WINED3DPSHADECAPS_FOGFLAT |
1967 WINED3DPSHADECAPS_FOGGOURAUD |
1968 WINED3DPSHADECAPS_SPECULARFLATRGB;
1970 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1971 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1972 WINED3DPTEXTURECAPS_BORDER |
1973 WINED3DPTEXTURECAPS_MIPMAP |
1974 WINED3DPTEXTURECAPS_PROJECTED |
1975 WINED3DPTEXTURECAPS_PERSPECTIVE |
1976 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1978 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1979 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1980 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1981 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1984 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1985 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1986 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1987 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1991 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1992 WINED3DPTFILTERCAPS_MAGFPOINT |
1993 WINED3DPTFILTERCAPS_MINFLINEAR |
1994 WINED3DPTFILTERCAPS_MINFPOINT |
1995 WINED3DPTFILTERCAPS_MIPFLINEAR |
1996 WINED3DPTFILTERCAPS_MIPFPOINT |
1997 WINED3DPTFILTERCAPS_LINEAR |
1998 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1999 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2000 WINED3DPTFILTERCAPS_MIPLINEAR |
2001 WINED3DPTFILTERCAPS_MIPNEAREST |
2002 WINED3DPTFILTERCAPS_NEAREST;
2004 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2005 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2006 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2009 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2010 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2011 WINED3DPTFILTERCAPS_MAGFPOINT |
2012 WINED3DPTFILTERCAPS_MINFLINEAR |
2013 WINED3DPTFILTERCAPS_MINFPOINT |
2014 WINED3DPTFILTERCAPS_MIPFLINEAR |
2015 WINED3DPTFILTERCAPS_MIPFPOINT |
2016 WINED3DPTFILTERCAPS_LINEAR |
2017 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2018 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2019 WINED3DPTFILTERCAPS_MIPLINEAR |
2020 WINED3DPTFILTERCAPS_MIPNEAREST |
2021 WINED3DPTFILTERCAPS_NEAREST;
2023 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2024 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2025 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2027 } else
2028 *pCaps->CubeTextureFilterCaps = 0;
2030 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2031 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2032 WINED3DPTFILTERCAPS_MAGFPOINT |
2033 WINED3DPTFILTERCAPS_MINFLINEAR |
2034 WINED3DPTFILTERCAPS_MINFPOINT |
2035 WINED3DPTFILTERCAPS_MIPFLINEAR |
2036 WINED3DPTFILTERCAPS_MIPFPOINT |
2037 WINED3DPTFILTERCAPS_LINEAR |
2038 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2039 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2040 WINED3DPTFILTERCAPS_MIPLINEAR |
2041 WINED3DPTFILTERCAPS_MIPNEAREST |
2042 WINED3DPTFILTERCAPS_NEAREST;
2043 } else
2044 *pCaps->VolumeTextureFilterCaps = 0;
2046 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2047 WINED3DPTADDRESSCAPS_CLAMP |
2048 WINED3DPTADDRESSCAPS_WRAP;
2050 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2051 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2053 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2054 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2056 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2057 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2060 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2061 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2062 WINED3DPTADDRESSCAPS_CLAMP |
2063 WINED3DPTADDRESSCAPS_WRAP;
2064 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2065 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2067 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2068 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2070 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2071 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2073 } else
2074 *pCaps->VolumeTextureAddressCaps = 0;
2076 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2077 WINED3DLINECAPS_ZTEST;
2078 /* FIXME: Add
2079 WINED3DLINECAPS_BLEND
2080 WINED3DLINECAPS_ALPHACMP
2081 WINED3DLINECAPS_FOG */
2083 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2084 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2086 if(GL_SUPPORT(EXT_TEXTURE3D))
2087 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2088 else
2089 *pCaps->MaxVolumeExtent = 0;
2091 *pCaps->MaxTextureRepeat = 32768;
2092 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2093 *pCaps->MaxVertexW = 1.0;
2095 *pCaps->GuardBandLeft = 0;
2096 *pCaps->GuardBandTop = 0;
2097 *pCaps->GuardBandRight = 0;
2098 *pCaps->GuardBandBottom = 0;
2100 *pCaps->ExtentsAdjust = 0;
2102 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2103 WINED3DSTENCILCAPS_INCRSAT |
2104 WINED3DSTENCILCAPS_INVERT |
2105 WINED3DSTENCILCAPS_KEEP |
2106 WINED3DSTENCILCAPS_REPLACE |
2107 WINED3DSTENCILCAPS_ZERO;
2108 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2109 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2110 WINED3DSTENCILCAPS_INCR;
2112 if ( This->dxVersion > 8 &&
2113 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2114 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2115 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2118 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2120 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2121 WINED3DTEXOPCAPS_ADDSIGNED |
2122 WINED3DTEXOPCAPS_ADDSIGNED2X |
2123 WINED3DTEXOPCAPS_MODULATE |
2124 WINED3DTEXOPCAPS_MODULATE2X |
2125 WINED3DTEXOPCAPS_MODULATE4X |
2126 WINED3DTEXOPCAPS_SELECTARG1 |
2127 WINED3DTEXOPCAPS_SELECTARG2 |
2128 WINED3DTEXOPCAPS_DISABLE;
2130 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2131 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2132 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2133 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2134 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2135 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2136 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2137 WINED3DTEXOPCAPS_LERP |
2138 WINED3DTEXOPCAPS_SUBTRACT;
2140 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2141 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2142 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2143 WINED3DTEXOPCAPS_MULTIPLYADD |
2144 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2145 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2146 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2148 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2149 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2151 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2152 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2153 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2156 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2157 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2158 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2159 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2160 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2161 * and 3D textures. It also allows us to keep the code simpler by having texture
2162 * shaders constantly enabled.
2164 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2165 /* TODO: Luminance bump map? */
2167 #if 0
2168 /* FIXME: Add
2169 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2170 WINED3DTEXOPCAPS_PREMODULATE */
2171 #endif
2173 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2174 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2175 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2176 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2178 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2179 *pCaps->MaxVertexBlendMatrixIndex = 0;
2181 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2182 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2185 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2186 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2187 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2188 WINED3DVTXPCAPS_LOCALVIEWER |
2189 WINED3DVTXPCAPS_VERTEXFOG |
2190 WINED3DVTXPCAPS_TEXGEN;
2191 /* FIXME: Add
2192 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2194 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2195 *pCaps->MaxVertexIndex = 0xFFFFF;
2196 *pCaps->MaxStreams = MAX_STREAMS;
2197 *pCaps->MaxStreamStride = 1024;
2199 if (vs_selected_mode == SHADER_GLSL) {
2200 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2201 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2202 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2203 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2204 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2205 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2206 else
2207 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2208 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2209 } else if (vs_selected_mode == SHADER_ARB) {
2210 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2211 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2212 } else {
2213 *pCaps->VertexShaderVersion = 0;
2214 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2217 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2219 if (ps_selected_mode == SHADER_GLSL) {
2220 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2221 in case of GeforceFX cards. */
2222 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2223 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2224 else
2225 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2226 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2227 *pCaps->PixelShader1xMaxValue = 1.0;
2228 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2229 } else if (ps_selected_mode == SHADER_ARB) {
2230 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2231 *pCaps->PixelShader1xMaxValue = 1.0;
2232 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2233 } else {
2234 *pCaps->PixelShaderVersion = 0;
2235 *pCaps->PixelShader1xMaxValue = 0.0;
2236 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2239 /* ------------------------------------------------
2240 The following fields apply to d3d9 only
2241 ------------------------------------------------ */
2242 if (This->dxVersion > 8) {
2243 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2244 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2245 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2246 *pCaps->MaxNpatchTessellationLevel = 0;
2247 *pCaps->MasterAdapterOrdinal = 0;
2248 *pCaps->AdapterOrdinalInGroup = 0;
2249 *pCaps->NumberOfAdaptersInGroup = 1;
2251 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2252 /* OpenGL supports all the formats below, perhaps not always
2253 * without conversion, but it supports them.
2254 * Further GLSL doesn't seem to have an official unsigned type so
2255 * don't advertise it yet as I'm not sure how we handle it.
2256 * We might need to add some clamping in the shader engine to
2257 * support it.
2258 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2259 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2260 WINED3DDTCAPS_UBYTE4N |
2261 WINED3DDTCAPS_SHORT2N |
2262 WINED3DDTCAPS_SHORT4N;
2263 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2264 *pCaps->DeclTypes |=
2265 WINED3DDTCAPS_FLOAT16_2 |
2266 WINED3DDTCAPS_FLOAT16_4;
2268 } else
2269 *pCaps->DeclTypes = 0;
2271 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2274 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2275 WINED3DPTFILTERCAPS_MAGFPOINT |
2276 WINED3DPTFILTERCAPS_MINFLINEAR |
2277 WINED3DPTFILTERCAPS_MAGFLINEAR;
2278 *pCaps->VertexTextureFilterCaps = 0;
2280 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2281 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2282 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2283 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2284 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2285 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2286 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2288 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2289 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2290 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2291 *pCaps->VS20Caps.Caps = 0;
2292 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2293 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2294 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2296 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2297 *pCaps->MaxVertexShader30InstructionSlots = 0;
2298 } else { /* VS 1.x */
2299 *pCaps->VS20Caps.Caps = 0;
2300 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2301 *pCaps->VS20Caps.NumTemps = 0;
2302 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2304 *pCaps->MaxVShaderInstructionsExecuted = 0;
2305 *pCaps->MaxVertexShader30InstructionSlots = 0;
2308 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2309 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2310 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2312 /* 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 */
2313 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2314 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2315 WINED3DPS20CAPS_PREDICATION |
2316 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2317 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2318 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2319 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2320 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2321 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2323 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2324 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2325 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2326 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2327 *pCaps->PS20Caps.Caps = 0;
2328 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2329 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2330 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2331 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2333 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2334 *pCaps->MaxPixelShader30InstructionSlots = 0;
2335 } else { /* PS 1.x */
2336 *pCaps->PS20Caps.Caps = 0;
2337 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2338 *pCaps->PS20Caps.NumTemps = 0;
2339 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2340 *pCaps->PS20Caps.NumInstructionSlots = 0;
2342 *pCaps->MaxPShaderInstructionsExecuted = 0;
2343 *pCaps->MaxPixelShader30InstructionSlots = 0;
2347 return WINED3D_OK;
2350 static unsigned int glsl_program_key_hash(void *key) {
2351 glsl_program_key_t *k = (glsl_program_key_t *)key;
2353 unsigned int hash = k->vshader | k->pshader << 16;
2354 hash += ~(hash << 15);
2355 hash ^= (hash >> 10);
2356 hash += (hash << 3);
2357 hash ^= (hash >> 6);
2358 hash += ~(hash << 11);
2359 hash ^= (hash >> 16);
2361 return hash;
2364 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2365 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2366 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2368 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2371 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2372 and fields being inserted in the middle, a new structure is used in place */
2373 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2374 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2375 IUnknown *parent) {
2377 IWineD3DDeviceImpl *object = NULL;
2378 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2379 HDC hDC;
2380 int i;
2382 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2383 * number and create a device without a 3D adapter for 2D only operation.
2385 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2386 return WINED3DERR_INVALIDCALL;
2389 /* Create a WineD3DDevice object */
2390 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2391 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2392 TRACE("Created WineD3DDevice object @ %p\n", object);
2393 if (NULL == object) {
2394 return WINED3DERR_OUTOFVIDEOMEMORY;
2397 /* Set up initial COM information */
2398 object->lpVtbl = &IWineD3DDevice_Vtbl;
2399 object->ref = 1;
2400 object->wineD3D = iface;
2401 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2402 IWineD3D_AddRef(object->wineD3D);
2403 object->parent = parent;
2405 if(This->dxVersion == 7) {
2406 object->surface_alignment = 8;
2407 } else {
2408 object->surface_alignment = 4;
2411 /* Set the state up as invalid until the device is fully created */
2412 object->state = WINED3DERR_DRIVERINTERNALERROR;
2414 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2415 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2417 /* Save the creation parameters */
2418 object->createParms.AdapterOrdinal = Adapter;
2419 object->createParms.DeviceType = DeviceType;
2420 object->createParms.hFocusWindow = hFocusWindow;
2421 object->createParms.BehaviorFlags = BehaviourFlags;
2423 /* Initialize other useful values */
2424 object->adapterNo = Adapter;
2425 object->devType = DeviceType;
2427 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2428 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2429 object->shader_backend = &glsl_shader_backend;
2430 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2431 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2432 object->shader_backend = &arb_program_shader_backend;
2433 } else {
2434 object->shader_backend = &none_shader_backend;
2437 /* set the state of the device to valid */
2438 object->state = WINED3D_OK;
2440 /* Get the initial screen setup for ddraw */
2441 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2442 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2443 hDC = GetDC(0);
2444 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2445 ReleaseDC(0, hDC);
2447 for(i = 0; i < PATCHMAP_SIZE; i++) {
2448 list_init(&object->patches[i]);
2450 return WINED3D_OK;
2452 #undef GLINFO_LOCATION
2454 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2455 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2456 IUnknown_AddRef(This->parent);
2457 *pParent = This->parent;
2458 return WINED3D_OK;
2461 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2462 IUnknown* surfaceParent;
2463 TRACE("(%p) call back\n", pSurface);
2465 /* Now, release the parent, which will take care of cleaning up the surface for us */
2466 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2467 IUnknown_Release(surfaceParent);
2468 return IUnknown_Release(surfaceParent);
2471 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2472 IUnknown* volumeParent;
2473 TRACE("(%p) call back\n", pVolume);
2475 /* Now, release the parent, which will take care of cleaning up the volume for us */
2476 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2477 IUnknown_Release(volumeParent);
2478 return IUnknown_Release(volumeParent);
2481 #define PUSH1(att) attribs[nAttribs++] = (att);
2482 #define GLINFO_LOCATION (Adapters[0].gl_info)
2483 BOOL InitAdapters(void) {
2484 BOOL ret;
2485 int ps_selected_mode, vs_selected_mode;
2487 /* No need to hold any lock. The calling library makes sure only one thread calls
2488 * wined3d simultaneously
2490 if(numAdapters > 0) return TRUE;
2492 TRACE("Initializing adapters\n");
2493 /* For now only one default adapter */
2495 int attribute;
2496 DISPLAY_DEVICEW DisplayDevice;
2498 TRACE("Initializing default adapter\n");
2499 Adapters[0].monitorPoint.x = -1;
2500 Adapters[0].monitorPoint.y = -1;
2502 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2503 if(!ret) {
2504 ERR("Failed to initialize gl caps for default adapter\n");
2505 HeapFree(GetProcessHeap(), 0, Adapters);
2506 return FALSE;
2508 ret = initPixelFormats(&Adapters[0].gl_info);
2509 if(!ret) {
2510 ERR("Failed to init gl formats\n");
2511 HeapFree(GetProcessHeap(), 0, Adapters);
2512 return FALSE;
2515 Adapters[0].driver = "Display";
2516 Adapters[0].description = "Direct3D HAL";
2518 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2519 DisplayDevice.cb = sizeof(DisplayDevice);
2520 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2521 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2522 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2524 if (WineD3D_CreateFakeGLContext()) {
2525 int iPixelFormat;
2526 int attribs[8];
2527 int values[8];
2528 int nAttribs = 0;
2529 int res;
2530 WineD3D_PixelFormat *cfgs;
2532 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2533 GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2535 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2536 cfgs = Adapters[0].cfgs;
2537 PUSH1(WGL_RED_BITS_ARB)
2538 PUSH1(WGL_GREEN_BITS_ARB)
2539 PUSH1(WGL_BLUE_BITS_ARB)
2540 PUSH1(WGL_ALPHA_BITS_ARB)
2541 PUSH1(WGL_DEPTH_BITS_ARB)
2542 PUSH1(WGL_STENCIL_BITS_ARB)
2544 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2545 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, iPixelFormat, 0, nAttribs, attribs, values));
2547 if(!res)
2548 continue;
2550 /* Cache the pixel format */
2551 cfgs->iPixelFormat = iPixelFormat;
2552 cfgs->redSize = values[0];
2553 cfgs->greenSize = values[1];
2554 cfgs->blueSize = values[2];
2555 cfgs->alphaSize = values[3];
2556 cfgs->depthSize = values[4];
2557 cfgs->stencilSize = values[5];
2559 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);
2560 cfgs++;
2562 WineD3D_ReleaseFakeGLContext();
2565 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2566 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2569 numAdapters = 1;
2570 TRACE("%d adapters successfully initialized\n", numAdapters);
2572 return TRUE;
2574 #undef PUSH1
2575 #undef GLINFO_LOCATION
2577 /**********************************************************
2578 * IWineD3D VTbl follows
2579 **********************************************************/
2581 const IWineD3DVtbl IWineD3D_Vtbl =
2583 /* IUnknown */
2584 IWineD3DImpl_QueryInterface,
2585 IWineD3DImpl_AddRef,
2586 IWineD3DImpl_Release,
2587 /* IWineD3D */
2588 IWineD3DImpl_GetParent,
2589 IWineD3DImpl_GetAdapterCount,
2590 IWineD3DImpl_RegisterSoftwareDevice,
2591 IWineD3DImpl_GetAdapterMonitor,
2592 IWineD3DImpl_GetAdapterModeCount,
2593 IWineD3DImpl_EnumAdapterModes,
2594 IWineD3DImpl_GetAdapterDisplayMode,
2595 IWineD3DImpl_GetAdapterIdentifier,
2596 IWineD3DImpl_CheckDeviceMultiSampleType,
2597 IWineD3DImpl_CheckDepthStencilMatch,
2598 IWineD3DImpl_CheckDeviceType,
2599 IWineD3DImpl_CheckDeviceFormat,
2600 IWineD3DImpl_CheckDeviceFormatConversion,
2601 IWineD3DImpl_GetDeviceCaps,
2602 IWineD3DImpl_CreateDevice