push b72af2511d67bded8ece08d825ff0eb4a60c20a6
[wine/hacks.git] / dlls / wined3d / directx.c
blobe77a237f8b15347a99d926fb1a0524d2b480ef87
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},
121 /* SGI */
122 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP},
125 /**********************************************************
126 * Utility functions follow
127 **********************************************************/
129 /* Adapters */
130 static int numAdapters = 0;
131 static struct WineD3DAdapter Adapters[1];
133 /* lookup tables */
134 int minLookup[MAX_LOOKUPS];
135 int maxLookup[MAX_LOOKUPS];
136 DWORD *stateLookup[MAX_LOOKUPS];
138 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
142 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
143 * ie there is no GL Context - Get a default rendering context to enable the
144 * function query some info from GL
147 static int wined3d_fake_gl_context_ref = 0;
148 static BOOL wined3d_fake_gl_context_foreign;
149 static BOOL wined3d_fake_gl_context_available = FALSE;
150 static HDC wined3d_fake_gl_context_hdc = NULL;
151 static HWND wined3d_fake_gl_context_hwnd = NULL;
153 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
154 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
156 0, 0, &wined3d_fake_gl_context_cs,
157 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
158 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
159 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
161 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
163 static void WineD3D_ReleaseFakeGLContext(void) {
164 HGLRC glCtx;
166 EnterCriticalSection(&wined3d_fake_gl_context_cs);
168 if(!wined3d_fake_gl_context_available) {
169 TRACE_(d3d_caps)("context not available\n");
170 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
171 return;
174 glCtx = pwglGetCurrentContext();
176 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
177 if (0 == (--wined3d_fake_gl_context_ref) ) {
178 if(!wined3d_fake_gl_context_foreign && glCtx) {
179 TRACE_(d3d_caps)("destroying fake GL context\n");
180 pwglMakeCurrent(NULL, NULL);
181 pwglDeleteContext(glCtx);
183 if(wined3d_fake_gl_context_hdc)
184 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
185 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
186 if(wined3d_fake_gl_context_hwnd)
187 DestroyWindow(wined3d_fake_gl_context_hwnd);
188 wined3d_fake_gl_context_hwnd = NULL;
189 wined3d_fake_gl_context_available = FALSE;
191 assert(wined3d_fake_gl_context_ref >= 0);
193 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
194 LEAVE_GL();
197 static BOOL WineD3D_CreateFakeGLContext(void) {
198 HGLRC glCtx = NULL;
200 ENTER_GL();
201 EnterCriticalSection(&wined3d_fake_gl_context_cs);
203 TRACE("getting context...\n");
204 if(wined3d_fake_gl_context_ref > 0) goto ret;
205 assert(0 == wined3d_fake_gl_context_ref);
207 wined3d_fake_gl_context_foreign = TRUE;
209 glCtx = pwglGetCurrentContext();
210 if (!glCtx) {
211 PIXELFORMATDESCRIPTOR pfd;
212 int iPixelFormat;
214 wined3d_fake_gl_context_foreign = FALSE;
216 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
217 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
218 if(!wined3d_fake_gl_context_hwnd) {
219 ERR("HWND creation failed!\n");
220 goto fail;
222 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
223 if(!wined3d_fake_gl_context_hdc) {
224 ERR("GetDC failed!\n");
225 goto fail;
228 /* PixelFormat selection */
229 ZeroMemory(&pfd, sizeof(pfd));
230 pfd.nSize = sizeof(pfd);
231 pfd.nVersion = 1;
232 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
233 pfd.iPixelType = PFD_TYPE_RGBA;
234 pfd.cColorBits = 32;
235 pfd.iLayerType = PFD_MAIN_PLANE;
237 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
238 if(!iPixelFormat) {
239 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
240 ERR("Can't find a suitable iPixelFormat\n");
241 goto fail;
243 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
244 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
246 /* Create a GL context */
247 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
248 if (!glCtx) {
249 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
250 goto fail;
253 /* Make it the current GL context */
254 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
255 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
256 goto fail;
260 ret:
261 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
262 wined3d_fake_gl_context_ref++;
263 wined3d_fake_gl_context_available = TRUE;
264 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
265 return TRUE;
266 fail:
267 if(wined3d_fake_gl_context_hdc)
268 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
269 wined3d_fake_gl_context_hdc = NULL;
270 if(wined3d_fake_gl_context_hwnd)
271 DestroyWindow(wined3d_fake_gl_context_hwnd);
272 wined3d_fake_gl_context_hwnd = NULL;
273 if(glCtx) pwglDeleteContext(glCtx);
274 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
275 LEAVE_GL();
276 return FALSE;
280 /**********************************************************
281 * IUnknown parts follows
282 **********************************************************/
284 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
286 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
288 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
289 if (IsEqualGUID(riid, &IID_IUnknown)
290 || IsEqualGUID(riid, &IID_IWineD3DBase)
291 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
292 IUnknown_AddRef(iface);
293 *ppobj = This;
294 return S_OK;
296 *ppobj = NULL;
297 return E_NOINTERFACE;
300 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
301 IWineD3DImpl *This = (IWineD3DImpl *)iface;
302 ULONG refCount = InterlockedIncrement(&This->ref);
304 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
305 return refCount;
308 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
309 IWineD3DImpl *This = (IWineD3DImpl *)iface;
310 ULONG ref;
311 TRACE("(%p) : Releasing from %d\n", This, This->ref);
312 ref = InterlockedDecrement(&This->ref);
313 if (ref == 0) {
314 HeapFree(GetProcessHeap(), 0, This);
317 return ref;
320 /* Set the shader type for this device, depending on the given capabilities,
321 * the device type, and the user preferences in wined3d_settings */
323 static void select_shader_mode(
324 WineD3D_GL_Info *gl_info,
325 WINED3DDEVTYPE DeviceType,
326 int* ps_selected,
327 int* vs_selected) {
329 if (wined3d_settings.vs_mode == VS_NONE) {
330 *vs_selected = SHADER_NONE;
331 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
332 *vs_selected = SHADER_GLSL;
333 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
334 *vs_selected = SHADER_ARB;
335 } else {
336 *vs_selected = SHADER_NONE;
339 if (wined3d_settings.ps_mode == PS_NONE) {
340 *ps_selected = SHADER_NONE;
341 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
342 *ps_selected = SHADER_GLSL;
343 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
344 *ps_selected = SHADER_ARB;
345 } else {
346 *ps_selected = SHADER_NONE;
350 /** Select the number of report maximum shader constants based on the selected shader modes */
351 static void select_shader_max_constants(
352 int ps_selected_mode,
353 int vs_selected_mode,
354 WineD3D_GL_Info *gl_info) {
356 switch (vs_selected_mode) {
357 case SHADER_GLSL:
358 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
359 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
360 break;
361 case SHADER_ARB:
362 /* We have to subtract any other PARAMs that we might use in our shader programs.
363 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
364 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
365 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
366 break;
367 default:
368 gl_info->max_vshader_constantsF = 0;
369 break;
372 switch (ps_selected_mode) {
373 case SHADER_GLSL:
374 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
375 * In theory the texbem instruction may need one more shader constant too. But lets assume
376 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
377 * and lets not take away a uniform needlessly from all other shaders.
379 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
380 break;
381 case SHADER_ARB:
382 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
383 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
385 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
386 break;
387 default:
388 gl_info->max_pshader_constantsF = 0;
389 break;
393 /**********************************************************
394 * IWineD3D parts follows
395 **********************************************************/
397 #define GLINFO_LOCATION (*gl_info)
398 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
399 const char *GL_Extensions = NULL;
400 const char *WGL_Extensions = NULL;
401 const char *gl_string = NULL;
402 const char *gl_string_cursor = NULL;
403 GLint gl_max;
404 GLfloat gl_floatv[2];
405 int major = 1, minor = 0;
406 BOOL return_value = TRUE;
407 int i;
408 HDC hdc;
410 TRACE_(d3d_caps)("(%p)\n", gl_info);
412 gl_string = (const char *) glGetString(GL_RENDERER);
413 if (NULL == gl_string)
414 gl_string = "None";
415 strcpy(gl_info->gl_renderer, gl_string);
417 gl_string = (const char *) glGetString(GL_VENDOR);
418 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
419 if (gl_string != NULL) {
420 /* Fill in the GL vendor */
421 if (strstr(gl_string, "NVIDIA")) {
422 gl_info->gl_vendor = VENDOR_NVIDIA;
423 } else if (strstr(gl_string, "ATI")) {
424 gl_info->gl_vendor = VENDOR_ATI;
425 } else if (strstr(gl_string, "Intel(R)") ||
426 strstr(gl_info->gl_renderer, "Intel(R)")) {
427 gl_info->gl_vendor = VENDOR_INTEL;
428 } else if (strstr(gl_string, "Mesa")) {
429 gl_info->gl_vendor = VENDOR_MESA;
430 } else {
431 gl_info->gl_vendor = VENDOR_WINE;
433 } else {
434 gl_info->gl_vendor = VENDOR_WINE;
438 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
440 /* Parse the GL_VERSION field into major and minor information */
441 gl_string = (const char *) glGetString(GL_VERSION);
442 if (gl_string != NULL) {
444 switch (gl_info->gl_vendor) {
445 case VENDOR_NVIDIA:
446 gl_string_cursor = strstr(gl_string, "NVIDIA");
447 if (!gl_string_cursor) {
448 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
449 break;
452 gl_string_cursor = strstr(gl_string_cursor, " ");
453 if (!gl_string_cursor) {
454 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
455 break;
458 while (*gl_string_cursor == ' ') {
459 ++gl_string_cursor;
462 if (!*gl_string_cursor) {
463 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
464 break;
467 major = atoi(gl_string_cursor);
468 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
469 ++gl_string_cursor;
472 if (*gl_string_cursor++ != '.') {
473 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
474 break;
477 minor = atoi(gl_string_cursor);
478 minor = major*100+minor;
479 major = 10;
481 break;
483 case VENDOR_ATI:
484 major = minor = 0;
485 gl_string_cursor = strchr(gl_string, '-');
486 if (gl_string_cursor) {
487 int error = 0;
488 gl_string_cursor++;
490 /* Check if version number is of the form x.y.z */
491 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
492 error = 1;
493 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
494 error = 1;
495 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
496 error = 1;
497 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
498 error = 1;
500 /* Mark version number as malformed */
501 if (error)
502 gl_string_cursor = 0;
505 if (!gl_string_cursor)
506 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
507 else {
508 major = *gl_string_cursor - '0';
509 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
511 break;
513 case VENDOR_INTEL:
514 case VENDOR_MESA:
515 gl_string_cursor = strstr(gl_string, "Mesa");
516 gl_string_cursor = strstr(gl_string_cursor, " ");
517 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
518 if (*gl_string_cursor) {
519 char tmp[16];
520 int cursor = 0;
522 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
523 tmp[cursor++] = *gl_string_cursor;
524 ++gl_string_cursor;
526 tmp[cursor] = 0;
527 major = atoi(tmp);
529 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
530 ++gl_string_cursor;
532 cursor = 0;
533 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
534 tmp[cursor++] = *gl_string_cursor;
535 ++gl_string_cursor;
537 tmp[cursor] = 0;
538 minor = atoi(tmp);
540 break;
542 default:
543 major = 0;
544 minor = 9;
546 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
547 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
550 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
553 * Initialize openGL extension related variables
554 * with Default values
556 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
557 gl_info->max_buffers = 1;
558 gl_info->max_textures = 1;
559 gl_info->max_texture_stages = 1;
560 gl_info->max_fragment_samplers = 1;
561 gl_info->max_vertex_samplers = 0;
562 gl_info->max_combined_samplers = 0;
563 gl_info->max_sampler_stages = 1;
564 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
565 gl_info->ps_arb_max_temps = 0;
566 gl_info->ps_arb_max_instructions = 0;
567 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
568 gl_info->vs_arb_max_temps = 0;
569 gl_info->vs_arb_max_instructions = 0;
570 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
571 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
572 gl_info->vs_glsl_constantsF = 0;
573 gl_info->ps_glsl_constantsF = 0;
574 gl_info->vs_arb_constantsF = 0;
575 gl_info->ps_arb_constantsF = 0;
577 /* Now work out what GL support this card really has */
578 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
579 GL_EXT_FUNCS_GEN;
580 WGL_EXT_FUNCS_GEN;
581 #undef USE_GL_FUNC
583 /* Retrieve opengl defaults */
584 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
585 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
586 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
588 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
589 gl_info->max_lights = gl_max;
590 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
592 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
593 gl_info->max_texture_size = gl_max;
594 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
596 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
597 gl_info->max_pointsize = gl_floatv[1];
598 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
600 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
601 gl_info->max_aux_buffers = gl_max;
602 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
604 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
605 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
606 TRACE_(d3d_caps)("GL_Extensions reported:\n");
608 if (NULL == GL_Extensions) {
609 ERR(" GL_Extensions returns NULL\n");
610 } else {
611 while (*GL_Extensions != 0x00) {
612 const char *Start;
613 char ThisExtn[256];
614 size_t len;
616 while (isspace(*GL_Extensions)) GL_Extensions++;
617 Start = GL_Extensions;
618 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
619 GL_Extensions++;
622 len = GL_Extensions - Start;
623 if (len == 0 || len >= sizeof(ThisExtn))
624 continue;
626 memcpy(ThisExtn, Start, len);
627 ThisExtn[len] = '\0';
628 TRACE_(d3d_caps)("- %s\n", ThisExtn);
630 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
631 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
632 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
633 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
634 break;
639 if (gl_info->supported[APPLE_FENCE]) {
640 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
641 * The apple extension interacts with some other apple exts. Disable the NV
642 * extension if the apple one is support to prevent confusion in other parts
643 * of the code
645 gl_info->supported[NV_FENCE] = FALSE;
647 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
648 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
649 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
651 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
652 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
653 * Won't occur in any real world situation though
655 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
657 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
658 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
659 gl_info->max_buffers = gl_max;
660 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
662 if (gl_info->supported[ARB_MULTITEXTURE]) {
663 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
664 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
665 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
667 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
668 GLint tmp;
669 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
670 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
671 } else {
672 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
674 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
676 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
677 GLint tmp;
678 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
679 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
680 } else {
681 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
683 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
685 if (gl_info->supported[ARB_VERTEX_SHADER]) {
686 GLint tmp;
687 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
688 gl_info->max_vertex_samplers = tmp;
689 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
690 gl_info->max_combined_samplers = tmp;
691 } else {
692 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
694 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
695 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
697 if (gl_info->supported[ARB_VERTEX_BLEND]) {
698 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
699 gl_info->max_blends = gl_max;
700 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
702 if (gl_info->supported[EXT_TEXTURE3D]) {
703 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
704 gl_info->max_texture3d_size = gl_max;
705 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
707 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
708 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
709 gl_info->max_anisotropy = gl_max;
710 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
712 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
713 gl_info->ps_arb_version = PS_VERSION_11;
714 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
715 gl_info->ps_arb_constantsF = gl_max;
716 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
717 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
718 gl_info->ps_arb_max_temps = gl_max;
719 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info->ps_arb_max_temps);
720 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
721 gl_info->ps_arb_max_instructions = gl_max;
722 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info->ps_arb_max_instructions);
724 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
725 gl_info->vs_arb_version = VS_VERSION_11;
726 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
727 gl_info->vs_arb_constantsF = gl_max;
728 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
729 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
730 gl_info->vs_arb_max_temps = gl_max;
731 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info->vs_arb_max_temps);
732 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
733 gl_info->vs_arb_max_instructions = gl_max;
734 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info->vs_arb_max_instructions);
736 if (gl_info->supported[ARB_VERTEX_SHADER]) {
737 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
738 gl_info->vs_glsl_constantsF = gl_max / 4;
739 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
741 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
742 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
743 gl_info->ps_glsl_constantsF = gl_max / 4;
744 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
746 if (gl_info->supported[EXT_VERTEX_SHADER]) {
747 gl_info->vs_ati_version = VS_VERSION_11;
749 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
750 gl_info->vs_nv_version = VS_VERSION_30;
751 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
752 gl_info->vs_nv_version = VS_VERSION_20;
753 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
754 gl_info->vs_nv_version = VS_VERSION_11;
755 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
756 gl_info->vs_nv_version = VS_VERSION_10;
758 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
759 gl_info->ps_nv_version = PS_VERSION_30;
760 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
761 gl_info->ps_nv_version = PS_VERSION_20;
765 checkGLcall("extension detection\n");
767 /* In some cases the number of texture stages can be larger than the number
768 * of samplers. The GF4 for example can use only 2 samplers (no fragment
769 * shaders), but 8 texture stages (register combiners). */
770 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
772 /* We can only use ORM_FBO when the hardware supports it. */
773 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
774 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
775 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
778 /* MRTs are currently only supported when FBOs are used. */
779 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
780 gl_info->max_buffers = 1;
783 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
784 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
785 * in case of the latest videocards in the number of pixel/vertex pipelines.
787 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
788 * rendering. Various games use this information to get a rough estimation of the features of the card
789 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
790 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
791 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
792 * not the PCI id.
794 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
795 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
796 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
797 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
798 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
799 * is used for rendering which is not always the case). This would work but it is not very portable. Second
800 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
801 * is limited.
803 * As said most games only use the PCI id to get an indication of the capabilities of the card.
804 * It doesn't really matter if the given id is the correct one if we return the id of a card with
805 * similar 3d features.
807 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
808 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
809 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
810 * won't pass we return a default card. This way is better than maintaining a full card database as even
811 * without a full database we can return a card with similar features. Second the size of the database
812 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
813 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
814 * to distinguishes between different models from that family.
816 switch (gl_info->gl_vendor) {
817 case VENDOR_NVIDIA:
818 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
819 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
821 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
822 if (strstr(gl_info->gl_renderer, "8800"))
823 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
824 else if(strstr(gl_info->gl_renderer, "8600") ||
825 strstr(gl_info->gl_renderer, "8700"))
826 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
827 else if(strstr(gl_info->gl_renderer, "8300") ||
828 strstr(gl_info->gl_renderer, "8400") ||
829 strstr(gl_info->gl_renderer, "8500"))
830 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
831 else if(strstr(gl_info->gl_renderer, "7800") ||
832 strstr(gl_info->gl_renderer, "7900") ||
833 strstr(gl_info->gl_renderer, "7950") ||
834 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
835 strstr(gl_info->gl_renderer, "Quadro FX 5"))
836 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
837 else if(strstr(gl_info->gl_renderer, "6800") ||
838 strstr(gl_info->gl_renderer, "7600"))
839 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
840 else if(strstr(gl_info->gl_renderer, "6600") ||
841 strstr(gl_info->gl_renderer, "6610") ||
842 strstr(gl_info->gl_renderer, "6700"))
843 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
844 else
845 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
846 } else if(WINE_D3D9_CAPABLE(gl_info)) {
847 if (strstr(gl_info->gl_renderer, "5800") ||
848 strstr(gl_info->gl_renderer, "5900") ||
849 strstr(gl_info->gl_renderer, "5950") ||
850 strstr(gl_info->gl_renderer, "Quadro FX"))
851 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
852 else if(strstr(gl_info->gl_renderer, "5600") ||
853 strstr(gl_info->gl_renderer, "5650") ||
854 strstr(gl_info->gl_renderer, "5700") ||
855 strstr(gl_info->gl_renderer, "5750"))
856 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
857 else
858 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
859 } else if(WINE_D3D8_CAPABLE(gl_info)) {
860 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
861 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
862 else
863 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
864 } else if(WINE_D3D7_CAPABLE(gl_info)) {
865 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
866 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
867 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
868 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
869 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
870 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
871 else
872 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
873 } else {
874 if (strstr(gl_info->gl_renderer, "TNT2"))
875 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
876 else
877 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
879 break;
880 case VENDOR_ATI:
881 if(WINE_D3D9_CAPABLE(gl_info)) {
882 /* Radeon R5xx */
883 if (strstr(gl_info->gl_renderer, "X1600") ||
884 strstr(gl_info->gl_renderer, "X1800") ||
885 strstr(gl_info->gl_renderer, "X1900") ||
886 strstr(gl_info->gl_renderer, "X1950"))
887 gl_info->gl_card = CARD_ATI_RADEON_X1600;
888 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
889 else if(strstr(gl_info->gl_renderer, "X700") ||
890 strstr(gl_info->gl_renderer, "X800") ||
891 strstr(gl_info->gl_renderer, "X850") ||
892 strstr(gl_info->gl_renderer, "X1300") ||
893 strstr(gl_info->gl_renderer, "X1400"))
894 gl_info->gl_card = CARD_ATI_RADEON_X700;
895 /* Radeon R3xx */
896 else
897 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
898 } else if(WINE_D3D8_CAPABLE(gl_info)) {
899 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
900 } else if(WINE_D3D7_CAPABLE(gl_info)) {
901 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
902 } else
903 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
904 break;
905 case VENDOR_INTEL:
906 if (strstr(gl_info->gl_renderer, "915GM")) {
907 gl_info->gl_card = CARD_INTEL_I915GM;
908 } else if (strstr(gl_info->gl_renderer, "915G")) {
909 gl_info->gl_card = CARD_INTEL_I915G;
910 } else if (strstr(gl_info->gl_renderer, "865G")) {
911 gl_info->gl_card = CARD_INTEL_I865G;
912 } else if (strstr(gl_info->gl_renderer, "855G")) {
913 gl_info->gl_card = CARD_INTEL_I855G;
914 } else if (strstr(gl_info->gl_renderer, "830G")) {
915 gl_info->gl_card = CARD_INTEL_I830G;
916 } else {
917 gl_info->gl_card = CARD_INTEL_I915G;
919 break;
920 case VENDOR_MESA:
921 case VENDOR_WINE:
922 default:
923 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
924 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
925 * them a good generic choice.
927 gl_info->gl_vendor = VENDOR_NVIDIA;
928 if(WINE_D3D9_CAPABLE(gl_info))
929 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
930 else if(WINE_D3D8_CAPABLE(gl_info))
931 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
932 else if(WINE_D3D7_CAPABLE(gl_info))
933 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
934 else if(WINE_D3D6_CAPABLE(gl_info))
935 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
936 else
937 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
939 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
941 /* Load all the lookup tables
942 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
943 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
944 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
946 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
947 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
950 for (i = 0; i < MAX_LOOKUPS; i++) {
951 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
954 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
955 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
956 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
957 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
958 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
959 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
960 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
961 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
962 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
963 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
965 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
966 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
967 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
968 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
969 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
972 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
973 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
974 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
975 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
976 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
977 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
978 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
979 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
980 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
981 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
982 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
983 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
984 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
986 /* TODO: config lookups */
988 /* Make sure there's an active HDC else the WGL extensions will fail */
989 hdc = pwglGetCurrentDC();
990 if (hdc) {
991 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
992 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
994 if (NULL == WGL_Extensions) {
995 ERR(" WGL_Extensions returns NULL\n");
996 } else {
997 while (*WGL_Extensions != 0x00) {
998 const char *Start;
999 char ThisExtn[256];
1000 size_t len;
1002 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1003 Start = WGL_Extensions;
1004 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1005 WGL_Extensions++;
1008 len = WGL_Extensions - Start;
1009 if (len == 0 || len >= sizeof(ThisExtn))
1010 continue;
1012 memcpy(ThisExtn, Start, len);
1013 ThisExtn[len] = '\0';
1014 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1016 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1017 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1018 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1024 return return_value;
1026 #undef GLINFO_LOCATION
1028 /**********************************************************
1029 * IWineD3D implementation follows
1030 **********************************************************/
1032 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1033 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1035 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1036 return numAdapters;
1039 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1040 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1041 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1042 return WINED3D_OK;
1045 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1046 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1048 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1049 return NULL;
1052 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1053 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1056 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1057 of the same bpp but different resolutions */
1059 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1060 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1061 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1062 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1064 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1065 return 0;
1068 /* TODO: Store modes per adapter and read it from the adapter structure */
1069 if (Adapter == 0) { /* Display */
1070 int i = 0;
1071 int j = 0;
1073 if (!DEBUG_SINGLE_MODE) {
1074 DEVMODEW DevModeW;
1076 ZeroMemory(&DevModeW, sizeof(DevModeW));
1077 DevModeW.dmSize = sizeof(DevModeW);
1078 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1079 j++;
1080 switch (Format)
1082 case WINED3DFMT_UNKNOWN:
1083 /* This is for D3D8, do not enumerate P8 here */
1084 if (DevModeW.dmBitsPerPel == 32 ||
1085 DevModeW.dmBitsPerPel == 16) i++;
1086 break;
1087 case WINED3DFMT_X8R8G8B8:
1088 if (DevModeW.dmBitsPerPel == 32) i++;
1089 break;
1090 case WINED3DFMT_R5G6B5:
1091 if (DevModeW.dmBitsPerPel == 16) i++;
1092 break;
1093 case WINED3DFMT_P8:
1094 if (DevModeW.dmBitsPerPel == 8) i++;
1095 break;
1096 default:
1097 /* Skip other modes as they do not match the requested format */
1098 break;
1101 } else {
1102 i = 1;
1103 j = 1;
1106 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1107 return i;
1108 } else {
1109 FIXME_(d3d_caps)("Adapter not primary display\n");
1111 return 0;
1114 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1115 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1116 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1117 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1119 /* Validate the parameters as much as possible */
1120 if (NULL == pMode ||
1121 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1122 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1123 return WINED3DERR_INVALIDCALL;
1126 /* TODO: Store modes per adapter and read it from the adapter structure */
1127 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1128 DEVMODEW DevModeW;
1129 int ModeIdx = 0;
1130 int i = 0;
1131 int j = 0;
1133 ZeroMemory(&DevModeW, sizeof(DevModeW));
1134 DevModeW.dmSize = sizeof(DevModeW);
1136 /* If we are filtering to a specific format (D3D9), then need to skip
1137 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1138 just count through the ones with valid bit depths */
1139 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1140 switch (Format)
1142 case WINED3DFMT_UNKNOWN:
1143 /* This is D3D8. Do not enumerate P8 here */
1144 if (DevModeW.dmBitsPerPel == 32 ||
1145 DevModeW.dmBitsPerPel == 16) i++;
1146 break;
1147 case WINED3DFMT_X8R8G8B8:
1148 if (DevModeW.dmBitsPerPel == 32) i++;
1149 break;
1150 case WINED3DFMT_R5G6B5:
1151 if (DevModeW.dmBitsPerPel == 16) i++;
1152 break;
1153 case WINED3DFMT_P8:
1154 if (DevModeW.dmBitsPerPel == 8) i++;
1155 break;
1156 default:
1157 /* Modes that don't match what we support can get an early-out */
1158 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1159 return WINED3DERR_INVALIDCALL;
1163 if (i == 0) {
1164 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1165 return WINED3DERR_INVALIDCALL;
1167 ModeIdx = j - 1;
1169 /* Now get the display mode via the calculated index */
1170 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1171 pMode->Width = DevModeW.dmPelsWidth;
1172 pMode->Height = DevModeW.dmPelsHeight;
1173 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1174 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1175 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1177 if (Format == WINED3DFMT_UNKNOWN)
1179 switch (DevModeW.dmBitsPerPel)
1181 case 8:
1182 pMode->Format = WINED3DFMT_P8;
1183 break;
1184 case 16:
1185 pMode->Format = WINED3DFMT_R5G6B5;
1186 break;
1187 case 32:
1188 pMode->Format = WINED3DFMT_X8R8G8B8;
1189 break;
1190 default:
1191 pMode->Format = WINED3DFMT_UNKNOWN;
1192 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1194 } else {
1195 pMode->Format = Format;
1197 } else {
1198 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1199 return WINED3DERR_INVALIDCALL;
1202 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1203 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1204 DevModeW.dmBitsPerPel);
1206 } else if (DEBUG_SINGLE_MODE) {
1207 /* Return one setting of the format requested */
1208 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1209 pMode->Width = 800;
1210 pMode->Height = 600;
1211 pMode->RefreshRate = 60;
1212 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1213 } else {
1214 FIXME_(d3d_caps)("Adapter not primary display\n");
1217 return WINED3D_OK;
1220 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1221 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1222 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1224 if (NULL == pMode ||
1225 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1226 return WINED3DERR_INVALIDCALL;
1229 if (Adapter == 0) { /* Display */
1230 int bpp = 0;
1231 DEVMODEW DevModeW;
1233 ZeroMemory(&DevModeW, sizeof(DevModeW));
1234 DevModeW.dmSize = sizeof(DevModeW);
1236 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1237 pMode->Width = DevModeW.dmPelsWidth;
1238 pMode->Height = DevModeW.dmPelsHeight;
1239 bpp = DevModeW.dmBitsPerPel;
1240 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1241 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1243 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1246 switch (bpp) {
1247 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1248 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1249 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1250 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1251 default: pMode->Format = WINED3DFMT_UNKNOWN;
1254 } else {
1255 FIXME_(d3d_caps)("Adapter not primary display\n");
1258 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1259 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1260 return WINED3D_OK;
1263 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1264 and fields being inserted in the middle, a new structure is used in place */
1265 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1266 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1267 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1269 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1271 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1272 return WINED3DERR_INVALIDCALL;
1275 /* Return the information requested */
1276 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1277 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1278 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1280 /* Note dx8 doesn't supply a DeviceName */
1281 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1282 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1283 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1284 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1285 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1286 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1287 *(pIdentifier->SubSysId) = 0;
1288 *(pIdentifier->Revision) = 0;
1290 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1291 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1292 *(pIdentifier->WHQLLevel) = 0;
1293 } else {
1294 *(pIdentifier->WHQLLevel) = 1;
1297 return WINED3D_OK;
1300 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1301 short redSize, greenSize, blueSize, alphaSize, colorBits;
1303 if(!cfg)
1304 return FALSE;
1306 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1307 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1308 return FALSE;
1311 if(cfg->redSize < redSize)
1312 return FALSE;
1314 if(cfg->greenSize < greenSize)
1315 return FALSE;
1317 if(cfg->blueSize < blueSize)
1318 return FALSE;
1320 if(cfg->alphaSize < alphaSize)
1321 return FALSE;
1323 return TRUE;
1326 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1327 short depthSize, stencilSize;
1329 if(!cfg)
1330 return FALSE;
1332 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1333 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1334 return FALSE;
1337 if(cfg->depthSize < depthSize)
1338 return FALSE;
1340 if(cfg->stencilSize < stencilSize)
1341 return FALSE;
1343 return TRUE;
1346 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1347 WINED3DFORMAT AdapterFormat,
1348 WINED3DFORMAT RenderTargetFormat,
1349 WINED3DFORMAT DepthStencilFormat) {
1350 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1351 int nCfgs;
1352 WineD3D_PixelFormat *cfgs;
1353 int it;
1355 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1356 This, Adapter,
1357 DeviceType, debug_d3ddevicetype(DeviceType),
1358 AdapterFormat, debug_d3dformat(AdapterFormat),
1359 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1360 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1362 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1363 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1364 return WINED3DERR_INVALIDCALL;
1367 cfgs = Adapters[Adapter].cfgs;
1368 nCfgs = Adapters[Adapter].nCfgs;
1369 for (it = 0; it < nCfgs; ++it) {
1370 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1371 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1372 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1373 return WINED3D_OK;
1377 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1379 return WINED3DERR_NOTAVAILABLE;
1382 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1383 WINED3DFORMAT SurfaceFormat,
1384 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1386 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1387 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1388 This,
1389 Adapter,
1390 DeviceType, debug_d3ddevicetype(DeviceType),
1391 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1392 Windowed,
1393 MultiSampleType,
1394 pQualityLevels);
1396 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1397 return WINED3DERR_INVALIDCALL;
1400 /* TODO: Store in Adapter structure */
1401 if (pQualityLevels != NULL) {
1402 static int s_single_shot = 0;
1403 if (!s_single_shot) {
1404 FIXME("Quality levels unsupported at present\n");
1405 s_single_shot = 1;
1407 *pQualityLevels = 1; /* Guess at a value! */
1410 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1411 return WINED3DERR_NOTAVAILABLE;
1414 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1415 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1417 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1418 int nCfgs = 0;
1419 WineD3D_PixelFormat *cfgs;
1420 int it;
1421 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1423 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1424 This,
1425 Adapter,
1426 CheckType, debug_d3ddevicetype(CheckType),
1427 DisplayFormat, debug_d3dformat(DisplayFormat),
1428 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1429 Windowed);
1431 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1432 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1433 return WINED3DERR_INVALIDCALL;
1436 cfgs = Adapters[Adapter].cfgs;
1437 nCfgs = Adapters[Adapter].nCfgs;
1438 for (it = 0; it < nCfgs; ++it) {
1439 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1440 hr = WINED3D_OK;
1441 TRACE_(d3d_caps)("OK\n");
1442 break ;
1446 if(hr != WINED3D_OK)
1447 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1449 if(hr != WINED3D_OK)
1450 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1452 return hr;
1455 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1456 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1457 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1458 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1459 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1460 This,
1461 Adapter,
1462 DeviceType, debug_d3ddevicetype(DeviceType),
1463 AdapterFormat, debug_d3dformat(AdapterFormat),
1464 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1465 RType, debug_d3dresourcetype(RType),
1466 CheckFormat, debug_d3dformat(CheckFormat));
1468 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1469 return WINED3DERR_INVALIDCALL;
1472 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1473 switch (CheckFormat) {
1474 /* Filtering not supported */
1475 case WINED3DFMT_A32B32G32R32F:
1476 TRACE_(d3d_caps)("[FAILED]\n");
1477 return WINED3DERR_NOTAVAILABLE;
1478 default:
1479 break;
1483 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1484 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1485 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1486 return WINED3DERR_NOTAVAILABLE;
1490 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1491 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1492 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1493 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1494 if (!GL_LIMITS(vertex_samplers)) {
1495 TRACE_(d3d_caps)("[FAILED]\n");
1496 return WINED3DERR_NOTAVAILABLE;
1499 switch (CheckFormat) {
1500 case WINED3DFMT_A32B32G32R32F:
1501 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1502 TRACE_(d3d_caps)("[FAILED]\n");
1503 return WINED3DERR_NOTAVAILABLE;
1505 TRACE_(d3d_caps)("[OK]\n");
1506 return WINED3D_OK;
1508 default:
1509 TRACE_(d3d_caps)("[FAILED]\n");
1510 return WINED3DERR_NOTAVAILABLE;
1514 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1515 switch (CheckFormat) {
1516 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1517 * Windows supports only those 3, and enumerating the other formats confuses applications
1519 case WINED3DFMT_D24S8:
1520 case WINED3DFMT_D24X8:
1521 case WINED3DFMT_D16:
1522 TRACE_(d3d_caps)("[OK]\n");
1523 return WINED3D_OK;
1524 case WINED3DFMT_D16_LOCKABLE:
1525 case WINED3DFMT_D24FS8:
1526 case WINED3DFMT_D32F_LOCKABLE:
1527 case WINED3DFMT_D24X4S4:
1528 case WINED3DFMT_D15S1:
1529 case WINED3DFMT_D32:
1530 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1531 return WINED3DERR_NOTAVAILABLE;
1532 default:
1533 TRACE_(d3d_caps)("[FAILED]\n");
1534 return WINED3DERR_NOTAVAILABLE;
1536 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1537 switch (CheckFormat) {
1538 case WINED3DFMT_R8G8B8:
1539 case WINED3DFMT_A8R8G8B8:
1540 case WINED3DFMT_X8R8G8B8:
1541 case WINED3DFMT_R5G6B5:
1542 case WINED3DFMT_X1R5G5B5:
1543 case WINED3DFMT_A1R5G5B5:
1544 case WINED3DFMT_A4R4G4B4:
1545 case WINED3DFMT_R3G3B2:
1546 case WINED3DFMT_X4R4G4B4:
1547 case WINED3DFMT_A8B8G8R8:
1548 case WINED3DFMT_X8B8G8R8:
1549 case WINED3DFMT_P8:
1550 TRACE_(d3d_caps)("[OK]\n");
1551 return WINED3D_OK;
1552 case WINED3DFMT_R16F:
1553 case WINED3DFMT_A16B16G16R16F:
1554 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1555 TRACE_(d3d_caps)("[FAILED]\n");
1556 return WINED3DERR_NOTAVAILABLE;
1558 TRACE_(d3d_caps)("[OK]\n");
1559 return WINED3D_OK;
1560 case WINED3DFMT_A32B32G32R32F:
1561 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1562 TRACE_(d3d_caps)("[FAILED]\n");
1563 return WINED3DERR_NOTAVAILABLE;
1565 TRACE_(d3d_caps)("[OK]\n");
1566 return WINED3D_OK;
1567 default:
1568 TRACE_(d3d_caps)("[FAILED]\n");
1569 return WINED3DERR_NOTAVAILABLE;
1571 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1572 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1573 switch (CheckFormat) {
1574 case WINED3DFMT_V8U8:
1575 TRACE_(d3d_caps)("[OK]\n");
1576 return WINED3D_OK;
1577 /* TODO: Other bump map formats */
1578 default:
1579 TRACE_(d3d_caps)("[FAILED]\n");
1580 return WINED3DERR_NOTAVAILABLE;
1583 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1584 switch (CheckFormat) {
1585 case WINED3DFMT_V8U8:
1586 TRACE_(d3d_caps)("[OK]\n");
1587 return WINED3D_OK;
1588 default:
1589 TRACE_(d3d_caps)("[FAILED]\n");
1590 return WINED3DERR_NOTAVAILABLE;
1593 TRACE_(d3d_caps)("[FAILED]\n");
1594 return WINED3DERR_NOTAVAILABLE;
1597 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1598 switch (CheckFormat) {
1599 case WINED3DFMT_DXT1:
1600 case WINED3DFMT_DXT2:
1601 case WINED3DFMT_DXT3:
1602 case WINED3DFMT_DXT4:
1603 case WINED3DFMT_DXT5:
1604 TRACE_(d3d_caps)("[OK]\n");
1605 return WINED3D_OK;
1606 default:
1607 break; /* Avoid compiler warnings */
1611 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1612 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1613 switch (CheckFormat) {
1614 case WINED3DFMT_A8R8G8B8:
1615 case WINED3DFMT_X8R8G8B8:
1616 case WINED3DFMT_A4R4G4B4:
1617 case WINED3DFMT_L8:
1618 case WINED3DFMT_A8L8:
1619 case WINED3DFMT_DXT1:
1620 case WINED3DFMT_DXT2:
1621 case WINED3DFMT_DXT3:
1622 case WINED3DFMT_DXT4:
1623 case WINED3DFMT_DXT5:
1624 TRACE_(d3d_caps)("[OK]\n");
1625 return WINED3D_OK;
1627 default:
1628 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1629 return WINED3DERR_NOTAVAILABLE;
1633 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1635 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1637 switch (CheckFormat) {
1638 case WINED3DFMT_R16F:
1639 case WINED3DFMT_A16B16G16R16F:
1640 if (!half_pixel_support) break;
1641 case WINED3DFMT_R32F:
1642 case WINED3DFMT_A32B32G32R32F:
1643 TRACE_(d3d_caps)("[OK]\n");
1644 return WINED3D_OK;
1645 default:
1646 break; /* Avoid compiler warnings */
1650 /* This format is nothing special and it is supported perfectly.
1651 * However, ati and nvidia driver on windows do not mark this format as
1652 * supported (tested with the dxCapsViewer) and pretending to
1653 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1654 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1655 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1657 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1658 TRACE_(d3d_caps)("[FAILED]\n");
1659 return WINED3DERR_NOTAVAILABLE;
1662 switch (CheckFormat) {
1664 /*****
1665 * supported: RGB(A) formats
1667 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1668 case WINED3DFMT_A8R8G8B8:
1669 case WINED3DFMT_X8R8G8B8:
1670 case WINED3DFMT_R5G6B5:
1671 case WINED3DFMT_X1R5G5B5:
1672 case WINED3DFMT_A1R5G5B5:
1673 case WINED3DFMT_A4R4G4B4:
1674 case WINED3DFMT_R3G3B2:
1675 case WINED3DFMT_A8:
1676 case WINED3DFMT_X4R4G4B4:
1677 case WINED3DFMT_A8B8G8R8:
1678 case WINED3DFMT_X8B8G8R8:
1679 case WINED3DFMT_A2R10G10B10:
1680 case WINED3DFMT_A2B10G10R10:
1681 TRACE_(d3d_caps)("[OK]\n");
1682 return WINED3D_OK;
1684 /*****
1685 * supported: Palettized
1687 case WINED3DFMT_P8:
1688 TRACE_(d3d_caps)("[OK]\n");
1689 return WINED3D_OK;
1691 /*****
1692 * Supported: (Alpha)-Luminance
1694 case WINED3DFMT_L8:
1695 case WINED3DFMT_A8L8:
1696 case WINED3DFMT_A4L4:
1697 TRACE_(d3d_caps)("[OK]\n");
1698 return WINED3D_OK;
1700 /*****
1701 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1702 * GL_NV_texture_shader), but advertized to make apps happy.
1703 * Enable some because games often fail when they are not available
1704 * and are still playable even without bump mapping
1706 case WINED3DFMT_V8U8:
1707 case WINED3DFMT_V16U16:
1708 case WINED3DFMT_L6V5U5:
1709 case WINED3DFMT_X8L8V8U8:
1710 case WINED3DFMT_Q8W8V8U8:
1711 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1712 return WINED3D_OK;
1714 /* Those are not advertized by the nvidia windows driver, and not
1715 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1716 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1717 * ARGB format if needed
1719 case WINED3DFMT_W11V11U10:
1720 case WINED3DFMT_A2W10V10U10:
1721 WARN_(d3d_caps)("[FAILED]\n");
1722 return WINED3DERR_NOTAVAILABLE;
1724 /*****
1725 * DXTN Formats: Handled above
1726 * WINED3DFMT_DXT1
1727 * WINED3DFMT_DXT2
1728 * WINED3DFMT_DXT3
1729 * WINED3DFMT_DXT4
1730 * WINED3DFMT_DXT5
1733 /*****
1734 * Odd formats - not supported
1736 case WINED3DFMT_VERTEXDATA:
1737 case WINED3DFMT_INDEX16:
1738 case WINED3DFMT_INDEX32:
1739 case WINED3DFMT_Q16W16V16U16:
1740 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1741 return WINED3DERR_NOTAVAILABLE;
1743 /*****
1744 * Float formats: Not supported right now
1746 case WINED3DFMT_G16R16F:
1747 case WINED3DFMT_G32R32F:
1748 case WINED3DFMT_CxV8U8:
1749 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1750 return WINED3DERR_NOTAVAILABLE;
1752 /* Not supported */
1753 case WINED3DFMT_G16R16:
1754 case WINED3DFMT_A16B16G16R16:
1755 case WINED3DFMT_A8R3G3B2:
1756 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1757 return WINED3DERR_NOTAVAILABLE;
1759 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1760 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1761 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1762 * We can do instancing with all shader versions, but we need vertex shaders.
1764 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1765 * to enable instancing. WineD3D doesn't need that and just ignores it.
1767 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1769 case WINEMAKEFOURCC('I','N','S','T'):
1770 TRACE("ATI Instancing check hack\n");
1771 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1772 TRACE_(d3d_caps)("[OK]\n");
1773 return WINED3D_OK;
1774 } else {
1775 TRACE_(d3d_caps)("[FAILED]\n");
1776 return WINED3DERR_NOTAVAILABLE;
1779 default:
1780 break;
1783 TRACE_(d3d_caps)("[FAILED]\n");
1784 return WINED3DERR_NOTAVAILABLE;
1787 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1788 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1789 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1791 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1792 This,
1793 Adapter,
1794 DeviceType, debug_d3ddevicetype(DeviceType),
1795 SourceFormat, debug_d3dformat(SourceFormat),
1796 TargetFormat, debug_d3dformat(TargetFormat));
1797 return WINED3D_OK;
1800 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1801 subset of a D3DCAPS9 structure. However, it has to come via a void *
1802 as the d3d8 interface cannot import the d3d9 header */
1803 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1805 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1806 int vs_selected_mode;
1807 int ps_selected_mode;
1809 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1811 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1812 return WINED3DERR_INVALIDCALL;
1815 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1817 /* This function should *not* be modifying GL caps
1818 * TODO: move the functionality where it belongs */
1819 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1821 /* ------------------------------------------------
1822 The following fields apply to both d3d8 and d3d9
1823 ------------------------------------------------ */
1824 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1825 *pCaps->AdapterOrdinal = Adapter;
1827 *pCaps->Caps = 0;
1828 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1829 WINED3DCAPS2_FULLSCREENGAMMA |
1830 WINED3DCAPS2_DYNAMICTEXTURES;
1831 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1832 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
1833 WINED3DPRESENT_INTERVAL_ONE;
1835 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1836 WINED3DCURSORCAPS_LOWRES;
1838 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1839 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1840 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1841 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1842 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1843 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1844 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1845 WINED3DDEVCAPS_PUREDEVICE |
1846 WINED3DDEVCAPS_HWRASTERIZATION |
1847 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1848 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1849 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1850 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1851 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1852 WINED3DDEVCAPS_RTPATCHES;
1854 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1855 WINED3DPMISCCAPS_CULLCCW |
1856 WINED3DPMISCCAPS_CULLCW |
1857 WINED3DPMISCCAPS_COLORWRITEENABLE |
1858 WINED3DPMISCCAPS_CLIPTLVERTS |
1859 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1860 WINED3DPMISCCAPS_MASKZ |
1861 WINED3DPMISCCAPS_BLENDOP;
1862 /* TODO:
1863 WINED3DPMISCCAPS_NULLREFERENCE
1864 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1865 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1866 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1867 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1868 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1869 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1871 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1872 #if 0
1873 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1874 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1875 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1876 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1877 #endif
1879 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1880 WINED3DPRASTERCAPS_PAT |
1881 WINED3DPRASTERCAPS_WFOG |
1882 WINED3DPRASTERCAPS_ZFOG |
1883 WINED3DPRASTERCAPS_FOGVERTEX |
1884 WINED3DPRASTERCAPS_FOGTABLE |
1885 WINED3DPRASTERCAPS_STIPPLE |
1886 WINED3DPRASTERCAPS_SUBPIXEL |
1887 WINED3DPRASTERCAPS_ZTEST |
1888 WINED3DPRASTERCAPS_SCISSORTEST |
1889 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1890 WINED3DPRASTERCAPS_DEPTHBIAS;
1892 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1893 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1894 WINED3DPRASTERCAPS_ZBIAS |
1895 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1897 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
1898 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
1900 /* FIXME Add:
1901 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1902 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1903 WINED3DPRASTERCAPS_ANTIALIASEDGES
1904 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1905 WINED3DPRASTERCAPS_WBUFFER */
1907 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1908 WINED3DPCMPCAPS_EQUAL |
1909 WINED3DPCMPCAPS_GREATER |
1910 WINED3DPCMPCAPS_GREATEREQUAL |
1911 WINED3DPCMPCAPS_LESS |
1912 WINED3DPCMPCAPS_LESSEQUAL |
1913 WINED3DPCMPCAPS_NEVER |
1914 WINED3DPCMPCAPS_NOTEQUAL;
1916 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1917 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1918 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1919 WINED3DPBLENDCAPS_DESTALPHA |
1920 WINED3DPBLENDCAPS_DESTCOLOR |
1921 WINED3DPBLENDCAPS_INVDESTALPHA |
1922 WINED3DPBLENDCAPS_INVDESTCOLOR |
1923 WINED3DPBLENDCAPS_INVSRCALPHA |
1924 WINED3DPBLENDCAPS_INVSRCCOLOR |
1925 WINED3DPBLENDCAPS_ONE |
1926 WINED3DPBLENDCAPS_SRCALPHA |
1927 WINED3DPBLENDCAPS_SRCALPHASAT |
1928 WINED3DPBLENDCAPS_SRCCOLOR |
1929 WINED3DPBLENDCAPS_ZERO;
1931 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1932 WINED3DPBLENDCAPS_DESTALPHA |
1933 WINED3DPBLENDCAPS_DESTCOLOR |
1934 WINED3DPBLENDCAPS_INVDESTALPHA |
1935 WINED3DPBLENDCAPS_INVDESTCOLOR |
1936 WINED3DPBLENDCAPS_INVSRCALPHA |
1937 WINED3DPBLENDCAPS_INVSRCCOLOR |
1938 WINED3DPBLENDCAPS_ONE |
1939 WINED3DPBLENDCAPS_SRCALPHA |
1940 WINED3DPBLENDCAPS_SRCCOLOR |
1941 WINED3DPBLENDCAPS_ZERO;
1942 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
1943 * according to the glBlendFunc manpage
1945 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
1946 * legacy settings for srcblend only
1949 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1950 WINED3DPCMPCAPS_EQUAL |
1951 WINED3DPCMPCAPS_GREATER |
1952 WINED3DPCMPCAPS_GREATEREQUAL |
1953 WINED3DPCMPCAPS_LESS |
1954 WINED3DPCMPCAPS_LESSEQUAL |
1955 WINED3DPCMPCAPS_NEVER |
1956 WINED3DPCMPCAPS_NOTEQUAL;
1958 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1959 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1960 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1961 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1962 WINED3DPSHADECAPS_COLORFLATRGB |
1963 WINED3DPSHADECAPS_FOGFLAT |
1964 WINED3DPSHADECAPS_FOGGOURAUD |
1965 WINED3DPSHADECAPS_SPECULARFLATRGB;
1967 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1968 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1969 WINED3DPTEXTURECAPS_BORDER |
1970 WINED3DPTEXTURECAPS_MIPMAP |
1971 WINED3DPTEXTURECAPS_PROJECTED |
1972 WINED3DPTEXTURECAPS_PERSPECTIVE;
1974 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
1975 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
1976 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1979 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1980 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1981 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1982 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1985 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1986 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1987 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1988 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1992 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1993 WINED3DPTFILTERCAPS_MAGFPOINT |
1994 WINED3DPTFILTERCAPS_MINFLINEAR |
1995 WINED3DPTFILTERCAPS_MINFPOINT |
1996 WINED3DPTFILTERCAPS_MIPFLINEAR |
1997 WINED3DPTFILTERCAPS_MIPFPOINT |
1998 WINED3DPTFILTERCAPS_LINEAR |
1999 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2000 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2001 WINED3DPTFILTERCAPS_MIPLINEAR |
2002 WINED3DPTFILTERCAPS_MIPNEAREST |
2003 WINED3DPTFILTERCAPS_NEAREST;
2005 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2006 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2007 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2010 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2011 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2012 WINED3DPTFILTERCAPS_MAGFPOINT |
2013 WINED3DPTFILTERCAPS_MINFLINEAR |
2014 WINED3DPTFILTERCAPS_MINFPOINT |
2015 WINED3DPTFILTERCAPS_MIPFLINEAR |
2016 WINED3DPTFILTERCAPS_MIPFPOINT |
2017 WINED3DPTFILTERCAPS_LINEAR |
2018 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2019 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2020 WINED3DPTFILTERCAPS_MIPLINEAR |
2021 WINED3DPTFILTERCAPS_MIPNEAREST |
2022 WINED3DPTFILTERCAPS_NEAREST;
2024 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2025 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2026 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2028 } else
2029 *pCaps->CubeTextureFilterCaps = 0;
2031 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2032 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2033 WINED3DPTFILTERCAPS_MAGFPOINT |
2034 WINED3DPTFILTERCAPS_MINFLINEAR |
2035 WINED3DPTFILTERCAPS_MINFPOINT |
2036 WINED3DPTFILTERCAPS_MIPFLINEAR |
2037 WINED3DPTFILTERCAPS_MIPFPOINT |
2038 WINED3DPTFILTERCAPS_LINEAR |
2039 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2040 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2041 WINED3DPTFILTERCAPS_MIPLINEAR |
2042 WINED3DPTFILTERCAPS_MIPNEAREST |
2043 WINED3DPTFILTERCAPS_NEAREST;
2044 } else
2045 *pCaps->VolumeTextureFilterCaps = 0;
2047 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2048 WINED3DPTADDRESSCAPS_CLAMP |
2049 WINED3DPTADDRESSCAPS_WRAP;
2051 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2052 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2054 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2055 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2057 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2058 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2061 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2062 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2063 WINED3DPTADDRESSCAPS_CLAMP |
2064 WINED3DPTADDRESSCAPS_WRAP;
2065 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2066 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2068 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2069 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2071 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2072 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2074 } else
2075 *pCaps->VolumeTextureAddressCaps = 0;
2077 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2078 WINED3DLINECAPS_ZTEST;
2079 /* FIXME: Add
2080 WINED3DLINECAPS_BLEND
2081 WINED3DLINECAPS_ALPHACMP
2082 WINED3DLINECAPS_FOG */
2084 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2085 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2087 if(GL_SUPPORT(EXT_TEXTURE3D))
2088 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2089 else
2090 *pCaps->MaxVolumeExtent = 0;
2092 *pCaps->MaxTextureRepeat = 32768;
2093 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2094 *pCaps->MaxVertexW = 1.0;
2096 *pCaps->GuardBandLeft = 0;
2097 *pCaps->GuardBandTop = 0;
2098 *pCaps->GuardBandRight = 0;
2099 *pCaps->GuardBandBottom = 0;
2101 *pCaps->ExtentsAdjust = 0;
2103 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2104 WINED3DSTENCILCAPS_INCRSAT |
2105 WINED3DSTENCILCAPS_INVERT |
2106 WINED3DSTENCILCAPS_KEEP |
2107 WINED3DSTENCILCAPS_REPLACE |
2108 WINED3DSTENCILCAPS_ZERO;
2109 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2110 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2111 WINED3DSTENCILCAPS_INCR;
2113 if ( This->dxVersion > 8 &&
2114 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2115 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2116 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2119 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2121 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2122 WINED3DTEXOPCAPS_ADDSIGNED |
2123 WINED3DTEXOPCAPS_ADDSIGNED2X |
2124 WINED3DTEXOPCAPS_MODULATE |
2125 WINED3DTEXOPCAPS_MODULATE2X |
2126 WINED3DTEXOPCAPS_MODULATE4X |
2127 WINED3DTEXOPCAPS_SELECTARG1 |
2128 WINED3DTEXOPCAPS_SELECTARG2 |
2129 WINED3DTEXOPCAPS_DISABLE;
2131 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2132 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2133 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2134 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2135 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2136 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2137 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2138 WINED3DTEXOPCAPS_LERP |
2139 WINED3DTEXOPCAPS_SUBTRACT;
2141 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2142 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2143 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2144 WINED3DTEXOPCAPS_MULTIPLYADD |
2145 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2146 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2147 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2149 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2150 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2152 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2153 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2154 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2157 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2158 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2159 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2160 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2161 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2162 * and 3D textures. It also allows us to keep the code simpler by having texture
2163 * shaders constantly enabled.
2165 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2166 /* TODO: Luminance bump map? */
2168 #if 0
2169 /* FIXME: Add
2170 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2171 WINED3DTEXOPCAPS_PREMODULATE */
2172 #endif
2174 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2175 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2176 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2177 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2179 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2180 *pCaps->MaxVertexBlendMatrixIndex = 0;
2182 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2183 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2186 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2187 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2188 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2189 WINED3DVTXPCAPS_LOCALVIEWER |
2190 WINED3DVTXPCAPS_VERTEXFOG |
2191 WINED3DVTXPCAPS_TEXGEN;
2192 /* FIXME: Add
2193 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2195 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2196 *pCaps->MaxVertexIndex = 0xFFFFF;
2197 *pCaps->MaxStreams = MAX_STREAMS;
2198 *pCaps->MaxStreamStride = 1024;
2200 if (vs_selected_mode == SHADER_GLSL) {
2201 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2202 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2203 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2204 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2205 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2206 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2207 else
2208 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2209 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2210 } else if (vs_selected_mode == SHADER_ARB) {
2211 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2212 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2213 } else {
2214 *pCaps->VertexShaderVersion = 0;
2215 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2218 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2220 if (ps_selected_mode == SHADER_GLSL) {
2221 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2222 in case of GeforceFX cards. */
2223 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2224 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2225 else
2226 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2227 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2228 * Direct3D minimum requirement.
2230 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2231 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2233 * The problem is that the refrast clamps temporary results in the shader to
2234 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2235 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2236 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2237 * offer a way to query this.
2239 *pCaps->PixelShader1xMaxValue = 8.0;
2240 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2241 } else if (ps_selected_mode == SHADER_ARB) {
2242 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2243 *pCaps->PixelShader1xMaxValue = 8.0;
2244 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2245 } else {
2246 *pCaps->PixelShaderVersion = 0;
2247 *pCaps->PixelShader1xMaxValue = 0.0;
2248 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2251 /* ------------------------------------------------
2252 The following fields apply to d3d9 only
2253 ------------------------------------------------ */
2254 if (This->dxVersion > 8) {
2255 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2256 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2257 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2258 *pCaps->MaxNpatchTessellationLevel = 0;
2259 *pCaps->MasterAdapterOrdinal = 0;
2260 *pCaps->AdapterOrdinalInGroup = 0;
2261 *pCaps->NumberOfAdaptersInGroup = 1;
2263 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2264 /* OpenGL supports all the formats below, perhaps not always
2265 * without conversion, but it supports them.
2266 * Further GLSL doesn't seem to have an official unsigned type so
2267 * don't advertise it yet as I'm not sure how we handle it.
2268 * We might need to add some clamping in the shader engine to
2269 * support it.
2270 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2271 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2272 WINED3DDTCAPS_UBYTE4N |
2273 WINED3DDTCAPS_SHORT2N |
2274 WINED3DDTCAPS_SHORT4N;
2275 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2276 *pCaps->DeclTypes |=
2277 WINED3DDTCAPS_FLOAT16_2 |
2278 WINED3DDTCAPS_FLOAT16_4;
2280 } else
2281 *pCaps->DeclTypes = 0;
2283 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2286 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2287 WINED3DPTFILTERCAPS_MAGFPOINT |
2288 WINED3DPTFILTERCAPS_MINFLINEAR |
2289 WINED3DPTFILTERCAPS_MAGFLINEAR;
2290 *pCaps->VertexTextureFilterCaps = 0;
2292 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2293 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2294 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2295 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2296 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2297 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2298 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2300 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2301 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2302 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2303 *pCaps->VS20Caps.Caps = 0;
2304 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2305 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2306 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2308 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2309 *pCaps->MaxVertexShader30InstructionSlots = 0;
2310 } else { /* VS 1.x */
2311 *pCaps->VS20Caps.Caps = 0;
2312 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2313 *pCaps->VS20Caps.NumTemps = 0;
2314 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2316 *pCaps->MaxVShaderInstructionsExecuted = 0;
2317 *pCaps->MaxVertexShader30InstructionSlots = 0;
2320 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2321 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2322 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2324 /* 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 */
2325 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2326 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2327 WINED3DPS20CAPS_PREDICATION |
2328 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2329 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2330 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2331 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2332 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2333 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2335 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2336 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2337 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2338 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2339 *pCaps->PS20Caps.Caps = 0;
2340 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2341 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2342 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2343 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2345 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2346 *pCaps->MaxPixelShader30InstructionSlots = 0;
2347 } else { /* PS 1.x */
2348 *pCaps->PS20Caps.Caps = 0;
2349 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2350 *pCaps->PS20Caps.NumTemps = 0;
2351 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2352 *pCaps->PS20Caps.NumInstructionSlots = 0;
2354 *pCaps->MaxPShaderInstructionsExecuted = 0;
2355 *pCaps->MaxPixelShader30InstructionSlots = 0;
2359 return WINED3D_OK;
2362 static unsigned int glsl_program_key_hash(void *key) {
2363 glsl_program_key_t *k = (glsl_program_key_t *)key;
2365 unsigned int hash = k->vshader | k->pshader << 16;
2366 hash += ~(hash << 15);
2367 hash ^= (hash >> 10);
2368 hash += (hash << 3);
2369 hash ^= (hash >> 6);
2370 hash += ~(hash << 11);
2371 hash ^= (hash >> 16);
2373 return hash;
2376 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2377 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2378 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2380 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2383 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2384 and fields being inserted in the middle, a new structure is used in place */
2385 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2386 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2387 IUnknown *parent) {
2389 IWineD3DDeviceImpl *object = NULL;
2390 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2391 HDC hDC;
2392 int i;
2394 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2395 * number and create a device without a 3D adapter for 2D only operation.
2397 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2398 return WINED3DERR_INVALIDCALL;
2401 /* Create a WineD3DDevice object */
2402 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2403 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2404 TRACE("Created WineD3DDevice object @ %p\n", object);
2405 if (NULL == object) {
2406 return WINED3DERR_OUTOFVIDEOMEMORY;
2409 /* Set up initial COM information */
2410 object->lpVtbl = &IWineD3DDevice_Vtbl;
2411 object->ref = 1;
2412 object->wineD3D = iface;
2413 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2414 IWineD3D_AddRef(object->wineD3D);
2415 object->parent = parent;
2417 if(This->dxVersion == 7) {
2418 object->surface_alignment = 8;
2419 } else {
2420 object->surface_alignment = 4;
2423 /* Set the state up as invalid until the device is fully created */
2424 object->state = WINED3DERR_DRIVERINTERNALERROR;
2426 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2427 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2429 /* Save the creation parameters */
2430 object->createParms.AdapterOrdinal = Adapter;
2431 object->createParms.DeviceType = DeviceType;
2432 object->createParms.hFocusWindow = hFocusWindow;
2433 object->createParms.BehaviorFlags = BehaviourFlags;
2435 /* Initialize other useful values */
2436 object->adapterNo = Adapter;
2437 object->devType = DeviceType;
2439 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2440 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2441 object->shader_backend = &glsl_shader_backend;
2442 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2443 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2444 object->shader_backend = &arb_program_shader_backend;
2445 } else {
2446 object->shader_backend = &none_shader_backend;
2449 /* set the state of the device to valid */
2450 object->state = WINED3D_OK;
2452 /* Get the initial screen setup for ddraw */
2453 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2454 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2455 hDC = GetDC(0);
2456 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2457 ReleaseDC(0, hDC);
2459 for(i = 0; i < PATCHMAP_SIZE; i++) {
2460 list_init(&object->patches[i]);
2462 return WINED3D_OK;
2464 #undef GLINFO_LOCATION
2466 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2467 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2468 IUnknown_AddRef(This->parent);
2469 *pParent = This->parent;
2470 return WINED3D_OK;
2473 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2474 IUnknown* surfaceParent;
2475 TRACE("(%p) call back\n", pSurface);
2477 /* Now, release the parent, which will take care of cleaning up the surface for us */
2478 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2479 IUnknown_Release(surfaceParent);
2480 return IUnknown_Release(surfaceParent);
2483 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2484 IUnknown* volumeParent;
2485 TRACE("(%p) call back\n", pVolume);
2487 /* Now, release the parent, which will take care of cleaning up the volume for us */
2488 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2489 IUnknown_Release(volumeParent);
2490 return IUnknown_Release(volumeParent);
2493 #define PUSH1(att) attribs[nAttribs++] = (att);
2494 #define GLINFO_LOCATION (Adapters[0].gl_info)
2495 BOOL InitAdapters(void) {
2496 static HMODULE mod_gl;
2497 BOOL ret;
2498 int ps_selected_mode, vs_selected_mode;
2500 /* No need to hold any lock. The calling library makes sure only one thread calls
2501 * wined3d simultaneously
2503 if(numAdapters > 0) return TRUE;
2505 TRACE("Initializing adapters\n");
2507 if(!mod_gl) {
2508 #ifdef USE_WIN32_OPENGL
2509 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2510 mod_gl = LoadLibraryA("opengl32.dll");
2511 if(!mod_gl) {
2512 ERR("Can't load opengl32.dll!\n");
2513 return FALSE;
2515 #else
2516 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2517 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2518 mod_gl = GetModuleHandleA("gdi32.dll");
2519 #endif
2522 /* Load WGL core functions from opengl32.dll */
2523 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2524 WGL_FUNCS_GEN;
2525 #undef USE_WGL_FUNC
2527 if(!pwglGetProcAddress) {
2528 ERR("Unable to load wglGetProcAddress!\n");
2529 return FALSE;
2532 /* Dynamically load all GL core functions */
2533 GL_FUNCS_GEN;
2534 #undef USE_GL_FUNC
2536 /* For now only one default adapter */
2538 int iPixelFormat;
2539 int attribs[8];
2540 int values[8];
2541 int nAttribs = 0;
2542 int res;
2543 WineD3D_PixelFormat *cfgs;
2544 int attribute;
2545 DISPLAY_DEVICEW DisplayDevice;
2546 HDC hdc;
2548 TRACE("Initializing default adapter\n");
2549 Adapters[0].monitorPoint.x = -1;
2550 Adapters[0].monitorPoint.y = -1;
2552 if (!WineD3D_CreateFakeGLContext()) {
2553 ERR("Failed to get a gl context for default adapter\n");
2554 HeapFree(GetProcessHeap(), 0, Adapters);
2555 WineD3D_ReleaseFakeGLContext();
2556 return FALSE;
2559 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2560 if(!ret) {
2561 ERR("Failed to initialize gl caps for default adapter\n");
2562 HeapFree(GetProcessHeap(), 0, Adapters);
2563 WineD3D_ReleaseFakeGLContext();
2564 return FALSE;
2566 ret = initPixelFormats(&Adapters[0].gl_info);
2567 if(!ret) {
2568 ERR("Failed to init gl formats\n");
2569 HeapFree(GetProcessHeap(), 0, Adapters);
2570 WineD3D_ReleaseFakeGLContext();
2571 return FALSE;
2574 hdc = pwglGetCurrentDC();
2575 if(!hdc) {
2576 ERR("Failed to get gl HDC\n");
2577 HeapFree(GetProcessHeap(), 0, Adapters);
2578 WineD3D_ReleaseFakeGLContext();
2579 return FALSE;
2582 Adapters[0].driver = "Display";
2583 Adapters[0].description = "Direct3D HAL";
2585 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2586 DisplayDevice.cb = sizeof(DisplayDevice);
2587 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2588 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2589 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2591 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2592 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2594 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2595 cfgs = Adapters[0].cfgs;
2596 PUSH1(WGL_RED_BITS_ARB)
2597 PUSH1(WGL_GREEN_BITS_ARB)
2598 PUSH1(WGL_BLUE_BITS_ARB)
2599 PUSH1(WGL_ALPHA_BITS_ARB)
2600 PUSH1(WGL_DEPTH_BITS_ARB)
2601 PUSH1(WGL_STENCIL_BITS_ARB)
2603 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2604 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
2606 if(!res)
2607 continue;
2609 /* Cache the pixel format */
2610 cfgs->iPixelFormat = iPixelFormat;
2611 cfgs->redSize = values[0];
2612 cfgs->greenSize = values[1];
2613 cfgs->blueSize = values[2];
2614 cfgs->alphaSize = values[3];
2615 cfgs->depthSize = values[4];
2616 cfgs->stencilSize = values[5];
2618 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);
2619 cfgs++;
2621 WineD3D_ReleaseFakeGLContext();
2623 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2624 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2627 numAdapters = 1;
2628 TRACE("%d adapters successfully initialized\n", numAdapters);
2630 return TRUE;
2632 #undef PUSH1
2633 #undef GLINFO_LOCATION
2635 /**********************************************************
2636 * IWineD3D VTbl follows
2637 **********************************************************/
2639 const IWineD3DVtbl IWineD3D_Vtbl =
2641 /* IUnknown */
2642 IWineD3DImpl_QueryInterface,
2643 IWineD3DImpl_AddRef,
2644 IWineD3DImpl_Release,
2645 /* IWineD3D */
2646 IWineD3DImpl_GetParent,
2647 IWineD3DImpl_GetAdapterCount,
2648 IWineD3DImpl_RegisterSoftwareDevice,
2649 IWineD3DImpl_GetAdapterMonitor,
2650 IWineD3DImpl_GetAdapterModeCount,
2651 IWineD3DImpl_EnumAdapterModes,
2652 IWineD3DImpl_GetAdapterDisplayMode,
2653 IWineD3DImpl_GetAdapterIdentifier,
2654 IWineD3DImpl_CheckDeviceMultiSampleType,
2655 IWineD3DImpl_CheckDepthStencilMatch,
2656 IWineD3DImpl_CheckDeviceType,
2657 IWineD3DImpl_CheckDeviceFormat,
2658 IWineD3DImpl_CheckDeviceFormatConversion,
2659 IWineD3DImpl_GetDeviceCaps,
2660 IWineD3DImpl_CreateDevice