wined3d: Properly setup DevModeW before using it.
[wine/wine-kai.git] / dlls / wined3d / directx.c
bloba0d7dd1d358b87f6c27a78de59924f36b00fb9b2
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
29 #endif
32 #include "config.h"
33 #include <assert.h>
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 /* Extension detection */
40 static const struct {
41 const char *extension_string;
42 GL_SupportedExt extension;
43 } EXTENSION_MAP[] = {
44 /* APPLE */
45 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE},
46 {"GL_APPLE_fence", APPLE_FENCE},
48 /* ATI */
49 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL},
50 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3},
51 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE},
52 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP},
54 /* ARB */
55 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS},
56 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM},
57 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER},
58 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL},
59 {"GL_ARB_imaging", ARB_IMAGING},
60 {"GL_ARB_multisample", ARB_MULTISAMPLE}, /* needs GLX_ARB_MULTISAMPLE as well */
61 {"GL_ARB_multitexture", ARB_MULTITEXTURE},
62 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY},
63 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT},
64 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS},
65 {"GL_ARB_point_sprite", ARB_POINT_SPRITE},
66 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP},
67 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION},
68 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP},
69 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD},
70 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE},
71 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3},
72 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT},
73 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT},
74 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO},
75 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND},
76 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT},
77 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM},
78 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER},
80 /* EXT */
81 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX},
82 {"GL_EXT_fog_coord", EXT_FOG_COORD},
83 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT},
84 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT},
85 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE},
86 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS},
87 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR},
88 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE},
89 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP},
90 {"GL_EXT_texture3D", EXT_TEXTURE3D},
91 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC},
92 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD},
93 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE},
94 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3},
95 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB},
96 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC},
97 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD},
98 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS},
99 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER},
100 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING},
102 /* NV */
103 {"GL_NV_half_float", NV_HALF_FLOAT},
104 {"GL_NV_fence", NV_FENCE},
105 {"GL_NV_fog_distance", NV_FOG_DISTANCE},
106 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM},
107 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2},
108 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS},
109 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2},
110 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION},
111 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4},
112 {"GL_NV_texture_shader", NV_TEXTURE_SHADER},
113 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2},
114 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3},
115 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY},
116 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM},
117 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1},
118 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2},
119 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3},
122 /**********************************************************
123 * Utility functions follow
124 **********************************************************/
126 /* x11drv GDI escapes */
127 #define X11DRV_ESCAPE 6789
128 enum x11drv_escape_codes
130 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
131 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
132 X11DRV_GET_FONT, /* get current X font for a DC */
135 /* retrieve the X display to use on a given DC */
136 static inline Display *get_display( HDC hdc )
138 Display *display;
139 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
141 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
142 sizeof(display), (LPSTR)&display )) display = NULL;
143 return display;
146 /* Adapters */
147 static int numAdapters = 0;
148 static struct WineD3DAdapter Adapters[1];
150 /* lookup tables */
151 int minLookup[MAX_LOOKUPS];
152 int maxLookup[MAX_LOOKUPS];
153 DWORD *stateLookup[MAX_LOOKUPS];
155 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
159 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
160 * ie there is no GL Context - Get a default rendering context to enable the
161 * function query some info from GL
164 static int wined3d_fake_gl_context_ref = 0;
165 static BOOL wined3d_fake_gl_context_foreign;
166 static BOOL wined3d_fake_gl_context_available = FALSE;
167 static Display* wined3d_fake_gl_context_display = NULL;
169 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
170 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
172 0, 0, &wined3d_fake_gl_context_cs,
173 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
174 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
175 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
177 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
179 static void WineD3D_ReleaseFakeGLContext(void) {
180 GLXContext glCtx;
182 EnterCriticalSection(&wined3d_fake_gl_context_cs);
184 if(!wined3d_fake_gl_context_available) {
185 TRACE_(d3d_caps)("context not available\n");
186 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
187 return;
190 glCtx = glXGetCurrentContext();
192 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
193 if (0 == (--wined3d_fake_gl_context_ref) ) {
194 if(!wined3d_fake_gl_context_foreign && glCtx) {
195 TRACE_(d3d_caps)("destroying fake GL context\n");
196 glXMakeCurrent(wined3d_fake_gl_context_display, None, NULL);
197 glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
199 wined3d_fake_gl_context_available = FALSE;
201 assert(wined3d_fake_gl_context_ref >= 0);
203 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
204 LEAVE_GL();
207 static BOOL WineD3D_CreateFakeGLContext(void) {
208 XVisualInfo* visInfo;
209 GLXContext glCtx;
211 ENTER_GL();
212 EnterCriticalSection(&wined3d_fake_gl_context_cs);
214 TRACE_(d3d_caps)("getting context...\n");
215 if(wined3d_fake_gl_context_ref > 0) goto ret;
216 assert(0 == wined3d_fake_gl_context_ref);
218 wined3d_fake_gl_context_foreign = TRUE;
220 if(!wined3d_fake_gl_context_display) {
221 HDC device_context = GetDC(0);
223 wined3d_fake_gl_context_display = get_display(device_context);
224 ReleaseDC(0, device_context);
227 visInfo = NULL;
228 glCtx = glXGetCurrentContext();
230 if (!glCtx) {
231 Drawable drawable;
232 XVisualInfo template;
233 Visual* visual;
234 int num;
235 XWindowAttributes win_attr;
237 wined3d_fake_gl_context_foreign = FALSE;
238 drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
240 TRACE_(d3d_caps)("Creating Fake GL Context\n");
242 /* Get the X visual */
243 if (XGetWindowAttributes(wined3d_fake_gl_context_display, drawable, &win_attr)) {
244 visual = win_attr.visual;
245 } else {
246 visual = DefaultVisual(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display));
248 template.visualid = XVisualIDFromVisual(visual);
249 visInfo = XGetVisualInfo(wined3d_fake_gl_context_display, VisualIDMask, &template, &num);
250 if (!visInfo) {
251 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
252 goto fail;
255 /* Create a GL context */
256 glCtx = glXCreateContext(wined3d_fake_gl_context_display, visInfo, NULL, GL_TRUE);
257 if (!glCtx) {
258 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
259 goto fail;
262 /* Make it the current GL context */
263 if (!glXMakeCurrent(wined3d_fake_gl_context_display, drawable, glCtx)) {
264 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
265 goto fail;
268 XFree(visInfo);
272 ret:
273 TRACE_(d3d_caps)("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
274 wined3d_fake_gl_context_ref++;
275 wined3d_fake_gl_context_available = TRUE;
276 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
277 return TRUE;
278 fail:
279 if(visInfo) XFree(visInfo);
280 if(glCtx) glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
281 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
282 LEAVE_GL();
283 return FALSE;
286 /**********************************************************
287 * IUnknown parts follows
288 **********************************************************/
290 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
292 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
294 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
295 if (IsEqualGUID(riid, &IID_IUnknown)
296 || IsEqualGUID(riid, &IID_IWineD3DBase)
297 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
298 IUnknown_AddRef(iface);
299 *ppobj = This;
300 return S_OK;
302 *ppobj = NULL;
303 return E_NOINTERFACE;
306 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
307 IWineD3DImpl *This = (IWineD3DImpl *)iface;
308 ULONG refCount = InterlockedIncrement(&This->ref);
310 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
311 return refCount;
314 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
315 IWineD3DImpl *This = (IWineD3DImpl *)iface;
316 ULONG ref;
317 TRACE("(%p) : Releasing from %d\n", This, This->ref);
318 ref = InterlockedDecrement(&This->ref);
319 if (ref == 0) {
320 HeapFree(GetProcessHeap(), 0, This);
323 return ref;
326 /* Set the shader type for this device, depending on the given capabilities,
327 * the device type, and the user preferences in wined3d_settings */
329 static void select_shader_mode(
330 WineD3D_GL_Info *gl_info,
331 WINED3DDEVTYPE DeviceType,
332 int* ps_selected,
333 int* vs_selected) {
335 if (wined3d_settings.vs_mode == VS_NONE) {
336 *vs_selected = SHADER_NONE;
337 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
338 *vs_selected = SHADER_GLSL;
339 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
340 *vs_selected = SHADER_ARB;
341 } else {
342 *vs_selected = SHADER_NONE;
345 if (wined3d_settings.ps_mode == PS_NONE) {
346 *ps_selected = SHADER_NONE;
347 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
348 *ps_selected = SHADER_GLSL;
349 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
350 *ps_selected = SHADER_ARB;
351 } else {
352 *ps_selected = SHADER_NONE;
356 /** Select the number of report maximum shader constants based on the selected shader modes */
357 static void select_shader_max_constants(
358 int ps_selected_mode,
359 int vs_selected_mode,
360 WineD3D_GL_Info *gl_info) {
362 switch (vs_selected_mode) {
363 case SHADER_GLSL:
364 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
365 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
366 break;
367 case SHADER_ARB:
368 /* We have to subtract any other PARAMs that we might use in our shader programs.
369 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
370 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
371 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
372 break;
373 default:
374 gl_info->max_vshader_constantsF = 0;
375 break;
378 switch (ps_selected_mode) {
379 case SHADER_GLSL:
380 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
381 * In theory the texbem instruction may need one more shader constant too. But lets assume
382 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
383 * and lets not take away a uniform needlessly from all other shaders.
385 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
386 break;
387 case SHADER_ARB:
388 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
389 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
391 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
392 break;
393 default:
394 gl_info->max_pshader_constantsF = 0;
395 break;
399 /**********************************************************
400 * IWineD3D parts follows
401 **********************************************************/
403 #define GLINFO_LOCATION (*gl_info)
404 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info, Display* display) {
405 const char *GL_Extensions = NULL;
406 const char *GLX_Extensions = NULL;
407 const char *gl_string = NULL;
408 const char *gl_string_cursor = NULL;
409 GLint gl_max;
410 GLfloat gl_floatv[2];
411 Bool test = 0;
412 int major, minor;
413 BOOL return_value = TRUE;
414 int i;
416 /* Make sure that we've got a context */
417 /* TODO: CreateFakeGLContext should really take a display as a parameter */
418 /* Only save the values obtained when a display is provided */
419 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
420 return_value = FALSE;
422 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
424 gl_string = (const char *) glGetString(GL_RENDERER);
425 if (NULL == gl_string)
426 gl_string = "None";
427 strcpy(gl_info->gl_renderer, gl_string);
429 /* Fill in the GL info retrievable depending on the display */
430 if (NULL != display) {
431 test = glXQueryVersion(display, &major, &minor);
432 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
433 } else {
434 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
436 gl_string = (const char *) glGetString(GL_VENDOR);
438 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
439 if (gl_string != NULL) {
440 /* Fill in the GL vendor */
441 if (strstr(gl_string, "NVIDIA")) {
442 gl_info->gl_vendor = VENDOR_NVIDIA;
443 } else if (strstr(gl_string, "ATI")) {
444 gl_info->gl_vendor = VENDOR_ATI;
445 } else if (strstr(gl_string, "Intel(R)") ||
446 strstr(gl_info->gl_renderer, "Intel(R)")) {
447 gl_info->gl_vendor = VENDOR_INTEL;
448 } else if (strstr(gl_string, "Mesa")) {
449 gl_info->gl_vendor = VENDOR_MESA;
450 } else {
451 gl_info->gl_vendor = VENDOR_WINE;
453 } else {
454 gl_info->gl_vendor = VENDOR_WINE;
458 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
460 /* Parse the GL_VERSION field into major and minor information */
461 gl_string = (const char *) glGetString(GL_VERSION);
462 if (gl_string != NULL) {
464 switch (gl_info->gl_vendor) {
465 case VENDOR_NVIDIA:
466 gl_string_cursor = strstr(gl_string, "NVIDIA");
467 if (!gl_string_cursor) {
468 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
469 break;
472 gl_string_cursor = strstr(gl_string_cursor, " ");
473 if (!gl_string_cursor) {
474 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
475 break;
478 while (*gl_string_cursor == ' ') {
479 ++gl_string_cursor;
482 if (!*gl_string_cursor) {
483 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
484 break;
487 major = atoi(gl_string_cursor);
488 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
489 ++gl_string_cursor;
492 if (*gl_string_cursor++ != '.') {
493 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
494 break;
497 minor = atoi(gl_string_cursor);
498 minor = major*100+minor;
499 major = 10;
501 break;
503 case VENDOR_ATI:
504 major = minor = 0;
505 gl_string_cursor = strchr(gl_string, '-');
506 if (gl_string_cursor) {
507 int error = 0;
508 gl_string_cursor++;
510 /* Check if version number is of the form x.y.z */
511 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
512 error = 1;
513 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
514 error = 1;
515 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
516 error = 1;
517 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
518 error = 1;
520 /* Mark version number as malformed */
521 if (error)
522 gl_string_cursor = 0;
525 if (!gl_string_cursor)
526 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
527 else {
528 major = *gl_string_cursor - '0';
529 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
531 break;
533 case VENDOR_INTEL:
534 case VENDOR_MESA:
535 gl_string_cursor = strstr(gl_string, "Mesa");
536 gl_string_cursor = strstr(gl_string_cursor, " ");
537 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
538 if (*gl_string_cursor) {
539 char tmp[16];
540 int cursor = 0;
542 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
543 tmp[cursor++] = *gl_string_cursor;
544 ++gl_string_cursor;
546 tmp[cursor] = 0;
547 major = atoi(tmp);
549 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
550 ++gl_string_cursor;
552 cursor = 0;
553 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
554 tmp[cursor++] = *gl_string_cursor;
555 ++gl_string_cursor;
557 tmp[cursor] = 0;
558 minor = atoi(tmp);
560 break;
562 default:
563 major = 0;
564 minor = 9;
566 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
567 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
570 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
573 * Initialize openGL extension related variables
574 * with Default values
576 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
577 gl_info->max_buffers = 1;
578 gl_info->max_textures = 1;
579 gl_info->max_texture_stages = 1;
580 gl_info->max_fragment_samplers = 1;
581 gl_info->max_vertex_samplers = 0;
582 gl_info->max_combined_samplers = 0;
583 gl_info->max_sampler_stages = 1;
584 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
585 gl_info->ps_arb_max_temps = 0;
586 gl_info->ps_arb_max_instructions = 0;
587 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
588 gl_info->vs_arb_max_temps = 0;
589 gl_info->vs_arb_max_instructions = 0;
590 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
591 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
592 gl_info->vs_glsl_constantsF = 0;
593 gl_info->ps_glsl_constantsF = 0;
594 gl_info->vs_arb_constantsF = 0;
595 gl_info->ps_arb_constantsF = 0;
597 /* Now work out what GL support this card really has */
598 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
599 GL_EXT_FUNCS_GEN;
600 GLX_EXT_FUNCS_GEN;
601 #undef USE_GL_FUNC
603 /* Retrieve opengl defaults */
604 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
605 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
606 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
608 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
609 gl_info->max_lights = gl_max;
610 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
612 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
613 gl_info->max_texture_size = gl_max;
614 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
616 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
617 gl_info->max_pointsize = gl_floatv[1];
618 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
620 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
621 gl_info->max_aux_buffers = gl_max;
622 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
624 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
625 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
626 TRACE_(d3d_caps)("GL_Extensions reported:\n");
628 if (NULL == GL_Extensions) {
629 ERR(" GL_Extensions returns NULL\n");
630 } else {
631 while (*GL_Extensions != 0x00) {
632 const char *Start = GL_Extensions;
633 char ThisExtn[256];
635 memset(ThisExtn, 0x00, sizeof(ThisExtn));
636 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
637 GL_Extensions++;
639 memcpy(ThisExtn, Start, (GL_Extensions - Start));
640 TRACE_(d3d_caps)("- %s\n", ThisExtn);
642 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
643 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
644 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
645 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
646 break;
650 if (*GL_Extensions == ' ') GL_Extensions++;
653 if (gl_info->supported[APPLE_FENCE]) {
654 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
655 * The apple extension interacts with some other apple exts. Disable the NV
656 * extension if the apple one is support to prevent confusion in other parts
657 * of the code
659 gl_info->supported[NV_FENCE] = FALSE;
661 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
662 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
663 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
665 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
666 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
667 * Won't occur in any real world situation though
669 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
671 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
672 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
673 gl_info->max_buffers = gl_max;
674 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
676 if (gl_info->supported[ARB_MULTITEXTURE]) {
677 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
678 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
679 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
681 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
682 GLint tmp;
683 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
684 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
685 } else {
686 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
688 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
690 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
691 GLint tmp;
692 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
693 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
694 } else {
695 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
697 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
699 if (gl_info->supported[ARB_VERTEX_SHADER]) {
700 GLint tmp;
701 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
702 gl_info->max_vertex_samplers = tmp;
703 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
704 gl_info->max_combined_samplers = tmp;
705 } else {
706 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
708 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
709 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
711 if (gl_info->supported[ARB_VERTEX_BLEND]) {
712 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
713 gl_info->max_blends = gl_max;
714 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
716 if (gl_info->supported[EXT_TEXTURE3D]) {
717 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
718 gl_info->max_texture3d_size = gl_max;
719 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
721 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
722 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
723 gl_info->max_anisotropy = gl_max;
724 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
726 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
727 gl_info->ps_arb_version = PS_VERSION_11;
728 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
729 gl_info->ps_arb_constantsF = gl_max;
730 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
731 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
732 gl_info->ps_arb_max_temps = gl_max;
733 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info->ps_arb_max_temps);
734 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
735 gl_info->ps_arb_max_instructions = gl_max;
736 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info->ps_arb_max_instructions);
738 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
739 gl_info->vs_arb_version = VS_VERSION_11;
740 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
741 gl_info->vs_arb_constantsF = gl_max;
742 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
743 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
744 gl_info->vs_arb_max_temps = gl_max;
745 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info->vs_arb_max_temps);
746 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
747 gl_info->vs_arb_max_instructions = gl_max;
748 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info->vs_arb_max_instructions);
750 if (gl_info->supported[ARB_VERTEX_SHADER]) {
751 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
752 gl_info->vs_glsl_constantsF = gl_max / 4;
753 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
755 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
756 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
757 gl_info->ps_glsl_constantsF = gl_max / 4;
758 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
760 if (gl_info->supported[EXT_VERTEX_SHADER]) {
761 gl_info->vs_ati_version = VS_VERSION_11;
763 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
764 gl_info->vs_nv_version = VS_VERSION_30;
765 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
766 gl_info->vs_nv_version = VS_VERSION_20;
767 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
768 gl_info->vs_nv_version = VS_VERSION_11;
769 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
770 gl_info->vs_nv_version = VS_VERSION_10;
772 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
773 gl_info->ps_nv_version = PS_VERSION_30;
774 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
775 gl_info->ps_nv_version = PS_VERSION_20;
779 checkGLcall("extension detection\n");
781 /* In some cases the number of texture stages can be larger than the number
782 * of samplers. The GF4 for example can use only 2 samplers (no fragment
783 * shaders), but 8 texture stages (register combiners). */
784 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
786 /* We can only use ORM_FBO when the hardware supports it. */
787 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
788 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
789 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
792 /* MRTs are currently only supported when FBOs are used. */
793 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
794 gl_info->max_buffers = 1;
797 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
798 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
799 * in case of the latest videocards in the number of pixel/vertex pipelines.
801 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
802 * rendering. Various games use this information to get a rough estimation of the features of the card
803 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
804 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
805 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
806 * not the PCI id.
808 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
809 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
810 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
811 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
812 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
813 * is used for rendering which is not always the case). This would work but it is not very portable. Second
814 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
815 * is limited.
817 * As said most games only use the PCI id to get an indication of the capabilities of the card.
818 * It doesn't really matter if the given id is the correct one if we return the id of a card with
819 * similar 3d features.
821 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
822 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
823 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
824 * won't pass we return a default card. This way is better than maintaining a full card database as even
825 * without a full database we can return a card with similar features. Second the size of the database
826 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
827 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
828 * to distinguishes between different models from that family.
830 switch (gl_info->gl_vendor) {
831 case VENDOR_NVIDIA:
832 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
833 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
835 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
836 if (strstr(gl_info->gl_renderer, "7800") ||
837 strstr(gl_info->gl_renderer, "7900") ||
838 strstr(gl_info->gl_renderer, "7950") ||
839 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
840 strstr(gl_info->gl_renderer, "Quadro FX 5"))
841 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
842 else if(strstr(gl_info->gl_renderer, "6800") ||
843 strstr(gl_info->gl_renderer, "7600"))
844 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
845 else if(strstr(gl_info->gl_renderer, "6600") ||
846 strstr(gl_info->gl_renderer, "6610") ||
847 strstr(gl_info->gl_renderer, "6700"))
848 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
849 else
850 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
851 } else if(WINE_D3D9_CAPABLE(gl_info)) {
852 if (strstr(gl_info->gl_renderer, "5800") ||
853 strstr(gl_info->gl_renderer, "5900") ||
854 strstr(gl_info->gl_renderer, "5950") ||
855 strstr(gl_info->gl_renderer, "Quadro FX"))
856 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
857 else if(strstr(gl_info->gl_renderer, "5600") ||
858 strstr(gl_info->gl_renderer, "5650") ||
859 strstr(gl_info->gl_renderer, "5700") ||
860 strstr(gl_info->gl_renderer, "5750"))
861 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
862 else
863 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
864 } else if(WINE_D3D8_CAPABLE(gl_info)) {
865 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
866 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
867 else
868 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
869 } else if(WINE_D3D7_CAPABLE(gl_info)) {
870 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
871 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
872 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
873 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
874 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
875 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
876 else
877 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
878 } else {
879 if (strstr(gl_info->gl_renderer, "TNT2"))
880 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
881 else
882 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
884 break;
885 case VENDOR_ATI:
886 if(WINE_D3D9_CAPABLE(gl_info)) {
887 /* Radeon R5xx */
888 if (strstr(gl_info->gl_renderer, "X1600") ||
889 strstr(gl_info->gl_renderer, "X1800") ||
890 strstr(gl_info->gl_renderer, "X1900") ||
891 strstr(gl_info->gl_renderer, "X1950"))
892 gl_info->gl_card = CARD_ATI_RADEON_X1600;
893 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
894 else if(strstr(gl_info->gl_renderer, "X700") ||
895 strstr(gl_info->gl_renderer, "X800") ||
896 strstr(gl_info->gl_renderer, "X850") ||
897 strstr(gl_info->gl_renderer, "X1300") ||
898 strstr(gl_info->gl_renderer, "X1400"))
899 gl_info->gl_card = CARD_ATI_RADEON_X700;
900 /* Radeon R3xx */
901 else
902 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
903 } else if(WINE_D3D8_CAPABLE(gl_info)) {
904 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
905 } else if(WINE_D3D7_CAPABLE(gl_info)) {
906 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
907 } else
908 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
909 break;
910 case VENDOR_INTEL:
911 if (strstr(gl_info->gl_renderer, "915GM")) {
912 gl_info->gl_card = CARD_INTEL_I915GM;
913 } else if (strstr(gl_info->gl_renderer, "915G")) {
914 gl_info->gl_card = CARD_INTEL_I915G;
915 } else if (strstr(gl_info->gl_renderer, "865G")) {
916 gl_info->gl_card = CARD_INTEL_I865G;
917 } else if (strstr(gl_info->gl_renderer, "855G")) {
918 gl_info->gl_card = CARD_INTEL_I855G;
919 } else if (strstr(gl_info->gl_renderer, "830G")) {
920 gl_info->gl_card = CARD_INTEL_I830G;
921 } else {
922 gl_info->gl_card = CARD_INTEL_I915G;
924 break;
925 case VENDOR_MESA:
926 case VENDOR_WINE:
927 default:
928 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
929 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
930 * them a good generic choice.
932 gl_info->gl_vendor = VENDOR_NVIDIA;
933 if(WINE_D3D9_CAPABLE(gl_info))
934 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
935 else if(WINE_D3D8_CAPABLE(gl_info))
936 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
937 else if(WINE_D3D7_CAPABLE(gl_info))
938 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
939 else if(WINE_D3D6_CAPABLE(gl_info))
940 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
941 else
942 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
944 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
946 /* Load all the lookup tables
947 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
948 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
949 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
951 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
952 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
955 for (i = 0; i < MAX_LOOKUPS; i++) {
956 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
959 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
960 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
961 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
962 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
963 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
964 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
965 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
966 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
967 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
968 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
970 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
971 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
972 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
973 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
974 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
977 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
978 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
979 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
980 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
981 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
982 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
983 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
984 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
985 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
986 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
987 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
988 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
989 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
991 /* TODO: config lookups */
993 if (display != NULL) {
994 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
995 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
997 if (NULL == GLX_Extensions) {
998 ERR(" GLX_Extensions returns NULL\n");
999 } else {
1000 while (*GLX_Extensions != 0x00) {
1001 const char *Start = GLX_Extensions;
1002 char ThisExtn[256];
1004 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1005 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1006 GLX_Extensions++;
1008 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1009 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1010 if (strstr(ThisExtn, "GLX_SGI_video_sync")) {
1011 gl_info->supported[SGI_VIDEO_SYNC] = TRUE;
1014 if (*GLX_Extensions == ' ') GLX_Extensions++;
1020 WineD3D_ReleaseFakeGLContext();
1021 return return_value;
1023 #undef GLINFO_LOCATION
1025 /**********************************************************
1026 * IWineD3D implementation follows
1027 **********************************************************/
1029 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1030 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1032 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1033 return numAdapters;
1036 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1037 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1038 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1039 return WINED3D_OK;
1042 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1043 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1045 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1046 return NULL;
1049 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1050 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1053 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1054 of the same bpp but different resolutions */
1056 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1057 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1058 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1059 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1061 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1062 return 0;
1065 /* TODO: Store modes per adapter and read it from the adapter structure */
1066 if (Adapter == 0) { /* Display */
1067 int i = 0;
1068 int j = 0;
1070 if (!DEBUG_SINGLE_MODE) {
1071 DEVMODEW DevModeW;
1073 ZeroMemory(&DevModeW, sizeof(DevModeW));
1074 DevModeW.dmSize = sizeof(DevModeW);
1075 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1076 j++;
1077 switch (Format)
1079 case WINED3DFMT_UNKNOWN:
1080 /* This is for D3D8, do not enumerate P8 here */
1081 if (DevModeW.dmBitsPerPel == 32 ||
1082 DevModeW.dmBitsPerPel == 16) i++;
1083 break;
1084 case WINED3DFMT_X8R8G8B8:
1085 if (DevModeW.dmBitsPerPel == 32) i++;
1086 break;
1087 case WINED3DFMT_R5G6B5:
1088 if (DevModeW.dmBitsPerPel == 16) i++;
1089 break;
1090 case WINED3DFMT_P8:
1091 if (DevModeW.dmBitsPerPel == 8) i++;
1092 break;
1093 default:
1094 /* Skip other modes as they do not match the requested format */
1095 break;
1098 } else {
1099 i = 1;
1100 j = 1;
1103 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1104 return i;
1105 } else {
1106 FIXME_(d3d_caps)("Adapter not primary display\n");
1108 return 0;
1111 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1112 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1113 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1114 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1116 /* Validate the parameters as much as possible */
1117 if (NULL == pMode ||
1118 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1119 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1120 return WINED3DERR_INVALIDCALL;
1123 /* TODO: Store modes per adapter and read it from the adapter structure */
1124 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1125 DEVMODEW DevModeW;
1126 int ModeIdx = 0;
1127 int i = 0;
1128 int j = 0;
1130 ZeroMemory(&DevModeW, sizeof(DevModeW));
1131 DevModeW.dmSize = sizeof(DevModeW);
1133 /* If we are filtering to a specific format (D3D9), then need to skip
1134 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1135 just count through the ones with valid bit depths */
1136 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1137 switch (Format)
1139 case WINED3DFMT_UNKNOWN:
1140 /* This is D3D8. Do not enumerate P8 here */
1141 if (DevModeW.dmBitsPerPel == 32 ||
1142 DevModeW.dmBitsPerPel == 16) i++;
1143 break;
1144 case WINED3DFMT_X8R8G8B8:
1145 if (DevModeW.dmBitsPerPel == 32) i++;
1146 break;
1147 case WINED3DFMT_R5G6B5:
1148 if (DevModeW.dmBitsPerPel == 16) i++;
1149 break;
1150 case WINED3DFMT_P8:
1151 if (DevModeW.dmBitsPerPel == 8) i++;
1152 break;
1153 default:
1154 /* Modes that don't match what we support can get an early-out */
1155 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1156 return WINED3DERR_INVALIDCALL;
1160 if (i == 0) {
1161 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1162 return WINED3DERR_INVALIDCALL;
1164 ModeIdx = j - 1;
1166 /* Now get the display mode via the calculated index */
1167 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1168 pMode->Width = DevModeW.dmPelsWidth;
1169 pMode->Height = DevModeW.dmPelsHeight;
1170 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1171 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1172 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1174 if (Format == WINED3DFMT_UNKNOWN)
1176 switch (DevModeW.dmBitsPerPel)
1178 case 8:
1179 pMode->Format = WINED3DFMT_P8;
1180 break;
1181 case 16:
1182 pMode->Format = WINED3DFMT_R5G6B5;
1183 break;
1184 case 32:
1185 pMode->Format = WINED3DFMT_X8R8G8B8;
1186 break;
1187 default:
1188 pMode->Format = WINED3DFMT_UNKNOWN;
1189 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1191 } else {
1192 pMode->Format = Format;
1194 } else {
1195 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1196 return WINED3DERR_INVALIDCALL;
1199 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1200 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1201 DevModeW.dmBitsPerPel);
1203 } else if (DEBUG_SINGLE_MODE) {
1204 /* Return one setting of the format requested */
1205 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1206 pMode->Width = 800;
1207 pMode->Height = 600;
1208 pMode->RefreshRate = 60;
1209 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1210 } else {
1211 FIXME_(d3d_caps)("Adapter not primary display\n");
1214 return WINED3D_OK;
1217 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1218 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1219 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1221 if (NULL == pMode ||
1222 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1223 return WINED3DERR_INVALIDCALL;
1226 if (Adapter == 0) { /* Display */
1227 int bpp = 0;
1228 DEVMODEW DevModeW;
1230 ZeroMemory(&DevModeW, sizeof(DevModeW));
1231 DevModeW.dmSize = sizeof(DevModeW);
1233 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1234 pMode->Width = DevModeW.dmPelsWidth;
1235 pMode->Height = DevModeW.dmPelsHeight;
1236 bpp = DevModeW.dmBitsPerPel;
1237 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1238 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1240 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1243 switch (bpp) {
1244 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1245 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1246 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1247 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1248 default: pMode->Format = WINED3DFMT_UNKNOWN;
1251 } else {
1252 FIXME_(d3d_caps)("Adapter not primary display\n");
1255 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1256 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1257 return WINED3D_OK;
1260 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1261 and fields being inserted in the middle, a new structure is used in place */
1262 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1263 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1264 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1266 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1268 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1269 return WINED3DERR_INVALIDCALL;
1272 /* Return the information requested */
1273 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1274 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1275 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1277 /* Note dx8 doesn't supply a DeviceName */
1278 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1279 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1280 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1281 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1282 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1283 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1284 *(pIdentifier->SubSysId) = 0;
1285 *(pIdentifier->Revision) = 0;
1287 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1288 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1289 *(pIdentifier->WHQLLevel) = 0;
1290 } else {
1291 *(pIdentifier->WHQLLevel) = 1;
1294 return WINED3D_OK;
1297 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1298 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1299 int gl_test;
1300 int rb, gb, bb, ab, type, buf_sz;
1302 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1303 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1304 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1305 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1306 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1307 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1309 switch (Format) {
1310 case WINED3DFMT_X8R8G8B8:
1311 case WINED3DFMT_R8G8B8:
1312 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1313 break;
1314 case WINED3DFMT_A8R8G8B8:
1315 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1316 break;
1317 case WINED3DFMT_A2R10G10B10:
1318 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1319 break;
1320 case WINED3DFMT_X1R5G5B5:
1321 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1322 break;
1323 case WINED3DFMT_A1R5G5B5:
1324 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1325 break;
1326 case WINED3DFMT_X4R4G4B4:
1327 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1328 break;
1329 case WINED3DFMT_R5G6B5:
1330 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1331 break;
1332 case WINED3DFMT_R3G3B2:
1333 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1334 break;
1335 case WINED3DFMT_A8P8:
1336 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1337 break;
1338 case WINED3DFMT_P8:
1339 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1340 break;
1341 default:
1342 break;
1344 return FALSE;
1345 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1346 switch (Format) {
1347 case WINED3DFMT_X8R8G8B8:
1348 case WINED3DFMT_R8G8B8:
1349 case WINED3DFMT_A8R8G8B8:
1350 case WINED3DFMT_A2R10G10B10:
1351 case WINED3DFMT_X1R5G5B5:
1352 case WINED3DFMT_A1R5G5B5:
1353 case WINED3DFMT_R5G6B5:
1354 case WINED3DFMT_R3G3B2:
1355 case WINED3DFMT_A8P8:
1356 case WINED3DFMT_P8:
1357 return TRUE;
1358 default:
1359 break;
1361 return FALSE;
1362 #endif
1365 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1366 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1367 int gl_test;
1368 int db, sb;
1370 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1371 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1373 switch (Format) {
1374 case WINED3DFMT_D16:
1375 case WINED3DFMT_D16_LOCKABLE:
1376 if (16 == db) return TRUE;
1377 break;
1378 case WINED3DFMT_D32:
1379 if (32 == db) return TRUE;
1380 break;
1381 case WINED3DFMT_D15S1:
1382 if (15 == db) return TRUE;
1383 break;
1384 case WINED3DFMT_D24S8:
1385 if (24 == db && 8 == sb) return TRUE;
1386 break;
1387 case WINED3DFMT_D24FS8:
1388 if (24 == db && 8 == sb) return TRUE;
1389 break;
1390 case WINED3DFMT_D24X8:
1391 if (24 == db) return TRUE;
1392 break;
1393 case WINED3DFMT_D24X4S4:
1394 if (24 == db && 4 == sb) return TRUE;
1395 break;
1396 case WINED3DFMT_D32F_LOCKABLE:
1397 if (32 == db) return TRUE;
1398 break;
1399 default:
1400 break;
1402 return FALSE;
1403 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1404 switch (Format) {
1405 case WINED3DFMT_D16:
1406 case WINED3DFMT_D16_LOCKABLE:
1407 case WINED3DFMT_D32:
1408 case WINED3DFMT_D15S1:
1409 case WINED3DFMT_D24S8:
1410 case WINED3DFMT_D24FS8:
1411 case WINED3DFMT_D24X8:
1412 case WINED3DFMT_D24X4S4:
1413 case WINED3DFMT_D32F_LOCKABLE:
1414 return TRUE;
1415 default:
1416 break;
1418 return FALSE;
1419 #endif
1422 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1423 WINED3DFORMAT AdapterFormat,
1424 WINED3DFORMAT RenderTargetFormat,
1425 WINED3DFORMAT DepthStencilFormat) {
1426 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1427 int it;
1429 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1430 This, Adapter,
1431 DeviceType, debug_d3ddevicetype(DeviceType),
1432 AdapterFormat, debug_d3dformat(AdapterFormat),
1433 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1434 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1436 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1437 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1438 return WINED3DERR_INVALIDCALL;
1441 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
1442 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Adapters[Adapter].display, Adapters[Adapter].cfgs[it], RenderTargetFormat)) {
1443 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Adapters[Adapter].display, Adapters[Adapter].cfgs[it], DepthStencilFormat)) {
1444 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1445 return WINED3D_OK;
1449 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1451 return WINED3DERR_NOTAVAILABLE;
1454 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1455 WINED3DFORMAT SurfaceFormat,
1456 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1458 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1459 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1460 This,
1461 Adapter,
1462 DeviceType, debug_d3ddevicetype(DeviceType),
1463 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1464 Windowed,
1465 MultiSampleType,
1466 pQualityLevels);
1468 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1469 return WINED3DERR_INVALIDCALL;
1472 /* TODO: Store in Adapter structure */
1473 if (pQualityLevels != NULL) {
1474 static int s_single_shot = 0;
1475 if (!s_single_shot) {
1476 FIXME("Quality levels unsupported at present\n");
1477 s_single_shot = 1;
1479 *pQualityLevels = 1; /* Guess at a value! */
1482 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1483 return WINED3DERR_NOTAVAILABLE;
1486 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1487 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1489 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1490 GLXFBConfig* cfgs = NULL;
1491 int nCfgs = 0;
1492 int it;
1493 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1495 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1496 This,
1497 Adapter,
1498 CheckType, debug_d3ddevicetype(CheckType),
1499 DisplayFormat, debug_d3dformat(DisplayFormat),
1500 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1501 Windowed);
1503 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1504 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1505 return WINED3DERR_INVALIDCALL;
1508 /* TODO: Store in adapter structure */
1509 if (WineD3D_CreateFakeGLContext()) {
1510 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1511 for (it = 0; it < nCfgs; ++it) {
1512 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1513 hr = WINED3D_OK;
1514 TRACE_(d3d_caps)("OK\n");
1515 break ;
1518 if(cfgs) XFree(cfgs);
1519 if(hr != WINED3D_OK)
1520 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1521 WineD3D_ReleaseFakeGLContext();
1524 if(hr != WINED3D_OK)
1525 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1527 return hr;
1530 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1531 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1532 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1533 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1534 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1535 This,
1536 Adapter,
1537 DeviceType, debug_d3ddevicetype(DeviceType),
1538 AdapterFormat, debug_d3dformat(AdapterFormat),
1539 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1540 RType, debug_d3dresourcetype(RType),
1541 CheckFormat, debug_d3dformat(CheckFormat));
1543 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1544 return WINED3DERR_INVALIDCALL;
1547 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1548 switch (CheckFormat) {
1549 /* Filtering not supported */
1550 case WINED3DFMT_A32B32G32R32F:
1551 TRACE_(d3d_caps)("[FAILED]\n");
1552 return WINED3DERR_NOTAVAILABLE;
1553 default:
1554 break;
1558 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1559 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1560 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1561 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1562 if (!GL_LIMITS(vertex_samplers)) {
1563 TRACE_(d3d_caps)("[FAILED]\n");
1564 return WINED3DERR_NOTAVAILABLE;
1567 switch (CheckFormat) {
1568 case WINED3DFMT_A32B32G32R32F:
1569 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1570 TRACE_(d3d_caps)("[FAILED]\n");
1571 return WINED3DERR_NOTAVAILABLE;
1573 TRACE_(d3d_caps)("[OK]\n");
1574 return WINED3D_OK;
1576 default:
1577 TRACE_(d3d_caps)("[FAILED]\n");
1578 return WINED3DERR_NOTAVAILABLE;
1582 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1583 switch (CheckFormat) {
1584 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1585 * Windows supports only those 3, and enumerating the other formats confuses applications
1587 case WINED3DFMT_D24S8:
1588 case WINED3DFMT_D24X8:
1589 case WINED3DFMT_D16:
1590 TRACE_(d3d_caps)("[OK]\n");
1591 return WINED3D_OK;
1592 case WINED3DFMT_D16_LOCKABLE:
1593 case WINED3DFMT_D24FS8:
1594 case WINED3DFMT_D32F_LOCKABLE:
1595 case WINED3DFMT_D24X4S4:
1596 case WINED3DFMT_D15S1:
1597 case WINED3DFMT_D32:
1598 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1599 return WINED3DERR_NOTAVAILABLE;
1600 default:
1601 TRACE_(d3d_caps)("[FAILED]\n");
1602 return WINED3DERR_NOTAVAILABLE;
1604 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1605 switch (CheckFormat) {
1606 case WINED3DFMT_R8G8B8:
1607 case WINED3DFMT_A8R8G8B8:
1608 case WINED3DFMT_X8R8G8B8:
1609 case WINED3DFMT_R5G6B5:
1610 case WINED3DFMT_X1R5G5B5:
1611 case WINED3DFMT_A1R5G5B5:
1612 case WINED3DFMT_A4R4G4B4:
1613 case WINED3DFMT_R3G3B2:
1614 case WINED3DFMT_X4R4G4B4:
1615 case WINED3DFMT_A8B8G8R8:
1616 case WINED3DFMT_X8B8G8R8:
1617 case WINED3DFMT_P8:
1618 TRACE_(d3d_caps)("[OK]\n");
1619 return WINED3D_OK;
1620 case WINED3DFMT_R16F:
1621 case WINED3DFMT_A16B16G16R16F:
1622 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1623 TRACE_(d3d_caps)("[FAILED]\n");
1624 return WINED3DERR_NOTAVAILABLE;
1626 TRACE_(d3d_caps)("[OK]\n");
1627 return WINED3D_OK;
1628 case WINED3DFMT_A32B32G32R32F:
1629 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1630 TRACE_(d3d_caps)("[FAILED]\n");
1631 return WINED3DERR_NOTAVAILABLE;
1633 TRACE_(d3d_caps)("[OK]\n");
1634 return WINED3D_OK;
1635 default:
1636 TRACE_(d3d_caps)("[FAILED]\n");
1637 return WINED3DERR_NOTAVAILABLE;
1639 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1640 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1641 switch (CheckFormat) {
1642 case WINED3DFMT_V8U8:
1643 TRACE_(d3d_caps)("[OK]\n");
1644 return WINED3D_OK;
1645 /* TODO: Other bump map formats */
1646 default:
1647 TRACE_(d3d_caps)("[FAILED]\n");
1648 return WINED3DERR_NOTAVAILABLE;
1651 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1652 switch (CheckFormat) {
1653 case WINED3DFMT_V8U8:
1654 TRACE_(d3d_caps)("[OK]\n");
1655 return WINED3D_OK;
1656 default:
1657 TRACE_(d3d_caps)("[FAILED]\n");
1658 return WINED3DERR_NOTAVAILABLE;
1661 TRACE_(d3d_caps)("[FAILED]\n");
1662 return WINED3DERR_NOTAVAILABLE;
1665 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1666 switch (CheckFormat) {
1667 case WINED3DFMT_DXT1:
1668 case WINED3DFMT_DXT2:
1669 case WINED3DFMT_DXT3:
1670 case WINED3DFMT_DXT4:
1671 case WINED3DFMT_DXT5:
1672 TRACE_(d3d_caps)("[OK]\n");
1673 return WINED3D_OK;
1674 default:
1675 break; /* Avoid compiler warnings */
1679 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1680 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1681 switch (CheckFormat) {
1682 case WINED3DFMT_A8R8G8B8:
1683 case WINED3DFMT_X8R8G8B8:
1684 case WINED3DFMT_A4R4G4B4:
1685 case WINED3DFMT_L8:
1686 case WINED3DFMT_A8L8:
1687 case WINED3DFMT_DXT1:
1688 case WINED3DFMT_DXT2:
1689 case WINED3DFMT_DXT3:
1690 case WINED3DFMT_DXT4:
1691 case WINED3DFMT_DXT5:
1692 TRACE_(d3d_caps)("[OK]\n");
1693 return WINED3D_OK;
1695 default:
1696 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1697 return WINED3DERR_NOTAVAILABLE;
1701 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1703 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1705 switch (CheckFormat) {
1706 case WINED3DFMT_R16F:
1707 case WINED3DFMT_A16B16G16R16F:
1708 if (!half_pixel_support) break;
1709 case WINED3DFMT_R32F:
1710 case WINED3DFMT_A32B32G32R32F:
1711 TRACE_(d3d_caps)("[OK]\n");
1712 return WINED3D_OK;
1713 default:
1714 break; /* Avoid compiler warnings */
1718 /* This format is nothing special and it is supported perfectly.
1719 * However, ati and nvidia driver on windows do not mark this format as
1720 * supported (tested with the dxCapsViewer) and pretending to
1721 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1722 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1723 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1725 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1726 TRACE_(d3d_caps)("[FAILED]\n");
1727 return WINED3DERR_NOTAVAILABLE;
1730 switch (CheckFormat) {
1732 /*****
1733 * supported: RGB(A) formats
1735 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1736 case WINED3DFMT_A8R8G8B8:
1737 case WINED3DFMT_X8R8G8B8:
1738 case WINED3DFMT_R5G6B5:
1739 case WINED3DFMT_X1R5G5B5:
1740 case WINED3DFMT_A1R5G5B5:
1741 case WINED3DFMT_A4R4G4B4:
1742 case WINED3DFMT_R3G3B2:
1743 case WINED3DFMT_A8:
1744 case WINED3DFMT_A8R3G3B2:
1745 case WINED3DFMT_X4R4G4B4:
1746 case WINED3DFMT_A8B8G8R8:
1747 case WINED3DFMT_X8B8G8R8:
1748 case WINED3DFMT_A2R10G10B10:
1749 case WINED3DFMT_A2B10G10R10:
1750 TRACE_(d3d_caps)("[OK]\n");
1751 return WINED3D_OK;
1753 /*****
1754 * supported: Palettized
1756 case WINED3DFMT_P8:
1757 TRACE_(d3d_caps)("[OK]\n");
1758 return WINED3D_OK;
1760 /*****
1761 * Supported: (Alpha)-Luminance
1763 case WINED3DFMT_L8:
1764 case WINED3DFMT_A8L8:
1765 case WINED3DFMT_A4L4:
1766 TRACE_(d3d_caps)("[OK]\n");
1767 return WINED3D_OK;
1769 /*****
1770 * Not supported for now: Bump mapping formats
1771 * Enable some because games often fail when they are not available
1772 * and are still playable even without bump mapping
1774 case WINED3DFMT_V8U8:
1775 case WINED3DFMT_V16U16:
1776 case WINED3DFMT_L6V5U5:
1777 case WINED3DFMT_X8L8V8U8:
1778 case WINED3DFMT_Q8W8V8U8:
1779 case WINED3DFMT_W11V11U10:
1780 case WINED3DFMT_A2W10V10U10:
1781 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1782 return WINED3D_OK;
1784 /*****
1785 * DXTN Formats: Handled above
1786 * WINED3DFMT_DXT1
1787 * WINED3DFMT_DXT2
1788 * WINED3DFMT_DXT3
1789 * WINED3DFMT_DXT4
1790 * WINED3DFMT_DXT5
1793 /*****
1794 * Odd formats - not supported
1796 case WINED3DFMT_VERTEXDATA:
1797 case WINED3DFMT_INDEX16:
1798 case WINED3DFMT_INDEX32:
1799 case WINED3DFMT_Q16W16V16U16:
1800 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1801 return WINED3DERR_NOTAVAILABLE;
1803 /*****
1804 * Float formats: Not supported right now
1806 case WINED3DFMT_G16R16F:
1807 case WINED3DFMT_G32R32F:
1808 case WINED3DFMT_CxV8U8:
1809 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1810 return WINED3DERR_NOTAVAILABLE;
1812 /* Not supported */
1813 case WINED3DFMT_G16R16:
1814 case WINED3DFMT_A16B16G16R16:
1815 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1816 return WINED3DERR_NOTAVAILABLE;
1818 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1819 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1820 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1821 * We can do instancing with all shader versions, but we need vertex shaders.
1823 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1824 * to enable instancing. WineD3D doesn't need that and just ignores it.
1826 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1828 case WINEMAKEFOURCC('I','N','S','T'):
1829 TRACE("ATI Instancing check hack\n");
1830 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1831 TRACE_(d3d_caps)("[OK]\n");
1832 return WINED3D_OK;
1833 } else {
1834 TRACE_(d3d_caps)("[FAILED]\n");
1835 return WINED3DERR_NOTAVAILABLE;
1838 default:
1839 break;
1842 TRACE_(d3d_caps)("[FAILED]\n");
1843 return WINED3DERR_NOTAVAILABLE;
1846 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1847 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1848 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1850 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1851 This,
1852 Adapter,
1853 DeviceType, debug_d3ddevicetype(DeviceType),
1854 SourceFormat, debug_d3dformat(SourceFormat),
1855 TargetFormat, debug_d3dformat(TargetFormat));
1856 return WINED3D_OK;
1859 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1860 subset of a D3DCAPS9 structure. However, it has to come via a void *
1861 as the d3d8 interface cannot import the d3d9 header */
1862 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1864 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1865 int vs_selected_mode;
1866 int ps_selected_mode;
1868 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1870 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1871 return WINED3DERR_INVALIDCALL;
1874 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1876 /* This function should *not* be modifying GL caps
1877 * TODO: move the functionality where it belongs */
1878 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1880 /* ------------------------------------------------
1881 The following fields apply to both d3d8 and d3d9
1882 ------------------------------------------------ */
1883 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1884 *pCaps->AdapterOrdinal = Adapter;
1886 *pCaps->Caps = 0;
1887 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1888 WINED3DCAPS2_FULLSCREENGAMMA |
1889 WINED3DCAPS2_DYNAMICTEXTURES;
1890 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1891 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1893 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1894 WINED3DCURSORCAPS_LOWRES;
1896 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1897 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1898 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1899 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1900 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1901 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1902 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1903 WINED3DDEVCAPS_PUREDEVICE |
1904 WINED3DDEVCAPS_HWRASTERIZATION |
1905 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1906 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1907 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1908 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1909 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1910 WINED3DDEVCAPS_RTPATCHES;
1912 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1913 WINED3DPMISCCAPS_CULLCCW |
1914 WINED3DPMISCCAPS_CULLCW |
1915 WINED3DPMISCCAPS_COLORWRITEENABLE |
1916 WINED3DPMISCCAPS_CLIPTLVERTS |
1917 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1918 WINED3DPMISCCAPS_MASKZ |
1919 WINED3DPMISCCAPS_BLENDOP;
1920 /* TODO:
1921 WINED3DPMISCCAPS_NULLREFERENCE
1922 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1923 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1924 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1925 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1926 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1927 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1929 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1930 #if 0
1931 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1932 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1933 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1934 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1935 #endif
1937 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1938 WINED3DPRASTERCAPS_PAT |
1939 WINED3DPRASTERCAPS_WFOG |
1940 WINED3DPRASTERCAPS_ZFOG |
1941 WINED3DPRASTERCAPS_FOGVERTEX |
1942 WINED3DPRASTERCAPS_FOGTABLE |
1943 WINED3DPRASTERCAPS_FOGRANGE |
1944 WINED3DPRASTERCAPS_STIPPLE |
1945 WINED3DPRASTERCAPS_SUBPIXEL |
1946 WINED3DPRASTERCAPS_ZTEST |
1947 WINED3DPRASTERCAPS_SCISSORTEST |
1948 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1949 WINED3DPRASTERCAPS_DEPTHBIAS;
1951 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1952 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1953 WINED3DPRASTERCAPS_ZBIAS |
1954 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1956 /* FIXME Add:
1957 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1958 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1959 WINED3DPRASTERCAPS_ANTIALIASEDGES
1960 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1961 WINED3DPRASTERCAPS_WBUFFER */
1963 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1964 WINED3DPCMPCAPS_EQUAL |
1965 WINED3DPCMPCAPS_GREATER |
1966 WINED3DPCMPCAPS_GREATEREQUAL |
1967 WINED3DPCMPCAPS_LESS |
1968 WINED3DPCMPCAPS_LESSEQUAL |
1969 WINED3DPCMPCAPS_NEVER |
1970 WINED3DPCMPCAPS_NOTEQUAL;
1972 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1973 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1974 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1975 WINED3DPBLENDCAPS_DESTALPHA |
1976 WINED3DPBLENDCAPS_DESTCOLOR |
1977 WINED3DPBLENDCAPS_INVDESTALPHA |
1978 WINED3DPBLENDCAPS_INVDESTCOLOR |
1979 WINED3DPBLENDCAPS_INVSRCALPHA |
1980 WINED3DPBLENDCAPS_INVSRCCOLOR |
1981 WINED3DPBLENDCAPS_ONE |
1982 WINED3DPBLENDCAPS_SRCALPHA |
1983 WINED3DPBLENDCAPS_SRCALPHASAT |
1984 WINED3DPBLENDCAPS_SRCCOLOR |
1985 WINED3DPBLENDCAPS_ZERO;
1987 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1988 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1989 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1990 WINED3DPBLENDCAPS_DESTALPHA |
1991 WINED3DPBLENDCAPS_DESTCOLOR |
1992 WINED3DPBLENDCAPS_INVDESTALPHA |
1993 WINED3DPBLENDCAPS_INVDESTCOLOR |
1994 WINED3DPBLENDCAPS_INVSRCALPHA |
1995 WINED3DPBLENDCAPS_INVSRCCOLOR |
1996 WINED3DPBLENDCAPS_ONE |
1997 WINED3DPBLENDCAPS_SRCALPHA |
1998 WINED3DPBLENDCAPS_SRCALPHASAT |
1999 WINED3DPBLENDCAPS_SRCCOLOR |
2000 WINED3DPBLENDCAPS_ZERO;
2002 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2003 WINED3DPCMPCAPS_EQUAL |
2004 WINED3DPCMPCAPS_GREATER |
2005 WINED3DPCMPCAPS_GREATEREQUAL |
2006 WINED3DPCMPCAPS_LESS |
2007 WINED3DPCMPCAPS_LESSEQUAL |
2008 WINED3DPCMPCAPS_NEVER |
2009 WINED3DPCMPCAPS_NOTEQUAL;
2011 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2012 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2013 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2014 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2015 WINED3DPSHADECAPS_COLORFLATRGB |
2016 WINED3DPSHADECAPS_FOGFLAT |
2017 WINED3DPSHADECAPS_FOGGOURAUD |
2018 WINED3DPSHADECAPS_SPECULARFLATRGB;
2020 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2021 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2022 WINED3DPTEXTURECAPS_BORDER |
2023 WINED3DPTEXTURECAPS_MIPMAP |
2024 WINED3DPTEXTURECAPS_PROJECTED |
2025 WINED3DPTEXTURECAPS_PERSPECTIVE |
2026 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2028 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2029 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2030 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2031 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2034 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2035 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2036 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2037 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2041 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2042 WINED3DPTFILTERCAPS_MAGFPOINT |
2043 WINED3DPTFILTERCAPS_MINFLINEAR |
2044 WINED3DPTFILTERCAPS_MINFPOINT |
2045 WINED3DPTFILTERCAPS_MIPFLINEAR |
2046 WINED3DPTFILTERCAPS_MIPFPOINT |
2047 WINED3DPTFILTERCAPS_LINEAR |
2048 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2049 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2050 WINED3DPTFILTERCAPS_MIPLINEAR |
2051 WINED3DPTFILTERCAPS_MIPNEAREST |
2052 WINED3DPTFILTERCAPS_NEAREST;
2054 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2055 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2056 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2059 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2060 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2061 WINED3DPTFILTERCAPS_MAGFPOINT |
2062 WINED3DPTFILTERCAPS_MINFLINEAR |
2063 WINED3DPTFILTERCAPS_MINFPOINT |
2064 WINED3DPTFILTERCAPS_MIPFLINEAR |
2065 WINED3DPTFILTERCAPS_MIPFPOINT |
2066 WINED3DPTFILTERCAPS_LINEAR |
2067 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2068 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2069 WINED3DPTFILTERCAPS_MIPLINEAR |
2070 WINED3DPTFILTERCAPS_MIPNEAREST |
2071 WINED3DPTFILTERCAPS_NEAREST;
2073 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2074 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2075 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2077 } else
2078 *pCaps->CubeTextureFilterCaps = 0;
2080 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2081 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2082 WINED3DPTFILTERCAPS_MAGFPOINT |
2083 WINED3DPTFILTERCAPS_MINFLINEAR |
2084 WINED3DPTFILTERCAPS_MINFPOINT |
2085 WINED3DPTFILTERCAPS_MIPFLINEAR |
2086 WINED3DPTFILTERCAPS_MIPFPOINT |
2087 WINED3DPTFILTERCAPS_LINEAR |
2088 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2089 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2090 WINED3DPTFILTERCAPS_MIPLINEAR |
2091 WINED3DPTFILTERCAPS_MIPNEAREST |
2092 WINED3DPTFILTERCAPS_NEAREST;
2093 } else
2094 *pCaps->VolumeTextureFilterCaps = 0;
2096 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2097 WINED3DPTADDRESSCAPS_CLAMP |
2098 WINED3DPTADDRESSCAPS_WRAP;
2100 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2101 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2103 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2104 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2106 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2107 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2110 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2111 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2112 WINED3DPTADDRESSCAPS_CLAMP |
2113 WINED3DPTADDRESSCAPS_WRAP;
2114 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2115 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2117 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2118 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2120 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2121 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2123 } else
2124 *pCaps->VolumeTextureAddressCaps = 0;
2126 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2127 WINED3DLINECAPS_ZTEST;
2128 /* FIXME: Add
2129 WINED3DLINECAPS_BLEND
2130 WINED3DLINECAPS_ALPHACMP
2131 WINED3DLINECAPS_FOG */
2133 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2134 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2136 if(GL_SUPPORT(EXT_TEXTURE3D))
2137 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2138 else
2139 *pCaps->MaxVolumeExtent = 0;
2141 *pCaps->MaxTextureRepeat = 32768;
2142 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2143 *pCaps->MaxVertexW = 1.0;
2145 *pCaps->GuardBandLeft = 0;
2146 *pCaps->GuardBandTop = 0;
2147 *pCaps->GuardBandRight = 0;
2148 *pCaps->GuardBandBottom = 0;
2150 *pCaps->ExtentsAdjust = 0;
2152 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2153 WINED3DSTENCILCAPS_INCRSAT |
2154 WINED3DSTENCILCAPS_INVERT |
2155 WINED3DSTENCILCAPS_KEEP |
2156 WINED3DSTENCILCAPS_REPLACE |
2157 WINED3DSTENCILCAPS_ZERO;
2158 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2159 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2160 WINED3DSTENCILCAPS_INCR;
2162 if ( This->dxVersion > 8 &&
2163 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2164 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2165 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2168 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2170 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2171 WINED3DTEXOPCAPS_ADDSIGNED |
2172 WINED3DTEXOPCAPS_ADDSIGNED2X |
2173 WINED3DTEXOPCAPS_MODULATE |
2174 WINED3DTEXOPCAPS_MODULATE2X |
2175 WINED3DTEXOPCAPS_MODULATE4X |
2176 WINED3DTEXOPCAPS_SELECTARG1 |
2177 WINED3DTEXOPCAPS_SELECTARG2 |
2178 WINED3DTEXOPCAPS_DISABLE;
2180 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2181 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2182 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2183 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2184 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2185 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2186 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2187 WINED3DTEXOPCAPS_LERP |
2188 WINED3DTEXOPCAPS_SUBTRACT;
2190 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2191 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2192 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2193 WINED3DTEXOPCAPS_MULTIPLYADD |
2194 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2195 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2196 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2198 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2199 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2201 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2202 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2203 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2206 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2207 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2208 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2209 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2210 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2211 * and 3D textures. It also allows us to keep the code simpler by having texture
2212 * shaders constantly enabled.
2214 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2215 /* TODO: Luminance bump map? */
2217 #if 0
2218 /* FIXME: Add
2219 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2220 WINED3DTEXOPCAPS_PREMODULATE */
2221 #endif
2223 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2224 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2225 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2226 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2228 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2229 *pCaps->MaxVertexBlendMatrixIndex = 0;
2231 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2232 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2235 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2236 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2237 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2238 WINED3DVTXPCAPS_LOCALVIEWER |
2239 WINED3DVTXPCAPS_VERTEXFOG |
2240 WINED3DVTXPCAPS_TEXGEN;
2241 /* FIXME: Add
2242 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2244 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2245 *pCaps->MaxVertexIndex = 0xFFFFF;
2246 *pCaps->MaxStreams = MAX_STREAMS;
2247 *pCaps->MaxStreamStride = 1024;
2249 if (vs_selected_mode == SHADER_GLSL) {
2250 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2251 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2252 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2253 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2254 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2255 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2256 else
2257 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2258 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2259 } else if (vs_selected_mode == SHADER_ARB) {
2260 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2261 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2262 } else {
2263 *pCaps->VertexShaderVersion = 0;
2264 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2267 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2269 if (ps_selected_mode == SHADER_GLSL) {
2270 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2271 in case of GeforceFX cards. */
2272 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2273 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2274 else
2275 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2276 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2277 *pCaps->PixelShader1xMaxValue = 1.0;
2278 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2279 } else if (ps_selected_mode == SHADER_ARB) {
2280 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2281 *pCaps->PixelShader1xMaxValue = 1.0;
2282 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2283 } else {
2284 *pCaps->PixelShaderVersion = 0;
2285 *pCaps->PixelShader1xMaxValue = 0.0;
2286 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2289 /* ------------------------------------------------
2290 The following fields apply to d3d9 only
2291 ------------------------------------------------ */
2292 if (This->dxVersion > 8) {
2293 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2294 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2295 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2296 *pCaps->MaxNpatchTessellationLevel = 0;
2297 *pCaps->MasterAdapterOrdinal = 0;
2298 *pCaps->AdapterOrdinalInGroup = 0;
2299 *pCaps->NumberOfAdaptersInGroup = 1;
2301 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2302 /* OpenGL supports all the formats below, perhaps not always
2303 * without conversion, but it supports them.
2304 * Further GLSL doesn't seem to have an official unsigned type so
2305 * don't advertise it yet as I'm not sure how we handle it.
2306 * We might need to add some clamping in the shader engine to
2307 * support it.
2308 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2309 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2310 WINED3DDTCAPS_UBYTE4N |
2311 WINED3DDTCAPS_SHORT2N |
2312 WINED3DDTCAPS_SHORT4N;
2313 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2314 *pCaps->DeclTypes |=
2315 WINED3DDTCAPS_FLOAT16_2 |
2316 WINED3DDTCAPS_FLOAT16_4;
2318 } else
2319 *pCaps->DeclTypes = 0;
2321 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2324 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2325 WINED3DPTFILTERCAPS_MAGFPOINT |
2326 WINED3DPTFILTERCAPS_MINFLINEAR |
2327 WINED3DPTFILTERCAPS_MAGFLINEAR;
2328 *pCaps->VertexTextureFilterCaps = 0;
2330 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2331 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2332 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2333 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2334 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2335 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2336 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2338 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2339 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2340 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2341 *pCaps->VS20Caps.Caps = 0;
2342 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2343 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2344 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2346 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2347 *pCaps->MaxVertexShader30InstructionSlots = 0;
2348 } else { /* VS 1.x */
2349 *pCaps->VS20Caps.Caps = 0;
2350 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2351 *pCaps->VS20Caps.NumTemps = 0;
2352 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2354 *pCaps->MaxVShaderInstructionsExecuted = 0;
2355 *pCaps->MaxVertexShader30InstructionSlots = 0;
2358 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2359 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2360 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2362 /* 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 */
2363 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2364 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2365 WINED3DPS20CAPS_PREDICATION |
2366 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2367 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2368 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2369 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2370 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2371 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2373 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2374 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2375 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2376 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2377 *pCaps->PS20Caps.Caps = 0;
2378 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2379 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2380 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2381 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2383 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2384 *pCaps->MaxPixelShader30InstructionSlots = 0;
2385 } else { /* PS 1.x */
2386 *pCaps->PS20Caps.Caps = 0;
2387 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2388 *pCaps->PS20Caps.NumTemps = 0;
2389 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2390 *pCaps->PS20Caps.NumInstructionSlots = 0;
2392 *pCaps->MaxPShaderInstructionsExecuted = 0;
2393 *pCaps->MaxPixelShader30InstructionSlots = 0;
2397 return WINED3D_OK;
2400 static unsigned int glsl_program_key_hash(void *key) {
2401 glsl_program_key_t *k = (glsl_program_key_t *)key;
2403 unsigned int hash = k->vshader | k->pshader << 16;
2404 hash += ~(hash << 15);
2405 hash ^= (hash >> 10);
2406 hash += (hash << 3);
2407 hash ^= (hash >> 6);
2408 hash += ~(hash << 11);
2409 hash ^= (hash >> 16);
2411 return hash;
2414 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2415 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2416 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2418 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2421 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2422 and fields being inserted in the middle, a new structure is used in place */
2423 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2424 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2425 IUnknown *parent) {
2427 IWineD3DDeviceImpl *object = NULL;
2428 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2429 HDC hDC;
2430 int i;
2432 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2433 * number and create a device without a 3D adapter for 2D only operation.
2435 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2436 return WINED3DERR_INVALIDCALL;
2439 /* Create a WineD3DDevice object */
2440 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2441 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2442 TRACE("Created WineD3DDevice object @ %p\n", object);
2443 if (NULL == object) {
2444 return WINED3DERR_OUTOFVIDEOMEMORY;
2447 /* Set up initial COM information */
2448 object->lpVtbl = &IWineD3DDevice_Vtbl;
2449 object->ref = 1;
2450 object->wineD3D = iface;
2451 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2452 IWineD3D_AddRef(object->wineD3D);
2453 object->parent = parent;
2455 if(This->dxVersion == 7) {
2456 object->surface_alignment = 8;
2457 } else {
2458 object->surface_alignment = 4;
2461 /* Set the state up as invalid until the device is fully created */
2462 object->state = WINED3DERR_DRIVERINTERNALERROR;
2464 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2465 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2467 /* Save the creation parameters */
2468 object->createParms.AdapterOrdinal = Adapter;
2469 object->createParms.DeviceType = DeviceType;
2470 object->createParms.hFocusWindow = hFocusWindow;
2471 object->createParms.BehaviorFlags = BehaviourFlags;
2473 /* Initialize other useful values */
2474 object->adapterNo = Adapter;
2475 object->devType = DeviceType;
2477 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2478 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2479 object->shader_backend = &glsl_shader_backend;
2480 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2481 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2482 object->shader_backend = &arb_program_shader_backend;
2483 } else {
2484 object->shader_backend = &none_shader_backend;
2487 /* set the state of the device to valid */
2488 object->state = WINED3D_OK;
2490 /* Get the initial screen setup for ddraw */
2491 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2492 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2493 hDC = GetDC(0);
2494 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2495 ReleaseDC(0, hDC);
2497 for(i = 0; i < PATCHMAP_SIZE; i++) {
2498 list_init(&object->patches[i]);
2500 return WINED3D_OK;
2502 #undef GLINFO_LOCATION
2504 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2505 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2506 IUnknown_AddRef(This->parent);
2507 *pParent = This->parent;
2508 return WINED3D_OK;
2511 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2512 IUnknown* surfaceParent;
2513 TRACE("(%p) call back\n", pSurface);
2515 /* Now, release the parent, which will take care of cleaning up the surface for us */
2516 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2517 IUnknown_Release(surfaceParent);
2518 return IUnknown_Release(surfaceParent);
2521 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2522 IUnknown* volumeParent;
2523 TRACE("(%p) call back\n", pVolume);
2525 /* Now, release the parent, which will take care of cleaning up the volume for us */
2526 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2527 IUnknown_Release(volumeParent);
2528 return IUnknown_Release(volumeParent);
2531 BOOL InitAdapters(void) {
2532 HDC device_context;
2533 BOOL ret;
2534 int ps_selected_mode, vs_selected_mode;
2536 /* No need to hold any lock. The calling library makes sure only one thread calls
2537 * wined3d simultaneously
2539 if(numAdapters > 0) return TRUE;
2541 TRACE("Initializing adapters\n");
2542 /* For now only one default adapter */
2544 TRACE("Initializing default adapter\n");
2545 Adapters[0].monitorPoint.x = -1;
2546 Adapters[0].monitorPoint.y = -1;
2548 device_context = GetDC(0);
2549 Adapters[0].display = get_display(device_context);
2550 ReleaseDC(0, device_context);
2552 ENTER_GL();
2553 if(WineD3D_CreateFakeGLContext()) {
2554 Adapters[0].cfgs = glXGetFBConfigs(Adapters[0].display, DefaultScreen(Adapters[0].display), &Adapters[0].nCfgs);
2555 WineD3D_ReleaseFakeGLContext();
2556 } else {
2557 ERR("Failed to create a fake opengl context to find fbconfigs formats\n");
2558 LEAVE_GL();
2559 return FALSE;
2561 LEAVE_GL();
2563 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info, Adapters[0].display);
2564 if(!ret) {
2565 ERR("Failed to initialize gl caps for default adapter\n");
2566 XFree(Adapters[0].cfgs);
2567 HeapFree(GetProcessHeap(), 0, Adapters);
2568 return FALSE;
2570 ret = initPixelFormats(&Adapters[0].gl_info);
2571 if(!ret) {
2572 ERR("Failed to init gl formats\n");
2573 XFree(Adapters[0].cfgs);
2574 HeapFree(GetProcessHeap(), 0, Adapters);
2575 return FALSE;
2578 Adapters[0].driver = "Display";
2579 Adapters[0].description = "Direct3D HAL";
2581 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2582 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2585 numAdapters = 1;
2586 TRACE("%d adapters successfully initialized\n", numAdapters);
2588 return TRUE;
2592 /**********************************************************
2593 * IWineD3D VTbl follows
2594 **********************************************************/
2596 const IWineD3DVtbl IWineD3D_Vtbl =
2598 /* IUnknown */
2599 IWineD3DImpl_QueryInterface,
2600 IWineD3DImpl_AddRef,
2601 IWineD3DImpl_Release,
2602 /* IWineD3D */
2603 IWineD3DImpl_GetParent,
2604 IWineD3DImpl_GetAdapterCount,
2605 IWineD3DImpl_RegisterSoftwareDevice,
2606 IWineD3DImpl_GetAdapterMonitor,
2607 IWineD3DImpl_GetAdapterModeCount,
2608 IWineD3DImpl_EnumAdapterModes,
2609 IWineD3DImpl_GetAdapterDisplayMode,
2610 IWineD3DImpl_GetAdapterIdentifier,
2611 IWineD3DImpl_CheckDeviceMultiSampleType,
2612 IWineD3DImpl_CheckDepthStencilMatch,
2613 IWineD3DImpl_CheckDeviceType,
2614 IWineD3DImpl_CheckDeviceFormat,
2615 IWineD3DImpl_CheckDeviceFormatConversion,
2616 IWineD3DImpl_GetDeviceCaps,
2617 IWineD3DImpl_CreateDevice