wined3d: Find the shader constant limit at adapter init time.
[wine/multimedia.git] / dlls / wined3d / directx.c
blob86eb0cc8874c3cd60e9ccfbe935ef997dc53a329
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_fence", NV_FENCE},
104 {"GL_NV_fog_distance", NV_FOG_DISTANCE},
105 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM},
106 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2},
107 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS},
108 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2},
109 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION},
110 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4},
111 {"GL_NV_texture_shader", NV_TEXTURE_SHADER},
112 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2},
113 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3},
114 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY},
115 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM},
116 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1},
117 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2},
118 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3},
121 /**********************************************************
122 * Utility functions follow
123 **********************************************************/
125 /* x11drv GDI escapes */
126 #define X11DRV_ESCAPE 6789
127 enum x11drv_escape_codes
129 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
130 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
131 X11DRV_GET_FONT, /* get current X font for a DC */
134 /* retrieve the X display to use on a given DC */
135 static inline Display *get_display( HDC hdc )
137 Display *display;
138 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
140 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
141 sizeof(display), (LPSTR)&display )) display = NULL;
142 return display;
145 /* Adapters */
146 static int numAdapters = 0;
147 static struct WineD3DAdapter Adapters[1];
149 /* lookup tables */
150 int minLookup[MAX_LOOKUPS];
151 int maxLookup[MAX_LOOKUPS];
152 DWORD *stateLookup[MAX_LOOKUPS];
154 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
158 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
159 * ie there is no GL Context - Get a default rendering context to enable the
160 * function query some info from GL
163 static int wined3d_fake_gl_context_ref = 0;
164 static BOOL wined3d_fake_gl_context_foreign;
165 static BOOL wined3d_fake_gl_context_available = FALSE;
166 static Display* wined3d_fake_gl_context_display = NULL;
168 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
169 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
171 0, 0, &wined3d_fake_gl_context_cs,
172 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
173 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
174 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
176 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
178 static void WineD3D_ReleaseFakeGLContext(void) {
179 GLXContext glCtx;
181 EnterCriticalSection(&wined3d_fake_gl_context_cs);
183 if(!wined3d_fake_gl_context_available) {
184 TRACE_(d3d_caps)("context not available\n");
185 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
186 return;
189 glCtx = glXGetCurrentContext();
191 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
192 if (0 == (--wined3d_fake_gl_context_ref) ) {
193 if(!wined3d_fake_gl_context_foreign && glCtx) {
194 TRACE_(d3d_caps)("destroying fake GL context\n");
195 glXMakeCurrent(wined3d_fake_gl_context_display, None, NULL);
196 glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
198 wined3d_fake_gl_context_available = FALSE;
200 assert(wined3d_fake_gl_context_ref >= 0);
202 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
203 LEAVE_GL();
206 static BOOL WineD3D_CreateFakeGLContext(void) {
207 XVisualInfo* visInfo;
208 GLXContext glCtx;
210 ENTER_GL();
211 EnterCriticalSection(&wined3d_fake_gl_context_cs);
213 TRACE_(d3d_caps)("getting context...\n");
214 if(wined3d_fake_gl_context_ref > 0) goto ret;
215 assert(0 == wined3d_fake_gl_context_ref);
217 wined3d_fake_gl_context_foreign = TRUE;
219 if(!wined3d_fake_gl_context_display) {
220 HDC device_context = GetDC(0);
222 wined3d_fake_gl_context_display = get_display(device_context);
223 ReleaseDC(0, device_context);
226 visInfo = NULL;
227 glCtx = glXGetCurrentContext();
229 if (!glCtx) {
230 Drawable drawable;
231 XVisualInfo template;
232 Visual* visual;
233 int num;
234 XWindowAttributes win_attr;
236 wined3d_fake_gl_context_foreign = FALSE;
237 drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
239 TRACE_(d3d_caps)("Creating Fake GL Context\n");
241 /* Get the X visual */
242 if (XGetWindowAttributes(wined3d_fake_gl_context_display, drawable, &win_attr)) {
243 visual = win_attr.visual;
244 } else {
245 visual = DefaultVisual(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display));
247 template.visualid = XVisualIDFromVisual(visual);
248 visInfo = XGetVisualInfo(wined3d_fake_gl_context_display, VisualIDMask, &template, &num);
249 if (!visInfo) {
250 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
251 goto fail;
254 /* Create a GL context */
255 glCtx = glXCreateContext(wined3d_fake_gl_context_display, visInfo, NULL, GL_TRUE);
256 if (!glCtx) {
257 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
258 goto fail;
261 /* Make it the current GL context */
262 if (!glXMakeCurrent(wined3d_fake_gl_context_display, drawable, glCtx)) {
263 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
264 goto fail;
267 XFree(visInfo);
271 ret:
272 TRACE_(d3d_caps)("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
273 wined3d_fake_gl_context_ref++;
274 wined3d_fake_gl_context_available = TRUE;
275 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
276 return TRUE;
277 fail:
278 if(visInfo) XFree(visInfo);
279 if(glCtx) glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
280 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
281 LEAVE_GL();
282 return FALSE;
285 /**********************************************************
286 * IUnknown parts follows
287 **********************************************************/
289 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
291 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
293 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
294 if (IsEqualGUID(riid, &IID_IUnknown)
295 || IsEqualGUID(riid, &IID_IWineD3DBase)
296 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
297 IUnknown_AddRef(iface);
298 *ppobj = This;
299 return S_OK;
301 *ppobj = NULL;
302 return E_NOINTERFACE;
305 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
306 IWineD3DImpl *This = (IWineD3DImpl *)iface;
307 ULONG refCount = InterlockedIncrement(&This->ref);
309 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
310 return refCount;
313 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
314 IWineD3DImpl *This = (IWineD3DImpl *)iface;
315 ULONG ref;
316 TRACE("(%p) : Releasing from %d\n", This, This->ref);
317 ref = InterlockedDecrement(&This->ref);
318 if (ref == 0) {
319 HeapFree(GetProcessHeap(), 0, This);
322 return ref;
325 /* Set the shader type for this device, depending on the given capabilities,
326 * the device type, and the user preferences in wined3d_settings */
328 static void select_shader_mode(
329 WineD3D_GL_Info *gl_info,
330 WINED3DDEVTYPE DeviceType,
331 int* ps_selected,
332 int* vs_selected) {
334 if (wined3d_settings.vs_mode == VS_NONE) {
335 *vs_selected = SHADER_NONE;
336 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
337 *vs_selected = SHADER_GLSL;
338 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
339 *vs_selected = SHADER_ARB;
340 } else {
341 *vs_selected = SHADER_NONE;
344 if (wined3d_settings.ps_mode == PS_NONE) {
345 *ps_selected = SHADER_NONE;
346 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
347 *ps_selected = SHADER_GLSL;
348 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
349 *ps_selected = SHADER_ARB;
350 } else {
351 *ps_selected = SHADER_NONE;
355 /** Select the number of report maximum shader constants based on the selected shader modes */
356 static void select_shader_max_constants(
357 int ps_selected_mode,
358 int vs_selected_mode,
359 WineD3D_GL_Info *gl_info) {
361 switch (vs_selected_mode) {
362 case SHADER_GLSL:
363 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
364 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
365 break;
366 case SHADER_ARB:
367 /* We have to subtract any other PARAMs that we might use in our shader programs.
368 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
369 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
370 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
371 break;
372 default:
373 gl_info->max_vshader_constantsF = 0;
374 break;
377 switch (ps_selected_mode) {
378 case SHADER_GLSL:
379 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
380 * In theory the texbem instruction may need one more shader constant too. But lets assume
381 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
382 * and lets not take away a uniform needlessly from all other shaders.
384 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
385 break;
386 case SHADER_ARB:
387 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
388 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
390 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
391 break;
392 default:
393 gl_info->max_pshader_constantsF = 0;
394 break;
398 /**********************************************************
399 * IWineD3D parts follows
400 **********************************************************/
402 #define GLINFO_LOCATION (*gl_info)
403 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info, Display* display) {
404 const char *GL_Extensions = NULL;
405 const char *GLX_Extensions = NULL;
406 const char *gl_string = NULL;
407 const char *gl_string_cursor = NULL;
408 GLint gl_max;
409 GLfloat gl_floatv[2];
410 Bool test = 0;
411 int major, minor;
412 BOOL return_value = TRUE;
413 int i;
415 /* Make sure that we've got a context */
416 /* TODO: CreateFakeGLContext should really take a display as a parameter */
417 /* Only save the values obtained when a display is provided */
418 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
419 return_value = FALSE;
421 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
423 gl_string = (const char *) glGetString(GL_RENDERER);
424 if (NULL == gl_string)
425 gl_string = "None";
426 strcpy(gl_info->gl_renderer, gl_string);
428 /* Fill in the GL info retrievable depending on the display */
429 if (NULL != display) {
430 test = glXQueryVersion(display, &major, &minor);
431 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
432 } else {
433 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
435 gl_string = (const char *) glGetString(GL_VENDOR);
437 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
438 if (gl_string != NULL) {
439 /* Fill in the GL vendor */
440 if (strstr(gl_string, "NVIDIA")) {
441 gl_info->gl_vendor = VENDOR_NVIDIA;
442 } else if (strstr(gl_string, "ATI")) {
443 gl_info->gl_vendor = VENDOR_ATI;
444 } else if (strstr(gl_string, "Intel(R)") ||
445 strstr(gl_info->gl_renderer, "Intel(R)")) {
446 gl_info->gl_vendor = VENDOR_INTEL;
447 } else if (strstr(gl_string, "Mesa")) {
448 gl_info->gl_vendor = VENDOR_MESA;
449 } else {
450 gl_info->gl_vendor = VENDOR_WINE;
452 } else {
453 gl_info->gl_vendor = VENDOR_WINE;
457 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
459 /* Parse the GL_VERSION field into major and minor information */
460 gl_string = (const char *) glGetString(GL_VERSION);
461 if (gl_string != NULL) {
463 switch (gl_info->gl_vendor) {
464 case VENDOR_NVIDIA:
465 gl_string_cursor = strstr(gl_string, "NVIDIA");
466 if (!gl_string_cursor) {
467 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
468 break;
471 gl_string_cursor = strstr(gl_string_cursor, " ");
472 if (!gl_string_cursor) {
473 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
474 break;
477 while (*gl_string_cursor == ' ') {
478 ++gl_string_cursor;
481 if (!*gl_string_cursor) {
482 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
483 break;
486 major = atoi(gl_string_cursor);
487 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
488 ++gl_string_cursor;
491 if (*gl_string_cursor++ != '.') {
492 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
493 break;
496 minor = atoi(gl_string_cursor);
497 minor = major*100+minor;
498 major = 10;
500 break;
502 case VENDOR_ATI:
503 major = minor = 0;
504 gl_string_cursor = strchr(gl_string, '-');
505 if (gl_string_cursor) {
506 int error = 0;
507 gl_string_cursor++;
509 /* Check if version number is of the form x.y.z */
510 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
511 error = 1;
512 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
513 error = 1;
514 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
515 error = 1;
516 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
517 error = 1;
519 /* Mark version number as malformed */
520 if (error)
521 gl_string_cursor = 0;
524 if (!gl_string_cursor)
525 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
526 else {
527 major = *gl_string_cursor - '0';
528 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
530 break;
532 case VENDOR_INTEL:
533 case VENDOR_MESA:
534 gl_string_cursor = strstr(gl_string, "Mesa");
535 gl_string_cursor = strstr(gl_string_cursor, " ");
536 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
537 if (*gl_string_cursor) {
538 char tmp[16];
539 int cursor = 0;
541 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
542 tmp[cursor++] = *gl_string_cursor;
543 ++gl_string_cursor;
545 tmp[cursor] = 0;
546 major = atoi(tmp);
548 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
549 ++gl_string_cursor;
551 cursor = 0;
552 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
553 tmp[cursor++] = *gl_string_cursor;
554 ++gl_string_cursor;
556 tmp[cursor] = 0;
557 minor = atoi(tmp);
559 break;
561 default:
562 major = 0;
563 minor = 9;
565 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
566 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
569 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
572 * Initialize openGL extension related variables
573 * with Default values
575 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
576 gl_info->max_buffers = 1;
577 gl_info->max_textures = 1;
578 gl_info->max_texture_stages = 1;
579 gl_info->max_fragment_samplers = 1;
580 gl_info->max_vertex_samplers = 0;
581 gl_info->max_combined_samplers = 0;
582 gl_info->max_sampler_stages = 1;
583 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
584 gl_info->ps_arb_max_temps = 0;
585 gl_info->ps_arb_max_instructions = 0;
586 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
587 gl_info->vs_arb_max_temps = 0;
588 gl_info->vs_arb_max_instructions = 0;
589 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
590 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
591 gl_info->vs_glsl_constantsF = 0;
592 gl_info->ps_glsl_constantsF = 0;
593 gl_info->vs_arb_constantsF = 0;
594 gl_info->ps_arb_constantsF = 0;
596 /* Now work out what GL support this card really has */
597 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
598 GL_EXT_FUNCS_GEN;
599 GLX_EXT_FUNCS_GEN;
600 #undef USE_GL_FUNC
602 /* Retrieve opengl defaults */
603 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
604 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
605 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
607 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
608 gl_info->max_lights = gl_max;
609 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
611 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
612 gl_info->max_texture_size = gl_max;
613 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
615 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
616 gl_info->max_pointsize = gl_floatv[1];
617 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
619 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
620 gl_info->max_aux_buffers = gl_max;
621 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
623 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
624 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
625 TRACE_(d3d_caps)("GL_Extensions reported:\n");
627 if (NULL == GL_Extensions) {
628 ERR(" GL_Extensions returns NULL\n");
629 } else {
630 while (*GL_Extensions != 0x00) {
631 const char *Start = GL_Extensions;
632 char ThisExtn[256];
634 memset(ThisExtn, 0x00, sizeof(ThisExtn));
635 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
636 GL_Extensions++;
638 memcpy(ThisExtn, Start, (GL_Extensions - Start));
639 TRACE_(d3d_caps)("- %s\n", ThisExtn);
641 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
642 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
643 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
644 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
645 break;
649 if (*GL_Extensions == ' ') GL_Extensions++;
652 if (gl_info->supported[APPLE_FENCE]) {
653 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
654 * The apple extension interacts with some other apple exts. Disable the NV
655 * extension if the apple one is support to prevent confusion in other parts
656 * of the code
658 gl_info->supported[NV_FENCE] = FALSE;
660 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
661 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
662 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
664 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
665 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
666 * Won't occur in any real world situation though
668 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
670 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
671 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
672 gl_info->max_buffers = gl_max;
673 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
675 if (gl_info->supported[ARB_MULTITEXTURE]) {
676 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
677 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
678 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
680 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
681 GLint tmp;
682 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
683 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
684 } else {
685 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
687 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
689 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
690 GLint tmp;
691 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
692 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
693 } else {
694 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
696 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
698 if (gl_info->supported[ARB_VERTEX_SHADER]) {
699 GLint tmp;
700 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
701 gl_info->max_vertex_samplers = tmp;
702 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
703 gl_info->max_combined_samplers = tmp;
704 } else {
705 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
707 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
708 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
710 if (gl_info->supported[ARB_VERTEX_BLEND]) {
711 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
712 gl_info->max_blends = gl_max;
713 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
715 if (gl_info->supported[EXT_TEXTURE3D]) {
716 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
717 gl_info->max_texture3d_size = gl_max;
718 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
720 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
721 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
722 gl_info->max_anisotropy = gl_max;
723 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
725 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
726 gl_info->ps_arb_version = PS_VERSION_11;
727 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
728 gl_info->ps_arb_constantsF = gl_max;
729 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
730 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
731 gl_info->ps_arb_max_temps = gl_max;
732 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info->ps_arb_max_temps);
733 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
734 gl_info->ps_arb_max_instructions = gl_max;
735 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info->ps_arb_max_instructions);
737 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
738 gl_info->vs_arb_version = VS_VERSION_11;
739 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
740 gl_info->vs_arb_constantsF = gl_max;
741 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
742 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
743 gl_info->vs_arb_max_temps = gl_max;
744 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info->vs_arb_max_temps);
745 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
746 gl_info->vs_arb_max_instructions = gl_max;
747 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info->vs_arb_max_instructions);
749 if (gl_info->supported[ARB_VERTEX_SHADER]) {
750 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
751 gl_info->vs_glsl_constantsF = gl_max / 4;
752 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
754 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
755 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
756 gl_info->ps_glsl_constantsF = gl_max / 4;
757 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
759 if (gl_info->supported[EXT_VERTEX_SHADER]) {
760 gl_info->vs_ati_version = VS_VERSION_11;
762 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
763 gl_info->vs_nv_version = VS_VERSION_30;
764 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
765 gl_info->vs_nv_version = VS_VERSION_20;
766 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
767 gl_info->vs_nv_version = VS_VERSION_11;
768 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
769 gl_info->vs_nv_version = VS_VERSION_10;
771 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
772 gl_info->ps_nv_version = PS_VERSION_30;
773 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
774 gl_info->ps_nv_version = PS_VERSION_20;
778 checkGLcall("extension detection\n");
780 /* In some cases the number of texture stages can be larger than the number
781 * of samplers. The GF4 for example can use only 2 samplers (no fragment
782 * shaders), but 8 texture stages (register combiners). */
783 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
785 /* We can only use ORM_FBO when the hardware supports it. */
786 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
787 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
788 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
791 /* MRTs are currently only supported when FBOs are used. */
792 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
793 gl_info->max_buffers = 1;
796 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
797 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
798 * in case of the latest videocards in the number of pixel/vertex pipelines.
800 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
801 * rendering. Various games use this information to get a rough estimation of the features of the card
802 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
803 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
804 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
805 * not the PCI id.
807 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
808 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
809 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
810 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
811 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
812 * is used for rendering which is not always the case). This would work but it is not very portable. Second
813 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
814 * is limited.
816 * As said most games only use the PCI id to get an indication of the capabilities of the card.
817 * It doesn't really matter if the given id is the correct one if we return the id of a card with
818 * similar 3d features.
820 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
821 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
822 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
823 * won't pass we return a default card. This way is better than maintaining a full card database as even
824 * without a full database we can return a card with similar features. Second the size of the database
825 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
826 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
827 * to distinguishes between different models from that family.
829 switch (gl_info->gl_vendor) {
830 case VENDOR_NVIDIA:
831 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
832 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
834 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
835 if (strstr(gl_info->gl_renderer, "7800") ||
836 strstr(gl_info->gl_renderer, "7900") ||
837 strstr(gl_info->gl_renderer, "7950") ||
838 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
839 strstr(gl_info->gl_renderer, "Quadro FX 5"))
840 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
841 else if(strstr(gl_info->gl_renderer, "6800") ||
842 strstr(gl_info->gl_renderer, "7600"))
843 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
844 else if(strstr(gl_info->gl_renderer, "6600") ||
845 strstr(gl_info->gl_renderer, "6610") ||
846 strstr(gl_info->gl_renderer, "6700"))
847 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
848 else
849 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
850 } else if(WINE_D3D9_CAPABLE(gl_info)) {
851 if (strstr(gl_info->gl_renderer, "5800") ||
852 strstr(gl_info->gl_renderer, "5900") ||
853 strstr(gl_info->gl_renderer, "5950") ||
854 strstr(gl_info->gl_renderer, "Quadro FX"))
855 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
856 else if(strstr(gl_info->gl_renderer, "5600") ||
857 strstr(gl_info->gl_renderer, "5650") ||
858 strstr(gl_info->gl_renderer, "5700") ||
859 strstr(gl_info->gl_renderer, "5750"))
860 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
861 else
862 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
863 } else if(WINE_D3D8_CAPABLE(gl_info)) {
864 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
865 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
866 else
867 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
868 } else if(WINE_D3D7_CAPABLE(gl_info)) {
869 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
870 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
871 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
872 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
873 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
874 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
875 else
876 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
877 } else {
878 if (strstr(gl_info->gl_renderer, "TNT2"))
879 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
880 else
881 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
883 break;
884 case VENDOR_ATI:
885 if(WINE_D3D9_CAPABLE(gl_info)) {
886 /* Radeon R5xx */
887 if (strstr(gl_info->gl_renderer, "X1600") ||
888 strstr(gl_info->gl_renderer, "X1800") ||
889 strstr(gl_info->gl_renderer, "X1900") ||
890 strstr(gl_info->gl_renderer, "X1950"))
891 gl_info->gl_card = CARD_ATI_RADEON_X1600;
892 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
893 else if(strstr(gl_info->gl_renderer, "X700") ||
894 strstr(gl_info->gl_renderer, "X800") ||
895 strstr(gl_info->gl_renderer, "X850") ||
896 strstr(gl_info->gl_renderer, "X1300") ||
897 strstr(gl_info->gl_renderer, "X1400"))
898 gl_info->gl_card = CARD_ATI_RADEON_X700;
899 /* Radeon R3xx */
900 else
901 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
902 } else if(WINE_D3D8_CAPABLE(gl_info)) {
903 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
904 } else if(WINE_D3D7_CAPABLE(gl_info)) {
905 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
906 } else
907 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
908 break;
909 case VENDOR_INTEL:
910 if (strstr(gl_info->gl_renderer, "915GM")) {
911 gl_info->gl_card = CARD_INTEL_I915GM;
912 } else if (strstr(gl_info->gl_renderer, "915G")) {
913 gl_info->gl_card = CARD_INTEL_I915G;
914 } else if (strstr(gl_info->gl_renderer, "865G")) {
915 gl_info->gl_card = CARD_INTEL_I865G;
916 } else if (strstr(gl_info->gl_renderer, "855G")) {
917 gl_info->gl_card = CARD_INTEL_I855G;
918 } else if (strstr(gl_info->gl_renderer, "830G")) {
919 gl_info->gl_card = CARD_INTEL_I830G;
920 } else {
921 gl_info->gl_card = CARD_INTEL_I915G;
923 break;
924 case VENDOR_MESA:
925 case VENDOR_WINE:
926 default:
927 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
928 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
929 * them a good generic choice.
931 gl_info->gl_vendor = VENDOR_NVIDIA;
932 if(WINE_D3D9_CAPABLE(gl_info))
933 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
934 else if(WINE_D3D8_CAPABLE(gl_info))
935 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
936 else if(WINE_D3D7_CAPABLE(gl_info))
937 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
938 else if(WINE_D3D6_CAPABLE(gl_info))
939 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
940 else
941 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
943 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
945 /* Load all the lookup tables
946 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
947 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
948 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
950 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
951 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
954 for (i = 0; i < MAX_LOOKUPS; i++) {
955 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
958 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
959 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
960 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
961 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
962 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
963 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
964 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
965 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
966 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
967 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
969 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
970 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
971 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
972 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
973 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
976 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
977 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
978 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
979 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
980 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
981 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
982 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
983 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
984 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
985 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
986 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
987 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
988 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
990 /* TODO: config lookups */
992 if (display != NULL) {
993 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
994 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
996 if (NULL == GLX_Extensions) {
997 ERR(" GLX_Extensions returns NULL\n");
998 } else {
999 while (*GLX_Extensions != 0x00) {
1000 const char *Start = GLX_Extensions;
1001 char ThisExtn[256];
1003 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1004 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1005 GLX_Extensions++;
1007 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1008 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1009 if (strstr(ThisExtn, "GLX_SGI_video_sync")) {
1010 gl_info->supported[SGI_VIDEO_SYNC] = TRUE;
1013 if (*GLX_Extensions == ' ') GLX_Extensions++;
1019 WineD3D_ReleaseFakeGLContext();
1020 return return_value;
1022 #undef GLINFO_LOCATION
1024 /**********************************************************
1025 * IWineD3D implementation follows
1026 **********************************************************/
1028 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1029 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1031 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1032 return numAdapters;
1035 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1036 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1037 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1038 return WINED3D_OK;
1041 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1042 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1044 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1045 return NULL;
1048 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1049 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1052 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1053 of the same bpp but different resolutions */
1055 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1056 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1057 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1058 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1060 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1061 return 0;
1064 /* TODO: Store modes per adapter and read it from the adapter structure */
1065 if (Adapter == 0) { /* Display */
1066 int i = 0;
1067 int j = 0;
1069 if (!DEBUG_SINGLE_MODE) {
1070 DEVMODEW DevModeW;
1072 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1073 j++;
1074 switch (Format)
1076 case WINED3DFMT_UNKNOWN:
1077 /* This is for D3D8, do not enumerate P8 here */
1078 if (DevModeW.dmBitsPerPel == 32 ||
1079 DevModeW.dmBitsPerPel == 16) i++;
1080 break;
1081 case WINED3DFMT_X8R8G8B8:
1082 if (DevModeW.dmBitsPerPel == 32) i++;
1083 break;
1084 case WINED3DFMT_R5G6B5:
1085 if (DevModeW.dmBitsPerPel == 16) i++;
1086 break;
1087 case WINED3DFMT_P8:
1088 if (DevModeW.dmBitsPerPel == 8) i++;
1089 break;
1090 default:
1091 /* Skip other modes as they do not match the requested format */
1092 break;
1095 } else {
1096 i = 1;
1097 j = 1;
1100 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1101 return i;
1102 } else {
1103 FIXME_(d3d_caps)("Adapter not primary display\n");
1105 return 0;
1108 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1109 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1110 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1111 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1113 /* Validate the parameters as much as possible */
1114 if (NULL == pMode ||
1115 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1116 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1117 return WINED3DERR_INVALIDCALL;
1120 /* TODO: Store modes per adapter and read it from the adapter structure */
1121 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1122 DEVMODEW DevModeW;
1123 int ModeIdx = 0;
1124 int i = 0;
1125 int j = 0;
1127 /* If we are filtering to a specific format (D3D9), then need to skip
1128 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1129 just count through the ones with valid bit depths */
1130 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1131 switch (Format)
1133 case WINED3DFMT_UNKNOWN:
1134 /* This is D3D8. Do not enumerate P8 here */
1135 if (DevModeW.dmBitsPerPel == 32 ||
1136 DevModeW.dmBitsPerPel == 16) i++;
1137 break;
1138 case WINED3DFMT_X8R8G8B8:
1139 if (DevModeW.dmBitsPerPel == 32) i++;
1140 break;
1141 case WINED3DFMT_R5G6B5:
1142 if (DevModeW.dmBitsPerPel == 16) i++;
1143 break;
1144 case WINED3DFMT_P8:
1145 if (DevModeW.dmBitsPerPel == 8) i++;
1146 break;
1147 default:
1148 /* Modes that don't match what we support can get an early-out */
1149 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1150 return WINED3DERR_INVALIDCALL;
1154 if (i == 0) {
1155 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1156 return WINED3DERR_INVALIDCALL;
1158 ModeIdx = j - 1;
1160 /* Now get the display mode via the calculated index */
1161 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1162 pMode->Width = DevModeW.dmPelsWidth;
1163 pMode->Height = DevModeW.dmPelsHeight;
1164 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1165 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1166 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1168 if (Format == WINED3DFMT_UNKNOWN)
1170 switch (DevModeW.dmBitsPerPel)
1172 case 8:
1173 pMode->Format = WINED3DFMT_P8;
1174 break;
1175 case 16:
1176 pMode->Format = WINED3DFMT_R5G6B5;
1177 break;
1178 case 32:
1179 pMode->Format = WINED3DFMT_X8R8G8B8;
1180 break;
1181 default:
1182 pMode->Format = WINED3DFMT_UNKNOWN;
1183 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1185 } else {
1186 pMode->Format = Format;
1188 } else {
1189 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1190 return WINED3DERR_INVALIDCALL;
1193 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1194 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1195 DevModeW.dmBitsPerPel);
1197 } else if (DEBUG_SINGLE_MODE) {
1198 /* Return one setting of the format requested */
1199 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1200 pMode->Width = 800;
1201 pMode->Height = 600;
1202 pMode->RefreshRate = 60;
1203 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1204 } else {
1205 FIXME_(d3d_caps)("Adapter not primary display\n");
1208 return WINED3D_OK;
1211 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1212 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1213 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1215 if (NULL == pMode ||
1216 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1217 return WINED3DERR_INVALIDCALL;
1220 if (Adapter == 0) { /* Display */
1221 int bpp = 0;
1222 DEVMODEW DevModeW;
1224 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1225 pMode->Width = DevModeW.dmPelsWidth;
1226 pMode->Height = DevModeW.dmPelsHeight;
1227 bpp = DevModeW.dmBitsPerPel;
1228 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1229 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1231 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1234 switch (bpp) {
1235 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1236 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1237 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1238 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1239 default: pMode->Format = WINED3DFMT_UNKNOWN;
1242 } else {
1243 FIXME_(d3d_caps)("Adapter not primary display\n");
1246 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1247 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1248 return WINED3D_OK;
1251 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1252 and fields being inserted in the middle, a new structure is used in place */
1253 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1254 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1255 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1257 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1259 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1260 return WINED3DERR_INVALIDCALL;
1263 /* Return the information requested */
1264 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1265 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1266 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1268 /* Note dx8 doesn't supply a DeviceName */
1269 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1270 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1271 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1272 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1273 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1274 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1275 *(pIdentifier->SubSysId) = 0;
1276 *(pIdentifier->Revision) = 0;
1278 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1279 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1280 *(pIdentifier->WHQLLevel) = 0;
1281 } else {
1282 *(pIdentifier->WHQLLevel) = 1;
1285 return WINED3D_OK;
1288 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1289 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1290 int gl_test;
1291 int rb, gb, bb, ab, type, buf_sz;
1293 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1294 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1295 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1296 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1297 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1298 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1300 switch (Format) {
1301 case WINED3DFMT_X8R8G8B8:
1302 case WINED3DFMT_R8G8B8:
1303 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1304 break;
1305 case WINED3DFMT_A8R8G8B8:
1306 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1307 break;
1308 case WINED3DFMT_A2R10G10B10:
1309 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1310 break;
1311 case WINED3DFMT_X1R5G5B5:
1312 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1313 break;
1314 case WINED3DFMT_A1R5G5B5:
1315 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1316 break;
1317 case WINED3DFMT_X4R4G4B4:
1318 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1319 break;
1320 case WINED3DFMT_R5G6B5:
1321 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1322 break;
1323 case WINED3DFMT_R3G3B2:
1324 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1325 break;
1326 case WINED3DFMT_A8P8:
1327 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1328 break;
1329 case WINED3DFMT_P8:
1330 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1331 break;
1332 default:
1333 break;
1335 return FALSE;
1336 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1337 switch (Format) {
1338 case WINED3DFMT_X8R8G8B8:
1339 case WINED3DFMT_R8G8B8:
1340 case WINED3DFMT_A8R8G8B8:
1341 case WINED3DFMT_A2R10G10B10:
1342 case WINED3DFMT_X1R5G5B5:
1343 case WINED3DFMT_A1R5G5B5:
1344 case WINED3DFMT_R5G6B5:
1345 case WINED3DFMT_R3G3B2:
1346 case WINED3DFMT_A8P8:
1347 case WINED3DFMT_P8:
1348 return TRUE;
1349 default:
1350 break;
1352 return FALSE;
1353 #endif
1356 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1357 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1358 int gl_test;
1359 int db, sb;
1361 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1362 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1364 switch (Format) {
1365 case WINED3DFMT_D16:
1366 case WINED3DFMT_D16_LOCKABLE:
1367 if (16 == db) return TRUE;
1368 break;
1369 case WINED3DFMT_D32:
1370 if (32 == db) return TRUE;
1371 break;
1372 case WINED3DFMT_D15S1:
1373 if (15 == db) return TRUE;
1374 break;
1375 case WINED3DFMT_D24S8:
1376 if (24 == db && 8 == sb) return TRUE;
1377 break;
1378 case WINED3DFMT_D24FS8:
1379 if (24 == db && 8 == sb) return TRUE;
1380 break;
1381 case WINED3DFMT_D24X8:
1382 if (24 == db) return TRUE;
1383 break;
1384 case WINED3DFMT_D24X4S4:
1385 if (24 == db && 4 == sb) return TRUE;
1386 break;
1387 case WINED3DFMT_D32F_LOCKABLE:
1388 if (32 == db) return TRUE;
1389 break;
1390 default:
1391 break;
1393 return FALSE;
1394 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1395 switch (Format) {
1396 case WINED3DFMT_D16:
1397 case WINED3DFMT_D16_LOCKABLE:
1398 case WINED3DFMT_D32:
1399 case WINED3DFMT_D15S1:
1400 case WINED3DFMT_D24S8:
1401 case WINED3DFMT_D24FS8:
1402 case WINED3DFMT_D24X8:
1403 case WINED3DFMT_D24X4S4:
1404 case WINED3DFMT_D32F_LOCKABLE:
1405 return TRUE;
1406 default:
1407 break;
1409 return FALSE;
1410 #endif
1413 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1414 WINED3DFORMAT AdapterFormat,
1415 WINED3DFORMAT RenderTargetFormat,
1416 WINED3DFORMAT DepthStencilFormat) {
1417 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1418 int it;
1420 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1421 This, Adapter,
1422 DeviceType, debug_d3ddevicetype(DeviceType),
1423 AdapterFormat, debug_d3dformat(AdapterFormat),
1424 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1425 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1427 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1428 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1429 return WINED3DERR_INVALIDCALL;
1432 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
1433 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Adapters[Adapter].display, Adapters[Adapter].cfgs[it], RenderTargetFormat)) {
1434 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Adapters[Adapter].display, Adapters[Adapter].cfgs[it], DepthStencilFormat)) {
1435 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1436 return WINED3D_OK;
1440 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1442 return WINED3DERR_NOTAVAILABLE;
1445 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1446 WINED3DFORMAT SurfaceFormat,
1447 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1449 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1450 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1451 This,
1452 Adapter,
1453 DeviceType, debug_d3ddevicetype(DeviceType),
1454 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1455 Windowed,
1456 MultiSampleType,
1457 pQualityLevels);
1459 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1460 return WINED3DERR_INVALIDCALL;
1463 /* TODO: Store in Adapter structure */
1464 if (pQualityLevels != NULL) {
1465 static int s_single_shot = 0;
1466 if (!s_single_shot) {
1467 FIXME("Quality levels unsupported at present\n");
1468 s_single_shot = 1;
1470 *pQualityLevels = 1; /* Guess at a value! */
1473 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1474 return WINED3DERR_NOTAVAILABLE;
1477 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1478 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1480 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1481 GLXFBConfig* cfgs = NULL;
1482 int nCfgs = 0;
1483 int it;
1484 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1486 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1487 This,
1488 Adapter,
1489 CheckType, debug_d3ddevicetype(CheckType),
1490 DisplayFormat, debug_d3dformat(DisplayFormat),
1491 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1492 Windowed);
1494 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1495 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1496 return WINED3DERR_INVALIDCALL;
1499 /* TODO: Store in adapter structure */
1500 if (WineD3D_CreateFakeGLContext()) {
1501 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1502 for (it = 0; it < nCfgs; ++it) {
1503 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1504 hr = WINED3D_OK;
1505 TRACE_(d3d_caps)("OK\n");
1506 break ;
1509 if(cfgs) XFree(cfgs);
1510 if(hr != WINED3D_OK)
1511 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1512 WineD3D_ReleaseFakeGLContext();
1515 if(hr != WINED3D_OK)
1516 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1518 return hr;
1521 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1522 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1523 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1524 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1525 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1526 This,
1527 Adapter,
1528 DeviceType, debug_d3ddevicetype(DeviceType),
1529 AdapterFormat, debug_d3dformat(AdapterFormat),
1530 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1531 RType, debug_d3dresourcetype(RType),
1532 CheckFormat, debug_d3dformat(CheckFormat));
1534 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1535 return WINED3DERR_INVALIDCALL;
1538 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1539 switch (CheckFormat) {
1540 /* Filtering not supported */
1541 case WINED3DFMT_A32B32G32R32F:
1542 TRACE_(d3d_caps)("[FAILED]\n");
1543 return WINED3DERR_NOTAVAILABLE;
1544 default:
1545 break;
1549 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1550 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1551 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1552 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1553 if (!GL_LIMITS(vertex_samplers)) {
1554 TRACE_(d3d_caps)("[FAILED]\n");
1555 return WINED3DERR_NOTAVAILABLE;
1558 switch (CheckFormat) {
1559 case WINED3DFMT_A32B32G32R32F:
1560 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1561 TRACE_(d3d_caps)("[FAILED]\n");
1562 return WINED3DERR_NOTAVAILABLE;
1564 TRACE_(d3d_caps)("[OK]\n");
1565 return WINED3D_OK;
1567 default:
1568 TRACE_(d3d_caps)("[FAILED]\n");
1569 return WINED3DERR_NOTAVAILABLE;
1573 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1574 switch (CheckFormat) {
1575 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1576 * Windows supports only those 3, and enumerating the other formats confuses applications
1578 case WINED3DFMT_D24S8:
1579 case WINED3DFMT_D24X8:
1580 case WINED3DFMT_D16:
1581 TRACE_(d3d_caps)("[OK]\n");
1582 return WINED3D_OK;
1583 case WINED3DFMT_D16_LOCKABLE:
1584 case WINED3DFMT_D24FS8:
1585 case WINED3DFMT_D32F_LOCKABLE:
1586 case WINED3DFMT_D24X4S4:
1587 case WINED3DFMT_D15S1:
1588 case WINED3DFMT_D32:
1589 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1590 return WINED3DERR_NOTAVAILABLE;
1591 default:
1592 TRACE_(d3d_caps)("[FAILED]\n");
1593 return WINED3DERR_NOTAVAILABLE;
1595 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1596 switch (CheckFormat) {
1597 case WINED3DFMT_R8G8B8:
1598 case WINED3DFMT_A8R8G8B8:
1599 case WINED3DFMT_X8R8G8B8:
1600 case WINED3DFMT_R5G6B5:
1601 case WINED3DFMT_X1R5G5B5:
1602 case WINED3DFMT_A1R5G5B5:
1603 case WINED3DFMT_A4R4G4B4:
1604 case WINED3DFMT_R3G3B2:
1605 case WINED3DFMT_X4R4G4B4:
1606 case WINED3DFMT_A8B8G8R8:
1607 case WINED3DFMT_X8B8G8R8:
1608 case WINED3DFMT_P8:
1609 TRACE_(d3d_caps)("[OK]\n");
1610 return WINED3D_OK;
1611 case WINED3DFMT_R16F:
1612 case WINED3DFMT_A16B16G16R16F:
1613 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1614 TRACE_(d3d_caps)("[FAILED]\n");
1615 return WINED3DERR_NOTAVAILABLE;
1617 TRACE_(d3d_caps)("[OK]\n");
1618 return WINED3D_OK;
1619 case WINED3DFMT_A32B32G32R32F:
1620 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1621 TRACE_(d3d_caps)("[FAILED]\n");
1622 return WINED3DERR_NOTAVAILABLE;
1624 TRACE_(d3d_caps)("[OK]\n");
1625 return WINED3D_OK;
1626 default:
1627 TRACE_(d3d_caps)("[FAILED]\n");
1628 return WINED3DERR_NOTAVAILABLE;
1630 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1631 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1632 switch (CheckFormat) {
1633 case WINED3DFMT_V8U8:
1634 TRACE_(d3d_caps)("[OK]\n");
1635 return WINED3D_OK;
1636 /* TODO: Other bump map formats */
1637 default:
1638 TRACE_(d3d_caps)("[FAILED]\n");
1639 return WINED3DERR_NOTAVAILABLE;
1642 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1643 switch (CheckFormat) {
1644 case WINED3DFMT_V8U8:
1645 TRACE_(d3d_caps)("[OK]\n");
1646 return WINED3D_OK;
1647 default:
1648 TRACE_(d3d_caps)("[FAILED]\n");
1649 return WINED3DERR_NOTAVAILABLE;
1652 TRACE_(d3d_caps)("[FAILED]\n");
1653 return WINED3DERR_NOTAVAILABLE;
1656 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1657 switch (CheckFormat) {
1658 case WINED3DFMT_DXT1:
1659 case WINED3DFMT_DXT2:
1660 case WINED3DFMT_DXT3:
1661 case WINED3DFMT_DXT4:
1662 case WINED3DFMT_DXT5:
1663 TRACE_(d3d_caps)("[OK]\n");
1664 return WINED3D_OK;
1665 default:
1666 break; /* Avoid compiler warnings */
1670 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1671 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1672 switch (CheckFormat) {
1673 case WINED3DFMT_A8R8G8B8:
1674 case WINED3DFMT_X8R8G8B8:
1675 case WINED3DFMT_A4R4G4B4:
1676 case WINED3DFMT_L8:
1677 case WINED3DFMT_A8L8:
1678 case WINED3DFMT_DXT1:
1679 case WINED3DFMT_DXT2:
1680 case WINED3DFMT_DXT3:
1681 case WINED3DFMT_DXT4:
1682 case WINED3DFMT_DXT5:
1683 TRACE_(d3d_caps)("[OK]\n");
1684 return WINED3D_OK;
1686 default:
1687 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1688 return WINED3DERR_NOTAVAILABLE;
1692 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1694 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1696 switch (CheckFormat) {
1697 case WINED3DFMT_R16F:
1698 case WINED3DFMT_A16B16G16R16F:
1699 if (!half_pixel_support) break;
1700 case WINED3DFMT_R32F:
1701 case WINED3DFMT_A32B32G32R32F:
1702 TRACE_(d3d_caps)("[OK]\n");
1703 return WINED3D_OK;
1704 default:
1705 break; /* Avoid compiler warnings */
1709 /* This format is nothing special and it is supported perfectly.
1710 * However, ati and nvidia driver on windows do not mark this format as
1711 * supported (tested with the dxCapsViewer) and pretending to
1712 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1713 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1714 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1716 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1717 TRACE_(d3d_caps)("[FAILED]\n");
1718 return WINED3DERR_NOTAVAILABLE;
1721 switch (CheckFormat) {
1723 /*****
1724 * supported: RGB(A) formats
1726 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1727 case WINED3DFMT_A8R8G8B8:
1728 case WINED3DFMT_X8R8G8B8:
1729 case WINED3DFMT_R5G6B5:
1730 case WINED3DFMT_X1R5G5B5:
1731 case WINED3DFMT_A1R5G5B5:
1732 case WINED3DFMT_A4R4G4B4:
1733 case WINED3DFMT_R3G3B2:
1734 case WINED3DFMT_A8:
1735 case WINED3DFMT_A8R3G3B2:
1736 case WINED3DFMT_X4R4G4B4:
1737 case WINED3DFMT_A8B8G8R8:
1738 case WINED3DFMT_X8B8G8R8:
1739 case WINED3DFMT_A2R10G10B10:
1740 case WINED3DFMT_A2B10G10R10:
1741 TRACE_(d3d_caps)("[OK]\n");
1742 return WINED3D_OK;
1744 /*****
1745 * supported: Palettized
1747 case WINED3DFMT_P8:
1748 TRACE_(d3d_caps)("[OK]\n");
1749 return WINED3D_OK;
1751 /*****
1752 * Supported: (Alpha)-Luminance
1754 case WINED3DFMT_L8:
1755 case WINED3DFMT_A8L8:
1756 case WINED3DFMT_A4L4:
1757 TRACE_(d3d_caps)("[OK]\n");
1758 return WINED3D_OK;
1760 /*****
1761 * Not supported for now: Bump mapping formats
1762 * Enable some because games often fail when they are not available
1763 * and are still playable even without bump mapping
1765 case WINED3DFMT_V8U8:
1766 case WINED3DFMT_V16U16:
1767 case WINED3DFMT_L6V5U5:
1768 case WINED3DFMT_X8L8V8U8:
1769 case WINED3DFMT_Q8W8V8U8:
1770 case WINED3DFMT_W11V11U10:
1771 case WINED3DFMT_A2W10V10U10:
1772 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1773 return WINED3D_OK;
1775 /*****
1776 * DXTN Formats: Handled above
1777 * WINED3DFMT_DXT1
1778 * WINED3DFMT_DXT2
1779 * WINED3DFMT_DXT3
1780 * WINED3DFMT_DXT4
1781 * WINED3DFMT_DXT5
1784 /*****
1785 * Odd formats - not supported
1787 case WINED3DFMT_VERTEXDATA:
1788 case WINED3DFMT_INDEX16:
1789 case WINED3DFMT_INDEX32:
1790 case WINED3DFMT_Q16W16V16U16:
1791 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1792 return WINED3DERR_NOTAVAILABLE;
1794 /*****
1795 * Float formats: Not supported right now
1797 case WINED3DFMT_G16R16F:
1798 case WINED3DFMT_G32R32F:
1799 case WINED3DFMT_CxV8U8:
1800 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1801 return WINED3DERR_NOTAVAILABLE;
1803 /* Not supported */
1804 case WINED3DFMT_G16R16:
1805 case WINED3DFMT_A16B16G16R16:
1806 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1807 return WINED3DERR_NOTAVAILABLE;
1809 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1810 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1811 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1812 * We can do instancing with all shader versions, but we need vertex shaders.
1814 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1815 * to enable instancing. WineD3D doesn't need that and just ignores it.
1817 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1819 case WINEMAKEFOURCC('I','N','S','T'):
1820 TRACE("ATI Instancing check hack\n");
1821 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1822 TRACE_(d3d_caps)("[OK]\n");
1823 return WINED3D_OK;
1824 } else {
1825 TRACE_(d3d_caps)("[FAILED]\n");
1826 return WINED3DERR_NOTAVAILABLE;
1829 default:
1830 break;
1833 TRACE_(d3d_caps)("[FAILED]\n");
1834 return WINED3DERR_NOTAVAILABLE;
1837 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1838 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1839 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1841 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1842 This,
1843 Adapter,
1844 DeviceType, debug_d3ddevicetype(DeviceType),
1845 SourceFormat, debug_d3dformat(SourceFormat),
1846 TargetFormat, debug_d3dformat(TargetFormat));
1847 return WINED3D_OK;
1850 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1851 subset of a D3DCAPS9 structure. However, it has to come via a void *
1852 as the d3d8 interface cannot import the d3d9 header */
1853 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1855 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1856 int vs_selected_mode;
1857 int ps_selected_mode;
1859 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1861 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1862 return WINED3DERR_INVALIDCALL;
1865 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1867 /* This function should *not* be modifying GL caps
1868 * TODO: move the functionality where it belongs */
1869 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1871 /* ------------------------------------------------
1872 The following fields apply to both d3d8 and d3d9
1873 ------------------------------------------------ */
1874 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1875 *pCaps->AdapterOrdinal = Adapter;
1877 *pCaps->Caps = 0;
1878 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1879 WINED3DCAPS2_FULLSCREENGAMMA |
1880 WINED3DCAPS2_DYNAMICTEXTURES;
1881 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1882 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1884 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1885 WINED3DCURSORCAPS_LOWRES;
1887 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1888 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1889 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1890 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1891 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1892 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1893 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1894 WINED3DDEVCAPS_PUREDEVICE |
1895 WINED3DDEVCAPS_HWRASTERIZATION |
1896 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1897 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1898 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1899 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1900 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1901 WINED3DDEVCAPS_RTPATCHES;
1903 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1904 WINED3DPMISCCAPS_CULLCCW |
1905 WINED3DPMISCCAPS_CULLCW |
1906 WINED3DPMISCCAPS_COLORWRITEENABLE |
1907 WINED3DPMISCCAPS_CLIPTLVERTS |
1908 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1909 WINED3DPMISCCAPS_MASKZ |
1910 WINED3DPMISCCAPS_BLENDOP;
1911 /* TODO:
1912 WINED3DPMISCCAPS_NULLREFERENCE
1913 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1914 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1915 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1916 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1917 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1918 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1920 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1921 #if 0
1922 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1923 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1924 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1925 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1926 #endif
1928 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1929 WINED3DPRASTERCAPS_PAT |
1930 WINED3DPRASTERCAPS_WFOG |
1931 WINED3DPRASTERCAPS_ZFOG |
1932 WINED3DPRASTERCAPS_FOGVERTEX |
1933 WINED3DPRASTERCAPS_FOGTABLE |
1934 WINED3DPRASTERCAPS_FOGRANGE |
1935 WINED3DPRASTERCAPS_STIPPLE |
1936 WINED3DPRASTERCAPS_SUBPIXEL |
1937 WINED3DPRASTERCAPS_ZTEST |
1938 WINED3DPRASTERCAPS_SCISSORTEST |
1939 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1940 WINED3DPRASTERCAPS_DEPTHBIAS;
1942 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1943 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1944 WINED3DPRASTERCAPS_ZBIAS |
1945 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1947 /* FIXME Add:
1948 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1949 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1950 WINED3DPRASTERCAPS_ANTIALIASEDGES
1951 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1952 WINED3DPRASTERCAPS_WBUFFER */
1954 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1955 WINED3DPCMPCAPS_EQUAL |
1956 WINED3DPCMPCAPS_GREATER |
1957 WINED3DPCMPCAPS_GREATEREQUAL |
1958 WINED3DPCMPCAPS_LESS |
1959 WINED3DPCMPCAPS_LESSEQUAL |
1960 WINED3DPCMPCAPS_NEVER |
1961 WINED3DPCMPCAPS_NOTEQUAL;
1963 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1964 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1965 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1966 WINED3DPBLENDCAPS_DESTALPHA |
1967 WINED3DPBLENDCAPS_DESTCOLOR |
1968 WINED3DPBLENDCAPS_INVDESTALPHA |
1969 WINED3DPBLENDCAPS_INVDESTCOLOR |
1970 WINED3DPBLENDCAPS_INVSRCALPHA |
1971 WINED3DPBLENDCAPS_INVSRCCOLOR |
1972 WINED3DPBLENDCAPS_ONE |
1973 WINED3DPBLENDCAPS_SRCALPHA |
1974 WINED3DPBLENDCAPS_SRCALPHASAT |
1975 WINED3DPBLENDCAPS_SRCCOLOR |
1976 WINED3DPBLENDCAPS_ZERO;
1978 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1979 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1980 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1981 WINED3DPBLENDCAPS_DESTALPHA |
1982 WINED3DPBLENDCAPS_DESTCOLOR |
1983 WINED3DPBLENDCAPS_INVDESTALPHA |
1984 WINED3DPBLENDCAPS_INVDESTCOLOR |
1985 WINED3DPBLENDCAPS_INVSRCALPHA |
1986 WINED3DPBLENDCAPS_INVSRCCOLOR |
1987 WINED3DPBLENDCAPS_ONE |
1988 WINED3DPBLENDCAPS_SRCALPHA |
1989 WINED3DPBLENDCAPS_SRCALPHASAT |
1990 WINED3DPBLENDCAPS_SRCCOLOR |
1991 WINED3DPBLENDCAPS_ZERO;
1993 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1994 WINED3DPCMPCAPS_EQUAL |
1995 WINED3DPCMPCAPS_GREATER |
1996 WINED3DPCMPCAPS_GREATEREQUAL |
1997 WINED3DPCMPCAPS_LESS |
1998 WINED3DPCMPCAPS_LESSEQUAL |
1999 WINED3DPCMPCAPS_NEVER |
2000 WINED3DPCMPCAPS_NOTEQUAL;
2002 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2003 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2004 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2005 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2006 WINED3DPSHADECAPS_COLORFLATRGB |
2007 WINED3DPSHADECAPS_FOGFLAT |
2008 WINED3DPSHADECAPS_FOGGOURAUD |
2009 WINED3DPSHADECAPS_SPECULARFLATRGB;
2011 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2012 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2013 WINED3DPTEXTURECAPS_BORDER |
2014 WINED3DPTEXTURECAPS_MIPMAP |
2015 WINED3DPTEXTURECAPS_PROJECTED |
2016 WINED3DPTEXTURECAPS_PERSPECTIVE |
2017 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2019 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2020 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2021 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2022 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2025 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2026 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2027 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2028 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2032 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2033 WINED3DPTFILTERCAPS_MAGFPOINT |
2034 WINED3DPTFILTERCAPS_MINFLINEAR |
2035 WINED3DPTFILTERCAPS_MINFPOINT |
2036 WINED3DPTFILTERCAPS_MIPFLINEAR |
2037 WINED3DPTFILTERCAPS_MIPFPOINT |
2038 WINED3DPTFILTERCAPS_LINEAR |
2039 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2040 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2041 WINED3DPTFILTERCAPS_MIPLINEAR |
2042 WINED3DPTFILTERCAPS_MIPNEAREST |
2043 WINED3DPTFILTERCAPS_NEAREST;
2045 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2046 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2047 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2050 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2051 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2052 WINED3DPTFILTERCAPS_MAGFPOINT |
2053 WINED3DPTFILTERCAPS_MINFLINEAR |
2054 WINED3DPTFILTERCAPS_MINFPOINT |
2055 WINED3DPTFILTERCAPS_MIPFLINEAR |
2056 WINED3DPTFILTERCAPS_MIPFPOINT |
2057 WINED3DPTFILTERCAPS_LINEAR |
2058 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2059 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2060 WINED3DPTFILTERCAPS_MIPLINEAR |
2061 WINED3DPTFILTERCAPS_MIPNEAREST |
2062 WINED3DPTFILTERCAPS_NEAREST;
2064 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2065 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2066 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2068 } else
2069 *pCaps->CubeTextureFilterCaps = 0;
2071 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2072 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2073 WINED3DPTFILTERCAPS_MAGFPOINT |
2074 WINED3DPTFILTERCAPS_MINFLINEAR |
2075 WINED3DPTFILTERCAPS_MINFPOINT |
2076 WINED3DPTFILTERCAPS_MIPFLINEAR |
2077 WINED3DPTFILTERCAPS_MIPFPOINT |
2078 WINED3DPTFILTERCAPS_LINEAR |
2079 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2080 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2081 WINED3DPTFILTERCAPS_MIPLINEAR |
2082 WINED3DPTFILTERCAPS_MIPNEAREST |
2083 WINED3DPTFILTERCAPS_NEAREST;
2084 } else
2085 *pCaps->VolumeTextureFilterCaps = 0;
2087 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2088 WINED3DPTADDRESSCAPS_CLAMP |
2089 WINED3DPTADDRESSCAPS_WRAP;
2091 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2092 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2094 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2095 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2097 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2098 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2101 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2102 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2103 WINED3DPTADDRESSCAPS_CLAMP |
2104 WINED3DPTADDRESSCAPS_WRAP;
2105 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2106 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2108 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2109 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2111 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2112 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2114 } else
2115 *pCaps->VolumeTextureAddressCaps = 0;
2117 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2118 WINED3DLINECAPS_ZTEST;
2119 /* FIXME: Add
2120 WINED3DLINECAPS_BLEND
2121 WINED3DLINECAPS_ALPHACMP
2122 WINED3DLINECAPS_FOG */
2124 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2125 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2127 if(GL_SUPPORT(EXT_TEXTURE3D))
2128 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2129 else
2130 *pCaps->MaxVolumeExtent = 0;
2132 *pCaps->MaxTextureRepeat = 32768;
2133 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2134 *pCaps->MaxVertexW = 1.0;
2136 *pCaps->GuardBandLeft = 0;
2137 *pCaps->GuardBandTop = 0;
2138 *pCaps->GuardBandRight = 0;
2139 *pCaps->GuardBandBottom = 0;
2141 *pCaps->ExtentsAdjust = 0;
2143 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2144 WINED3DSTENCILCAPS_INCRSAT |
2145 WINED3DSTENCILCAPS_INVERT |
2146 WINED3DSTENCILCAPS_KEEP |
2147 WINED3DSTENCILCAPS_REPLACE |
2148 WINED3DSTENCILCAPS_ZERO;
2149 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2150 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2151 WINED3DSTENCILCAPS_INCR;
2153 if ( This->dxVersion > 8 &&
2154 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2155 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2156 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2159 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2161 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2162 WINED3DTEXOPCAPS_ADDSIGNED |
2163 WINED3DTEXOPCAPS_ADDSIGNED2X |
2164 WINED3DTEXOPCAPS_MODULATE |
2165 WINED3DTEXOPCAPS_MODULATE2X |
2166 WINED3DTEXOPCAPS_MODULATE4X |
2167 WINED3DTEXOPCAPS_SELECTARG1 |
2168 WINED3DTEXOPCAPS_SELECTARG2 |
2169 WINED3DTEXOPCAPS_DISABLE;
2171 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2172 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2173 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2174 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2175 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2176 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2177 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2178 WINED3DTEXOPCAPS_LERP |
2179 WINED3DTEXOPCAPS_SUBTRACT;
2181 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2182 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2183 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2184 WINED3DTEXOPCAPS_MULTIPLYADD |
2185 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2186 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2187 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2189 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2190 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2192 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2193 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2194 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2197 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2198 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2199 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2200 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2201 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2202 * and 3D textures. It also allows us to keep the code simpler by having texture
2203 * shaders constantly enabled.
2205 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2206 /* TODO: Luminance bump map? */
2208 #if 0
2209 /* FIXME: Add
2210 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2211 WINED3DTEXOPCAPS_PREMODULATE */
2212 #endif
2214 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2215 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2216 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2217 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2219 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2220 *pCaps->MaxVertexBlendMatrixIndex = 0;
2222 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2223 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2226 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2227 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2228 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2229 WINED3DVTXPCAPS_LOCALVIEWER |
2230 WINED3DVTXPCAPS_VERTEXFOG |
2231 WINED3DVTXPCAPS_TEXGEN;
2232 /* FIXME: Add
2233 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2235 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2236 *pCaps->MaxVertexIndex = 0xFFFFF;
2237 *pCaps->MaxStreams = MAX_STREAMS;
2238 *pCaps->MaxStreamStride = 1024;
2240 if (vs_selected_mode == SHADER_GLSL) {
2241 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2242 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2243 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2244 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2245 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2246 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2247 else
2248 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2249 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2250 } else if (vs_selected_mode == SHADER_ARB) {
2251 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2252 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2253 } else {
2254 *pCaps->VertexShaderVersion = 0;
2255 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2258 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2260 if (ps_selected_mode == SHADER_GLSL) {
2261 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2262 in case of GeforceFX cards. */
2263 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2264 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2265 else
2266 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2267 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2268 *pCaps->PixelShader1xMaxValue = 1.0;
2269 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2270 } else if (ps_selected_mode == SHADER_ARB) {
2271 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2272 *pCaps->PixelShader1xMaxValue = 1.0;
2273 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2274 } else {
2275 *pCaps->PixelShaderVersion = 0;
2276 *pCaps->PixelShader1xMaxValue = 0.0;
2277 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2280 /* ------------------------------------------------
2281 The following fields apply to d3d9 only
2282 ------------------------------------------------ */
2283 if (This->dxVersion > 8) {
2284 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2285 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2286 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2287 *pCaps->MaxNpatchTessellationLevel = 0;
2288 *pCaps->MasterAdapterOrdinal = 0;
2289 *pCaps->AdapterOrdinalInGroup = 0;
2290 *pCaps->NumberOfAdaptersInGroup = 1;
2292 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2293 /* OpenGL supports all the formats below, perhaps not always
2294 * without conversion, but it supports them.
2295 * Further GLSL doesn't seem to have an official unsigned type so
2296 * don't advertise it yet as I'm not sure how we handle it.
2297 * We might need to add some clamping in the shader engine to
2298 * support it.
2299 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2300 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2301 WINED3DDTCAPS_UBYTE4N |
2302 WINED3DDTCAPS_SHORT2N |
2303 WINED3DDTCAPS_SHORT4N |
2304 WINED3DDTCAPS_FLOAT16_2 |
2305 WINED3DDTCAPS_FLOAT16_4;
2307 } else
2308 *pCaps->DeclTypes = 0;
2310 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2313 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2314 WINED3DPTFILTERCAPS_MAGFPOINT |
2315 WINED3DPTFILTERCAPS_MINFLINEAR |
2316 WINED3DPTFILTERCAPS_MAGFLINEAR;
2317 *pCaps->VertexTextureFilterCaps = 0;
2319 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2320 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2321 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2322 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2323 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2324 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2325 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2327 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2328 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2329 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2330 *pCaps->VS20Caps.Caps = 0;
2331 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2332 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2333 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2335 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2336 *pCaps->MaxVertexShader30InstructionSlots = 0;
2337 } else { /* VS 1.x */
2338 *pCaps->VS20Caps.Caps = 0;
2339 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2340 *pCaps->VS20Caps.NumTemps = 0;
2341 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2343 *pCaps->MaxVShaderInstructionsExecuted = 0;
2344 *pCaps->MaxVertexShader30InstructionSlots = 0;
2347 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2348 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2349 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2351 /* 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 */
2352 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2353 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2354 WINED3DPS20CAPS_PREDICATION |
2355 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2356 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2357 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2358 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2359 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2360 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2362 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2363 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2364 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2365 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2366 *pCaps->PS20Caps.Caps = 0;
2367 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2368 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2369 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2370 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2372 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2373 *pCaps->MaxPixelShader30InstructionSlots = 0;
2374 } else { /* PS 1.x */
2375 *pCaps->PS20Caps.Caps = 0;
2376 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2377 *pCaps->PS20Caps.NumTemps = 0;
2378 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2379 *pCaps->PS20Caps.NumInstructionSlots = 0;
2381 *pCaps->MaxPShaderInstructionsExecuted = 0;
2382 *pCaps->MaxPixelShader30InstructionSlots = 0;
2386 return WINED3D_OK;
2389 static unsigned int glsl_program_key_hash(void *key) {
2390 glsl_program_key_t *k = (glsl_program_key_t *)key;
2392 unsigned int hash = k->vshader | k->pshader << 16;
2393 hash += ~(hash << 15);
2394 hash ^= (hash >> 10);
2395 hash += (hash << 3);
2396 hash ^= (hash >> 6);
2397 hash += ~(hash << 11);
2398 hash ^= (hash >> 16);
2400 return hash;
2403 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2404 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2405 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2407 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2410 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2411 and fields being inserted in the middle, a new structure is used in place */
2412 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2413 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2414 IUnknown *parent) {
2416 IWineD3DDeviceImpl *object = NULL;
2417 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2418 HDC hDC;
2419 int i;
2421 /* Validate the adapter number */
2422 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2423 return WINED3DERR_INVALIDCALL;
2426 /* Create a WineD3DDevice object */
2427 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2428 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2429 TRACE("Created WineD3DDevice object @ %p\n", object);
2430 if (NULL == object) {
2431 return WINED3DERR_OUTOFVIDEOMEMORY;
2434 /* Set up initial COM information */
2435 object->lpVtbl = &IWineD3DDevice_Vtbl;
2436 object->ref = 1;
2437 object->wineD3D = iface;
2438 object->adapter = &Adapters[Adapter];
2439 IWineD3D_AddRef(object->wineD3D);
2440 object->parent = parent;
2442 if(This->dxVersion == 7) {
2443 object->surface_alignment = 8;
2444 } else {
2445 object->surface_alignment = 4;
2448 /* Set the state up as invalid until the device is fully created */
2449 object->state = WINED3DERR_DRIVERINTERNALERROR;
2451 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2452 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2454 /* Save the creation parameters */
2455 object->createParms.AdapterOrdinal = Adapter;
2456 object->createParms.DeviceType = DeviceType;
2457 object->createParms.hFocusWindow = hFocusWindow;
2458 object->createParms.BehaviorFlags = BehaviourFlags;
2460 /* Initialize other useful values */
2461 object->adapterNo = Adapter;
2462 object->devType = DeviceType;
2464 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2465 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2466 object->shader_backend = &glsl_shader_backend;
2467 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2468 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2469 object->shader_backend = &arb_program_shader_backend;
2470 } else {
2471 object->shader_backend = &none_shader_backend;
2474 /* set the state of the device to valid */
2475 object->state = WINED3D_OK;
2477 /* Get the initial screen setup for ddraw */
2478 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2479 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2480 hDC = GetDC(0);
2481 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2482 ReleaseDC(0, hDC);
2484 for(i = 0; i < PATCHMAP_SIZE; i++) {
2485 list_init(&object->patches[i]);
2487 return WINED3D_OK;
2489 #undef GLINFO_LOCATION
2491 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2492 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2493 IUnknown_AddRef(This->parent);
2494 *pParent = This->parent;
2495 return WINED3D_OK;
2498 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2499 IUnknown* surfaceParent;
2500 TRACE("(%p) call back\n", pSurface);
2502 /* Now, release the parent, which will take care of cleaning up the surface for us */
2503 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2504 IUnknown_Release(surfaceParent);
2505 return IUnknown_Release(surfaceParent);
2508 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2509 IUnknown* volumeParent;
2510 TRACE("(%p) call back\n", pVolume);
2512 /* Now, release the parent, which will take care of cleaning up the volume for us */
2513 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2514 IUnknown_Release(volumeParent);
2515 return IUnknown_Release(volumeParent);
2518 BOOL InitAdapters(void) {
2519 HDC device_context;
2520 BOOL ret;
2521 int ps_selected_mode, vs_selected_mode;
2523 /* No need to hold any lock. The calling library makes sure only one thread calls
2524 * wined3d simultaneously
2526 if(numAdapters > 0) return TRUE;
2528 TRACE("Initializing adapters\n");
2529 /* For now only one default adapter */
2531 TRACE("Initializing default adapter\n");
2532 Adapters[0].monitorPoint.x = -1;
2533 Adapters[0].monitorPoint.y = -1;
2535 device_context = GetDC(0);
2536 Adapters[0].display = get_display(device_context);
2537 ReleaseDC(0, device_context);
2539 ENTER_GL();
2540 if(WineD3D_CreateFakeGLContext()) {
2541 Adapters[0].cfgs = glXGetFBConfigs(Adapters[0].display, DefaultScreen(Adapters[0].display), &Adapters[0].nCfgs);
2542 WineD3D_ReleaseFakeGLContext();
2543 } else {
2544 ERR("Failed to create a fake opengl context to find fbconfigs formats\n");
2545 LEAVE_GL();
2546 return FALSE;
2548 LEAVE_GL();
2550 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info, Adapters[0].display);
2551 if(!ret) {
2552 ERR("Failed to initialize gl caps for default adapter\n");
2553 XFree(Adapters[0].cfgs);
2554 HeapFree(GetProcessHeap(), 0, Adapters);
2555 return FALSE;
2557 Adapters[0].driver = "Display";
2558 Adapters[0].description = "Direct3D HAL";
2560 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2561 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2563 numAdapters = 1;
2564 TRACE("%d adapters successfully initialized\n", numAdapters);
2566 return TRUE;
2570 /**********************************************************
2571 * IWineD3D VTbl follows
2572 **********************************************************/
2574 const IWineD3DVtbl IWineD3D_Vtbl =
2576 /* IUnknown */
2577 IWineD3DImpl_QueryInterface,
2578 IWineD3DImpl_AddRef,
2579 IWineD3DImpl_Release,
2580 /* IWineD3D */
2581 IWineD3DImpl_GetParent,
2582 IWineD3DImpl_GetAdapterCount,
2583 IWineD3DImpl_RegisterSoftwareDevice,
2584 IWineD3DImpl_GetAdapterMonitor,
2585 IWineD3DImpl_GetAdapterModeCount,
2586 IWineD3DImpl_EnumAdapterModes,
2587 IWineD3DImpl_GetAdapterDisplayMode,
2588 IWineD3DImpl_GetAdapterIdentifier,
2589 IWineD3DImpl_CheckDeviceMultiSampleType,
2590 IWineD3DImpl_CheckDepthStencilMatch,
2591 IWineD3DImpl_CheckDeviceType,
2592 IWineD3DImpl_CheckDeviceFormat,
2593 IWineD3DImpl_CheckDeviceFormatConversion,
2594 IWineD3DImpl_GetDeviceCaps,
2595 IWineD3DImpl_CreateDevice