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
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
38 #define GLINFO_LOCATION This->gl_info
40 /**********************************************************
41 * Utility functions follow
42 **********************************************************/
44 /* x11drv GDI escapes */
45 #define X11DRV_ESCAPE 6789
46 enum x11drv_escape_codes
48 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
49 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
50 X11DRV_GET_FONT, /* get current X font for a DC */
53 /* retrieve the X display to use on a given DC */
54 inline static Display *get_display( HDC hdc )
57 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
59 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
60 sizeof(display), (LPSTR)&display )) display = NULL;
65 int minLookup[MAX_LOOKUPS];
66 int maxLookup[MAX_LOOKUPS];
67 DWORD *stateLookup[MAX_LOOKUPS];
69 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
73 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
74 * ie there is no GL Context - Get a default rendering context to enable the
75 * function query some info from GL
78 static int wined3d_fake_gl_context_ref = 0;
79 static BOOL wined3d_fake_gl_context_foreign;
80 static BOOL wined3d_fake_gl_context_available = FALSE;
81 static Display* wined3d_fake_gl_context_display = NULL;
83 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
84 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
86 0, 0, &wined3d_fake_gl_context_cs,
87 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
88 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
89 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
91 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
93 static void WineD3D_ReleaseFakeGLContext(void) {
96 EnterCriticalSection(&wined3d_fake_gl_context_cs);
98 if(!wined3d_fake_gl_context_available) {
99 TRACE_(d3d_caps)("context not available\n");
100 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
104 glCtx = glXGetCurrentContext();
106 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
107 if (0 == (--wined3d_fake_gl_context_ref) ) {
108 if(!wined3d_fake_gl_context_foreign && glCtx) {
109 TRACE_(d3d_caps)("destroying fake GL context\n");
110 glXMakeCurrent(wined3d_fake_gl_context_display, None, NULL);
111 glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
113 wined3d_fake_gl_context_available = FALSE;
115 assert(wined3d_fake_gl_context_ref >= 0);
117 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
121 static BOOL WineD3D_CreateFakeGLContext(void) {
122 XVisualInfo* visInfo;
126 EnterCriticalSection(&wined3d_fake_gl_context_cs);
128 TRACE_(d3d_caps)("getting context...\n");
129 if(wined3d_fake_gl_context_ref > 0) goto ret;
130 assert(0 == wined3d_fake_gl_context_ref);
132 wined3d_fake_gl_context_foreign = TRUE;
134 if(!wined3d_fake_gl_context_display) {
135 HDC device_context = GetDC(0);
137 wined3d_fake_gl_context_display = get_display(device_context);
138 ReleaseDC(0, device_context);
142 glCtx = glXGetCurrentContext();
146 XVisualInfo template;
149 XWindowAttributes win_attr;
151 wined3d_fake_gl_context_foreign = FALSE;
152 drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
154 TRACE_(d3d_caps)("Creating Fake GL Context\n");
156 /* Get the X visual */
157 if (XGetWindowAttributes(wined3d_fake_gl_context_display, drawable, &win_attr)) {
158 visual = win_attr.visual;
160 visual = DefaultVisual(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display));
162 template.visualid = XVisualIDFromVisual(visual);
163 visInfo = XGetVisualInfo(wined3d_fake_gl_context_display, VisualIDMask, &template, &num);
165 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
169 /* Create a GL context */
170 glCtx = glXCreateContext(wined3d_fake_gl_context_display, visInfo, NULL, GL_TRUE);
172 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
176 /* Make it the current GL context */
177 if (!glXMakeCurrent(wined3d_fake_gl_context_display, drawable, glCtx)) {
178 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
187 TRACE_(d3d_caps)("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
188 wined3d_fake_gl_context_ref++;
189 wined3d_fake_gl_context_available = TRUE;
190 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
193 if(visInfo) XFree(visInfo);
194 if(glCtx) glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
195 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
200 /**********************************************************
201 * IUnknown parts follows
202 **********************************************************/
204 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
206 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
208 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
209 if (IsEqualGUID(riid, &IID_IUnknown)
210 || IsEqualGUID(riid, &IID_IWineD3DBase)
211 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
212 IUnknown_AddRef(iface);
217 return E_NOINTERFACE;
220 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
221 IWineD3DImpl *This = (IWineD3DImpl *)iface;
222 ULONG refCount = InterlockedIncrement(&This->ref);
224 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
228 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
229 IWineD3DImpl *This = (IWineD3DImpl *)iface;
231 TRACE("(%p) : Releasing from %d\n", This, This->ref);
232 ref = InterlockedDecrement(&This->ref);
234 HeapFree(GetProcessHeap(), 0, This);
240 /* Set the shader type for this device, depending on the given capabilities,
241 * the device type, and the user preferences in wined3d_settings */
243 static void select_shader_mode(
244 WineD3D_GL_Info *gl_info,
245 WINED3DDEVTYPE DeviceType,
249 /* Give priority to user disable/emulation request.
250 * Then respect REF device for software.
251 * Then check capabilities for hardware, and fallback to software */
253 if (wined3d_settings.vs_mode == VS_NONE) {
254 *vs_selected = SHADER_NONE;
255 } else if (DeviceType == WINED3DDEVTYPE_REF || wined3d_settings.vs_mode == VS_SW) {
256 *vs_selected = SHADER_SW;
257 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
258 *vs_selected = SHADER_GLSL;
259 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
260 *vs_selected = SHADER_ARB;
262 *vs_selected = SHADER_SW;
265 /* Fallback to SHADER_NONE where software pixel shaders should be used */
266 if (wined3d_settings.ps_mode == PS_NONE) {
267 *ps_selected = SHADER_NONE;
268 } else if (DeviceType == WINED3DDEVTYPE_REF) {
269 *ps_selected = SHADER_NONE;
270 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
271 *ps_selected = SHADER_GLSL;
272 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
273 *ps_selected = SHADER_ARB;
275 *ps_selected = SHADER_NONE;
279 /** Select the number of report maximum shader constants based on the selected shader modes */
280 void select_shader_max_constants(
281 int ps_selected_mode,
282 int vs_selected_mode,
283 WineD3D_GL_Info *gl_info) {
285 switch (vs_selected_mode) {
287 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
288 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
291 /* We have to subtract any other PARAMs that we might use in our shader programs.
292 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
293 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
294 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
297 gl_info->max_vshader_constantsF = 96; /* TODO: Fixup software shaders */
300 gl_info->max_vshader_constantsF = 0;
304 switch (ps_selected_mode) {
306 /* Subtract the other potential uniforms from the max available (bools & ints).
307 * In theory the texbem instruction may need one more shader constant too. But lets assume
308 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
309 * and lets not take away a uniform needlessly from all other shaders.
311 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I;
314 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
315 * a free constant to do that, so no need to reduce the number of available constants.
317 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
320 gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */
323 gl_info->max_pshader_constantsF = 0;
328 /**********************************************************
329 * IWineD3D parts follows
330 **********************************************************/
332 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
333 IWineD3DImpl *This = (IWineD3DImpl *)iface;
334 WineD3D_GL_Info *gl_info = &This->gl_info;
336 const char *GL_Extensions = NULL;
337 const char *GLX_Extensions = NULL;
338 const char *gl_string = NULL;
339 const char *gl_string_cursor = NULL;
341 GLfloat gl_floatv[2];
344 BOOL return_value = TRUE;
347 /* Make sure that we've got a context */
348 /* TODO: CreateFakeGLContext should really take a display as a parameter */
349 /* Only save the values obtained when a display is provided */
350 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
351 return_value = FALSE;
353 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
355 gl_string = (const char *) glGetString(GL_RENDERER);
356 if (NULL == gl_string)
358 strcpy(gl_info->gl_renderer, gl_string);
360 /* Fill in the GL info retrievable depending on the display */
361 if (NULL != display) {
362 test = glXQueryVersion(display, &major, &minor);
363 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
365 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
367 gl_string = (const char *) glGetString(GL_VENDOR);
369 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
370 if (gl_string != NULL) {
371 /* Fill in the GL vendor */
372 if (strstr(gl_string, "NVIDIA")) {
373 gl_info->gl_vendor = VENDOR_NVIDIA;
374 } else if (strstr(gl_string, "ATI")) {
375 gl_info->gl_vendor = VENDOR_ATI;
376 } else if (strstr(gl_string, "Intel(R)") ||
377 strstr(gl_info->gl_renderer, "Intel(R)")) {
378 gl_info->gl_vendor = VENDOR_INTEL;
379 } else if (strstr(gl_string, "Mesa")) {
380 gl_info->gl_vendor = VENDOR_MESA;
382 gl_info->gl_vendor = VENDOR_WINE;
385 gl_info->gl_vendor = VENDOR_WINE;
389 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
391 /* Parse the GL_VERSION field into major and minor information */
392 gl_string = (const char *) glGetString(GL_VERSION);
393 if (gl_string != NULL) {
395 switch (gl_info->gl_vendor) {
397 gl_string_cursor = strstr(gl_string, "NVIDIA");
398 if (!gl_string_cursor) {
399 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
403 gl_string_cursor = strstr(gl_string_cursor, " ");
404 if (!gl_string_cursor) {
405 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
409 while (*gl_string_cursor == ' ') {
413 if (!*gl_string_cursor) {
414 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
418 major = atoi(gl_string_cursor);
419 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
423 if (*gl_string_cursor++ != '.') {
424 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
428 minor = atoi(gl_string_cursor);
429 minor = major*100+minor;
436 gl_string_cursor = strchr(gl_string, '-');
437 if (gl_string_cursor) {
441 /* Check if version number is of the form x.y.z */
442 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
444 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
446 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
448 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
451 /* Mark version number as malformed */
453 gl_string_cursor = 0;
456 if (!gl_string_cursor)
457 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
459 major = *gl_string_cursor - '0';
460 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
466 gl_string_cursor = strstr(gl_string, "Mesa");
467 gl_string_cursor = strstr(gl_string_cursor, " ");
468 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
469 if (*gl_string_cursor) {
473 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
474 tmp[cursor++] = *gl_string_cursor;
480 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
484 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
485 tmp[cursor++] = *gl_string_cursor;
497 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
498 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
501 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
504 * Initialize openGL extension related variables
505 * with Default values
507 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
508 gl_info->max_buffers = 1;
509 gl_info->max_textures = 1;
510 gl_info->max_texture_stages = 1;
511 gl_info->max_samplers = 1;
512 gl_info->max_sampler_stages = 1;
513 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
514 gl_info->ps_arb_max_temps = 0;
515 gl_info->ps_arb_max_instructions = 0;
516 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
517 gl_info->vs_arb_max_temps = 0;
518 gl_info->vs_arb_max_instructions = 0;
519 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
520 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
521 gl_info->vs_glsl_constantsF = 0;
522 gl_info->ps_glsl_constantsF = 0;
523 gl_info->vs_arb_constantsF = 0;
524 gl_info->ps_arb_constantsF = 0;
526 /* Now work out what GL support this card really has */
527 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
532 /* Retrieve opengl defaults */
533 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
534 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
535 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
537 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
538 gl_info->max_lights = gl_max;
539 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
541 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
542 gl_info->max_texture_size = gl_max;
543 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
545 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
546 gl_info->max_pointsize = gl_floatv[1];
547 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
549 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
550 gl_info->max_aux_buffers = gl_max;
551 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
553 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
554 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
555 TRACE_(d3d_caps)("GL_Extensions reported:\n");
557 if (NULL == GL_Extensions) {
558 ERR(" GL_Extensions returns NULL\n");
560 while (*GL_Extensions != 0x00) {
561 const char *Start = GL_Extensions;
564 memset(ThisExtn, 0x00, sizeof(ThisExtn));
565 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
568 memcpy(ThisExtn, Start, (GL_Extensions - Start));
569 TRACE_(d3d_caps)("- %s\n", ThisExtn);
574 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
575 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
576 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
577 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
578 gl_info->max_buffers = gl_max;
579 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
580 gl_info->ps_arb_version = PS_VERSION_11;
581 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
582 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
583 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
584 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
585 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
586 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
587 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
588 gl_info->ps_arb_constantsF = gl_max;
589 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
590 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
591 gl_info->ps_arb_max_temps = gl_max;
592 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
593 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
594 gl_info->ps_arb_max_instructions = gl_max;
595 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
596 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
597 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
599 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
600 gl_info->ps_glsl_constantsF = gl_max;
601 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
602 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
603 gl_info->supported[ARB_IMAGING] = TRUE;
604 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
605 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
606 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
607 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
608 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
609 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
610 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
611 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
612 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
613 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
614 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
615 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
616 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
617 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
618 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
619 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
620 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
621 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
622 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
623 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
624 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
625 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
626 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
627 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
628 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
629 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
630 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
631 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
632 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
633 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
634 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
635 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
636 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
637 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
638 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
639 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
640 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
641 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
642 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
643 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
644 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
645 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
646 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
647 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
648 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
649 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
650 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
651 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
652 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
653 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
654 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
655 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
656 gl_info->vs_arb_version = VS_VERSION_11;
657 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
658 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
659 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
660 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
661 gl_info->vs_arb_constantsF = gl_max;
662 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
663 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
664 gl_info->vs_arb_max_temps = gl_max;
665 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
666 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
667 gl_info->vs_arb_max_instructions = gl_max;
668 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
669 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
670 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
672 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
673 gl_info->vs_glsl_constantsF = gl_max;
674 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
675 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
676 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
677 gl_info->max_blends = gl_max;
678 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
679 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
680 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
681 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
682 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
683 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
684 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
685 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
686 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
687 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
691 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
692 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
693 gl_info->supported[EXT_FOG_COORD] = TRUE;
694 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
695 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
696 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
697 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
698 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
699 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
700 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
701 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
702 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
703 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
704 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
705 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
706 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
707 TRACE_(d3d_caps)(" FOUND: EXT Secondary color support\n");
708 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
709 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
710 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
711 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
712 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
713 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
714 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
715 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
716 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
717 gl_info->supported[EXT_TEXTURE3D] = TRUE;
718 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
719 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
720 gl_info->max_texture3d_size = gl_max;
721 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
722 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
723 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
724 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
725 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
726 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
727 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
728 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
729 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
730 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
731 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
732 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
733 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
734 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
735 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
736 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
737 gl_info->max_anisotropy = gl_max;
738 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
739 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
740 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
741 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
742 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
743 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
744 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
745 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
746 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
751 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
752 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
753 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
754 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
755 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
756 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
757 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
758 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
759 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
760 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
761 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
762 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
763 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
764 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
765 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
766 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
767 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
768 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
769 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
770 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
771 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
772 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
773 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
774 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
775 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
776 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
777 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
778 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
779 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
780 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
781 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
782 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
783 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
784 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
785 gl_info->vs_nv_version = VS_VERSION_30;
786 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
787 gl_info->vs_nv_version = VS_VERSION_20;
788 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
789 gl_info->vs_nv_version = VS_VERSION_11;
791 gl_info->vs_nv_version = VS_VERSION_10;
792 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
793 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
794 } else if (strstr(ThisExtn, "GL_NV_fence")) {
795 if(!gl_info->supported[APPLE_FENCE]) {
796 gl_info->supported[NV_FENCE] = TRUE;
803 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
804 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
805 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
806 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
807 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
808 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
809 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
810 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
811 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
812 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
813 gl_info->vs_ati_version = VS_VERSION_11;
814 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
815 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
819 } else if (strstr(ThisExtn, "GL_APPLE_fence")) {
820 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
821 * The apple extension interacts with some other apple exts. Disable the NV
822 * extension if the apple one is support to prevent confusion in other parts
825 gl_info->supported[NV_FENCE] = FALSE;
826 gl_info->supported[APPLE_FENCE] = TRUE;
829 if (*GL_Extensions == ' ') GL_Extensions++;
832 checkGLcall("extension detection\n");
834 /* In some cases the number of texture stages can be larger than the number
835 * of samplers. The GF4 for example can use only 2 samplers (no fragment
836 * shaders), but 8 texture stages (register combiners). */
837 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
839 /* We can only use ORM_FBO when the hardware supports it. */
840 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
841 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
842 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
845 /* MRTs are currently only supported when FBOs are used. */
846 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
847 gl_info->max_buffers = 1;
850 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
851 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
852 * in case of the latest videocards in the number of pixel/vertex pipelines.
854 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
855 * rendering. Various games use this information to get a rough estimation of the features of the card
856 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
857 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
858 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
861 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
862 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
863 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
864 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
865 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
866 * is used for rendering which is not always the case). This would work but it is not very portable. Second
867 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
870 * As said most games only use the PCI id to get an indication of the capabilities of the card.
871 * It doesn't really matter if the given id is the correct one if we return the id of a card with
872 * similar 3d features.
874 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
875 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
876 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
877 * won't pass we return a default card. This way is better than maintaining a full card database as even
878 * without a full database we can return a card with similar features. Second the size of the database
879 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
880 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
881 * to distinguishes between different models from that family.
883 switch (gl_info->gl_vendor) {
885 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
886 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
888 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
889 if (strstr(gl_info->gl_renderer, "7800") ||
890 strstr(gl_info->gl_renderer, "7900") ||
891 strstr(gl_info->gl_renderer, "7950") ||
892 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
893 strstr(gl_info->gl_renderer, "Quadro FX 5"))
894 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
895 else if(strstr(gl_info->gl_renderer, "6800") ||
896 strstr(gl_info->gl_renderer, "7600"))
897 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
898 else if(strstr(gl_info->gl_renderer, "6600") ||
899 strstr(gl_info->gl_renderer, "6610") ||
900 strstr(gl_info->gl_renderer, "6700"))
901 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
903 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
904 } else if(WINE_D3D9_CAPABLE(gl_info)) {
905 if (strstr(gl_info->gl_renderer, "5800") ||
906 strstr(gl_info->gl_renderer, "5900") ||
907 strstr(gl_info->gl_renderer, "5950") ||
908 strstr(gl_info->gl_renderer, "Quadro FX"))
909 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
910 else if(strstr(gl_info->gl_renderer, "5600") ||
911 strstr(gl_info->gl_renderer, "5650") ||
912 strstr(gl_info->gl_renderer, "5700") ||
913 strstr(gl_info->gl_renderer, "5750"))
914 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
916 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
917 } else if(WINE_D3D8_CAPABLE(gl_info)) {
918 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
919 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
921 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
922 } else if(WINE_D3D7_CAPABLE(gl_info)) {
923 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
924 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
925 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
926 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
927 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
928 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
930 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
932 if (strstr(gl_info->gl_renderer, "TNT2"))
933 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
935 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
939 if(WINE_D3D9_CAPABLE(gl_info)) {
941 if (strstr(gl_info->gl_renderer, "X1600") ||
942 strstr(gl_info->gl_renderer, "X1800") ||
943 strstr(gl_info->gl_renderer, "X1900") ||
944 strstr(gl_info->gl_renderer, "X1950"))
945 gl_info->gl_card = CARD_ATI_RADEON_X1600;
946 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
947 else if(strstr(gl_info->gl_renderer, "X700") ||
948 strstr(gl_info->gl_renderer, "X800") ||
949 strstr(gl_info->gl_renderer, "X850") ||
950 strstr(gl_info->gl_renderer, "X1300") ||
951 strstr(gl_info->gl_renderer, "X1400"))
952 gl_info->gl_card = CARD_ATI_RADEON_X700;
955 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
956 } else if(WINE_D3D8_CAPABLE(gl_info)) {
957 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
958 } else if(WINE_D3D7_CAPABLE(gl_info)) {
959 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
961 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
964 if (strstr(gl_info->gl_renderer, "915GM")) {
965 gl_info->gl_card = CARD_INTEL_I915GM;
966 } else if (strstr(gl_info->gl_renderer, "915G")) {
967 gl_info->gl_card = CARD_INTEL_I915G;
968 } else if (strstr(gl_info->gl_renderer, "865G")) {
969 gl_info->gl_card = CARD_INTEL_I865G;
970 } else if (strstr(gl_info->gl_renderer, "855G")) {
971 gl_info->gl_card = CARD_INTEL_I855G;
972 } else if (strstr(gl_info->gl_renderer, "830G")) {
973 gl_info->gl_card = CARD_INTEL_I830G;
975 gl_info->gl_card = CARD_INTEL_I915G;
981 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
982 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
983 * them a good generic choice.
985 gl_info->gl_vendor = VENDOR_NVIDIA;
986 if(WINE_D3D9_CAPABLE(gl_info))
987 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
988 else if(WINE_D3D8_CAPABLE(gl_info))
989 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
990 else if(WINE_D3D7_CAPABLE(gl_info))
991 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
992 else if(WINE_D3D6_CAPABLE(gl_info))
993 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
995 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
997 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
999 /* Load all the lookup tables
1000 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1001 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1002 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1004 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1005 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1008 for (i = 0; i < MAX_LOOKUPS; i++) {
1009 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1012 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1013 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1014 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1015 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1016 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1017 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1018 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1019 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1020 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1021 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1023 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1024 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1025 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1026 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1027 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1030 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1031 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1032 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1033 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1034 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1035 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1036 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1037 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1038 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1039 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1040 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1041 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1042 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1044 /* TODO: config lookups */
1046 if (display != NULL) {
1047 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1048 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1050 if (NULL == GLX_Extensions) {
1051 ERR(" GLX_Extensions returns NULL\n");
1053 while (*GLX_Extensions != 0x00) {
1054 const char *Start = GLX_Extensions;
1057 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1058 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1061 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1062 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1063 if (*GLX_Extensions == ' ') GLX_Extensions++;
1069 WineD3D_ReleaseFakeGLContext();
1070 return return_value;
1073 /**********************************************************
1074 * IWineD3D implementation follows
1075 **********************************************************/
1077 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1078 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1080 /* FIXME: Set to one for now to imply the display */
1081 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1085 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1086 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1087 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1091 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1092 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1093 POINT pt = { -1, -1 };
1095 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1099 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1100 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1103 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1104 of the same bpp but different resolutions */
1106 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1107 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1108 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1109 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1111 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1115 if (Adapter == 0) { /* Display */
1119 if (!DEBUG_SINGLE_MODE) {
1122 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1126 case WINED3DFMT_UNKNOWN:
1127 if (DevModeW.dmBitsPerPel == 32 ||
1128 DevModeW.dmBitsPerPel == 16) i++;
1130 case WINED3DFMT_X8R8G8B8:
1131 if (DevModeW.dmBitsPerPel == 32) i++;
1133 case WINED3DFMT_R5G6B5:
1134 if (DevModeW.dmBitsPerPel == 16) i++;
1137 /* Skip other modes as they do not match the requested format */
1146 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1149 FIXME_(d3d_caps)("Adapter not primary display\n");
1154 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1155 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1156 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1157 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1159 /* Validate the parameters as much as possible */
1160 if (NULL == pMode ||
1161 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1162 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1163 return WINED3DERR_INVALIDCALL;
1166 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1172 /* If we are filtering to a specific format (D3D9), then need to skip
1173 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1174 just count through the ones with valid bit depths */
1175 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1178 case WINED3DFMT_UNKNOWN:
1179 if (DevModeW.dmBitsPerPel == 32 ||
1180 DevModeW.dmBitsPerPel == 16) i++;
1182 case WINED3DFMT_X8R8G8B8:
1183 if (DevModeW.dmBitsPerPel == 32) i++;
1185 case WINED3DFMT_R5G6B5:
1186 if (DevModeW.dmBitsPerPel == 16) i++;
1189 /* Modes that don't match what we support can get an early-out */
1190 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1191 return WINED3DERR_INVALIDCALL;
1196 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1197 return WINED3DERR_INVALIDCALL;
1201 /* Now get the display mode via the calculated index */
1202 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1203 pMode->Width = DevModeW.dmPelsWidth;
1204 pMode->Height = DevModeW.dmPelsHeight;
1205 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1206 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1207 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1209 if (Format == WINED3DFMT_UNKNOWN)
1211 switch (DevModeW.dmBitsPerPel)
1214 pMode->Format = WINED3DFMT_R5G6B5;
1217 pMode->Format = WINED3DFMT_X8R8G8B8;
1220 pMode->Format = WINED3DFMT_UNKNOWN;
1221 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1224 pMode->Format = Format;
1227 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1228 return WINED3DERR_INVALIDCALL;
1231 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1232 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1233 DevModeW.dmBitsPerPel);
1235 } else if (DEBUG_SINGLE_MODE) {
1236 /* Return one setting of the format requested */
1237 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1239 pMode->Height = 600;
1240 pMode->RefreshRate = 60;
1241 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1243 FIXME_(d3d_caps)("Adapter not primary display\n");
1249 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1250 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1251 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1253 if (NULL == pMode ||
1254 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1255 return WINED3DERR_INVALIDCALL;
1258 if (Adapter == 0) { /* Display */
1262 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1263 pMode->Width = DevModeW.dmPelsWidth;
1264 pMode->Height = DevModeW.dmPelsHeight;
1265 bpp = DevModeW.dmBitsPerPel;
1266 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1267 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1269 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1273 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1274 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1275 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1276 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1277 default: pMode->Format = WINED3DFMT_UNKNOWN;
1281 FIXME_(d3d_caps)("Adapter not primary display\n");
1284 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1285 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1289 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1292 /* only works with one adapter at the moment... */
1294 /* Get the display */
1295 device_context = GetDC(0);
1296 display = get_display(device_context);
1297 ReleaseDC(0, device_context);
1301 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1302 and fields being inserted in the middle, a new structure is used in place */
1303 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1304 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1305 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1307 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1309 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1310 return WINED3DERR_INVALIDCALL;
1313 if (Adapter == 0) { /* Display - only device supported for now */
1315 BOOL isGLInfoValid = This->isGLInfoValid;
1317 /* FillGLCaps updates gl_info, but we only want to store and
1318 reuse the values once we have a context which is valid. Values from
1319 a temporary context may differ from the final ones */
1320 if (!isGLInfoValid) {
1321 /* If we don't know the device settings, go query them now */
1322 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1325 /* If it worked, return the information requested */
1326 if (isGLInfoValid) {
1327 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1328 strcpy(pIdentifier->Driver, "Display");
1329 strcpy(pIdentifier->Description, "Direct3D HAL");
1331 /* Note dx8 doesn't supply a DeviceName */
1332 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1333 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1334 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1335 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1336 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1337 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1338 *(pIdentifier->SubSysId) = 0;
1339 *(pIdentifier->Revision) = 0;
1343 /* If it failed, return dummy values from an NVidia driver */
1344 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1345 strcpy(pIdentifier->Driver, "Display");
1346 strcpy(pIdentifier->Description, "Direct3D HAL");
1347 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1348 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1349 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1350 /* 71.74 is a current Linux Nvidia driver version */
1351 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1352 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1353 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1354 *(pIdentifier->SubSysId) = 0;
1355 *(pIdentifier->Revision) = 0;
1358 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1359 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1360 *(pIdentifier->WHQLLevel) = 0;
1362 *(pIdentifier->WHQLLevel) = 1;
1366 FIXME_(d3d_caps)("Adapter not primary display\n");
1372 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1373 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1375 int rb, gb, bb, ab, type, buf_sz;
1377 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1378 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1379 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1380 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1381 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1382 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1385 case WINED3DFMT_X8R8G8B8:
1386 case WINED3DFMT_R8G8B8:
1387 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1389 case WINED3DFMT_A8R8G8B8:
1390 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1392 case WINED3DFMT_A2R10G10B10:
1393 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1395 case WINED3DFMT_X1R5G5B5:
1396 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1398 case WINED3DFMT_A1R5G5B5:
1399 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1401 case WINED3DFMT_X4R4G4B4:
1402 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1404 case WINED3DFMT_R5G6B5:
1405 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1407 case WINED3DFMT_R3G3B2:
1408 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1410 case WINED3DFMT_A8P8:
1411 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1414 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1420 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1422 case WINED3DFMT_X8R8G8B8:
1423 case WINED3DFMT_R8G8B8:
1424 case WINED3DFMT_A8R8G8B8:
1425 case WINED3DFMT_A2R10G10B10:
1426 case WINED3DFMT_X1R5G5B5:
1427 case WINED3DFMT_A1R5G5B5:
1428 case WINED3DFMT_R5G6B5:
1429 case WINED3DFMT_R3G3B2:
1430 case WINED3DFMT_A8P8:
1440 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1441 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1445 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1446 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1449 case WINED3DFMT_D16:
1450 case WINED3DFMT_D16_LOCKABLE:
1451 if (16 == db) return TRUE;
1453 case WINED3DFMT_D32:
1454 if (32 == db) return TRUE;
1456 case WINED3DFMT_D15S1:
1457 if (15 == db) return TRUE;
1459 case WINED3DFMT_D24S8:
1460 if (24 == db && 8 == sb) return TRUE;
1462 case WINED3DFMT_D24FS8:
1463 if (24 == db && 8 == sb) return TRUE;
1465 case WINED3DFMT_D24X8:
1466 if (24 == db) return TRUE;
1468 case WINED3DFMT_D24X4S4:
1469 if (24 == db && 4 == sb) return TRUE;
1471 case WINED3DFMT_D32F_LOCKABLE:
1472 if (32 == db) return TRUE;
1478 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1480 case WINED3DFMT_D16:
1481 case WINED3DFMT_D16_LOCKABLE:
1482 case WINED3DFMT_D32:
1483 case WINED3DFMT_D15S1:
1484 case WINED3DFMT_D24S8:
1485 case WINED3DFMT_D24FS8:
1486 case WINED3DFMT_D24X8:
1487 case WINED3DFMT_D24X4S4:
1488 case WINED3DFMT_D32F_LOCKABLE:
1497 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1498 WINED3DFORMAT AdapterFormat,
1499 WINED3DFORMAT RenderTargetFormat,
1500 WINED3DFORMAT DepthStencilFormat) {
1501 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1502 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1503 GLXFBConfig* cfgs = NULL;
1507 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1509 DeviceType, debug_d3ddevicetype(DeviceType),
1510 AdapterFormat, debug_d3dformat(AdapterFormat),
1511 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1512 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1514 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1515 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1516 return WINED3DERR_INVALIDCALL;
1519 if(WineD3D_CreateFakeGLContext())
1520 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1523 for (it = 0; it < nCfgs; ++it) {
1524 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1525 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1532 if(hr != WINED3D_OK)
1533 ERR("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1535 ERR_(d3d_caps)("returning WINED3D_OK even so CreateFakeGLContext or glXGetFBConfigs failed\n");
1539 WineD3D_ReleaseFakeGLContext();
1541 if (hr != WINED3D_OK)
1542 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1544 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1548 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1549 WINED3DFORMAT SurfaceFormat,
1550 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1552 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1553 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1556 DeviceType, debug_d3ddevicetype(DeviceType),
1557 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1562 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1563 return WINED3DERR_INVALIDCALL;
1566 if (pQualityLevels != NULL) {
1567 static int s_single_shot = 0;
1568 if (!s_single_shot) {
1569 FIXME("Quality levels unsupported at present\n");
1572 *pQualityLevels = 1; /* Guess at a value! */
1575 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1576 return WINED3DERR_NOTAVAILABLE;
1579 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1580 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1582 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1583 GLXFBConfig* cfgs = NULL;
1586 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1588 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1591 CheckType, debug_d3ddevicetype(CheckType),
1592 DisplayFormat, debug_d3dformat(DisplayFormat),
1593 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1596 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1597 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1598 return WINED3DERR_INVALIDCALL;
1601 if (WineD3D_CreateFakeGLContext()) {
1602 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1603 for (it = 0; it < nCfgs; ++it) {
1604 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1606 TRACE_(d3d_caps)("OK\n");
1610 if(cfgs) XFree(cfgs);
1611 if(hr != WINED3D_OK)
1612 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1613 WineD3D_ReleaseFakeGLContext();
1616 if(hr != WINED3D_OK)
1617 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1622 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1623 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1624 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1625 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1628 DeviceType, debug_d3ddevicetype(DeviceType),
1629 AdapterFormat, debug_d3dformat(AdapterFormat),
1630 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1631 RType, debug_d3dresourcetype(RType),
1632 CheckFormat, debug_d3dformat(CheckFormat));
1634 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1635 return WINED3DERR_INVALIDCALL;
1638 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1639 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1640 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1641 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1642 TRACE_(d3d_caps)("[FAILED]\n");
1643 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1646 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1647 switch (CheckFormat) {
1648 case WINED3DFMT_D16_LOCKABLE:
1649 case WINED3DFMT_D32:
1650 case WINED3DFMT_D15S1:
1651 case WINED3DFMT_D24S8:
1652 case WINED3DFMT_D24X8:
1653 case WINED3DFMT_D24X4S4:
1654 case WINED3DFMT_D16:
1655 case WINED3DFMT_L16:
1656 case WINED3DFMT_D32F_LOCKABLE:
1657 case WINED3DFMT_D24FS8:
1658 TRACE_(d3d_caps)("[OK]\n");
1661 TRACE_(d3d_caps)("[FAILED]\n");
1662 return WINED3DERR_NOTAVAILABLE;
1664 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1665 switch (CheckFormat) {
1666 case WINED3DFMT_R8G8B8:
1667 case WINED3DFMT_A8R8G8B8:
1668 case WINED3DFMT_X8R8G8B8:
1669 case WINED3DFMT_R5G6B5:
1670 case WINED3DFMT_X1R5G5B5:
1671 case WINED3DFMT_A1R5G5B5:
1672 case WINED3DFMT_A4R4G4B4:
1673 case WINED3DFMT_R3G3B2:
1674 case WINED3DFMT_X4R4G4B4:
1675 case WINED3DFMT_A8B8G8R8:
1676 case WINED3DFMT_X8B8G8R8:
1678 TRACE_(d3d_caps)("[OK]\n");
1681 TRACE_(d3d_caps)("[FAILED]\n");
1682 return WINED3DERR_NOTAVAILABLE;
1686 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1687 switch (CheckFormat) {
1688 case WINED3DFMT_DXT1:
1689 case WINED3DFMT_DXT2:
1690 case WINED3DFMT_DXT3:
1691 case WINED3DFMT_DXT4:
1692 case WINED3DFMT_DXT5:
1693 TRACE_(d3d_caps)("[OK]\n");
1696 break; /* Avoid compiler warnings */
1700 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1702 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1704 switch (CheckFormat) {
1705 case WINED3DFMT_R16F:
1706 case WINED3DFMT_A16B16G16R16F:
1707 if (!half_pixel_support) break;
1708 case WINED3DFMT_R32F:
1709 case WINED3DFMT_A32B32G32R32F:
1710 TRACE_(d3d_caps)("[OK]\n");
1713 break; /* Avoid compiler warnings */
1717 /* This format is nothing special and it is supported perfectly.
1718 * However, ati and nvidia driver on windows do not mark this format as
1719 * supported (tested with the dxCapsViewer) and pretending to
1720 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1721 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1722 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1724 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1725 TRACE_(d3d_caps)("[FAILED]\n");
1726 return WINED3DERR_NOTAVAILABLE;
1729 switch (CheckFormat) {
1732 * supported: RGB(A) formats
1734 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1735 case WINED3DFMT_A8R8G8B8:
1736 case WINED3DFMT_X8R8G8B8:
1737 case WINED3DFMT_R5G6B5:
1738 case WINED3DFMT_X1R5G5B5:
1739 case WINED3DFMT_A1R5G5B5:
1740 case WINED3DFMT_A4R4G4B4:
1741 case WINED3DFMT_R3G3B2:
1743 case WINED3DFMT_A8R3G3B2:
1744 case WINED3DFMT_X4R4G4B4:
1745 case WINED3DFMT_A8B8G8R8:
1746 case WINED3DFMT_X8B8G8R8:
1747 case WINED3DFMT_A2R10G10B10:
1748 case WINED3DFMT_A2B10G10R10:
1749 TRACE_(d3d_caps)("[OK]\n");
1753 * supported: Palettized
1756 TRACE_(d3d_caps)("[OK]\n");
1760 * Supported: (Alpha)-Luminance
1763 case WINED3DFMT_A8L8:
1764 case WINED3DFMT_A4L4:
1765 TRACE_(d3d_caps)("[OK]\n");
1769 * Not supported for now: Bump mapping formats
1770 * Enable some because games often fail when they are not available
1771 * and are still playable even without bump mapping
1773 case WINED3DFMT_V8U8:
1774 case WINED3DFMT_V16U16:
1775 case WINED3DFMT_L6V5U5:
1776 case WINED3DFMT_X8L8V8U8:
1777 case WINED3DFMT_Q8W8V8U8:
1778 case WINED3DFMT_W11V11U10:
1779 case WINED3DFMT_A2W10V10U10:
1780 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1784 * DXTN Formats: Handled above
1793 * Odd formats - not supported
1795 case WINED3DFMT_VERTEXDATA:
1796 case WINED3DFMT_INDEX16:
1797 case WINED3DFMT_INDEX32:
1798 case WINED3DFMT_Q16W16V16U16:
1799 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1800 return WINED3DERR_NOTAVAILABLE;
1803 * Float formats: Not supported right now
1805 case WINED3DFMT_G16R16F:
1806 case WINED3DFMT_G32R32F:
1807 case WINED3DFMT_CxV8U8:
1808 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1809 return WINED3DERR_NOTAVAILABLE;
1812 case WINED3DFMT_G16R16:
1813 case WINED3DFMT_A16B16G16R16:
1814 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1815 return WINED3DERR_NOTAVAILABLE;
1817 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1818 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1819 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1820 * We can do instancing with all shader versions, but we need vertex shaders.
1822 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1823 * to enable instancing. WineD3D doesn't need that and just ignores it.
1825 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1827 case MAKEFOURCC('I','N','S','T'):
1828 TRACE("ATI Instancing check hack\n");
1829 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1830 TRACE_(d3d_caps)("[OK]\n");
1833 TRACE_(d3d_caps)("[FAILED]\n");
1834 return WINED3DERR_NOTAVAILABLE;
1841 TRACE_(d3d_caps)("[FAILED]\n");
1842 return WINED3DERR_NOTAVAILABLE;
1845 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1846 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1847 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1849 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1852 DeviceType, debug_d3ddevicetype(DeviceType),
1853 SourceFormat, debug_d3dformat(SourceFormat),
1854 TargetFormat, debug_d3dformat(TargetFormat));
1858 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1859 subset of a D3DCAPS9 structure. However, it has to come via a void *
1860 as the d3d8 interface cannot import the d3d9 header */
1861 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1863 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1864 int vs_selected_mode;
1865 int ps_selected_mode;
1867 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1869 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1870 return WINED3DERR_INVALIDCALL;
1873 /* FIXME: GL info should be per adapter */
1875 /* If we don't know the device settings, go query them now */
1876 if (!This->isGLInfoValid) {
1877 /* use the desktop window to fill gl caps */
1878 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1880 /* We are running off a real context, save the values */
1881 if (rc) This->isGLInfoValid = TRUE;
1883 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1885 /* This function should *not* be modifying GL caps
1886 * TODO: move the functionality where it belongs */
1887 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1889 /* ------------------------------------------------
1890 The following fields apply to both d3d8 and d3d9
1891 ------------------------------------------------ */
1892 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1893 *pCaps->AdapterOrdinal = Adapter;
1896 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1897 WINED3DCAPS2_FULLSCREENGAMMA;
1899 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1901 *pCaps->CursorCaps = 0;
1904 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1905 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1906 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1907 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1908 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1909 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1910 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1911 WINED3DDEVCAPS_PUREDEVICE |
1912 WINED3DDEVCAPS_HWRASTERIZATION |
1913 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1914 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1915 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1916 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1917 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1919 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1920 WINED3DPMISCCAPS_CULLCCW |
1921 WINED3DPMISCCAPS_CULLCW |
1922 WINED3DPMISCCAPS_COLORWRITEENABLE |
1923 WINED3DPMISCCAPS_CLIPTLVERTS |
1924 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1925 WINED3DPMISCCAPS_MASKZ |
1926 WINED3DPMISCCAPS_BLENDOP;
1928 WINED3DPMISCCAPS_NULLREFERENCE
1929 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1930 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1931 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1932 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1933 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1934 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1936 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1938 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1939 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1940 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1941 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1944 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1945 WINED3DPRASTERCAPS_PAT |
1946 WINED3DPRASTERCAPS_WFOG |
1947 WINED3DPRASTERCAPS_ZFOG |
1948 WINED3DPRASTERCAPS_FOGVERTEX |
1949 WINED3DPRASTERCAPS_FOGTABLE |
1950 WINED3DPRASTERCAPS_FOGRANGE |
1951 WINED3DPRASTERCAPS_STIPPLE |
1952 WINED3DPRASTERCAPS_SUBPIXEL |
1953 WINED3DPRASTERCAPS_ZTEST |
1954 WINED3DPRASTERCAPS_SCISSORTEST |
1955 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1956 WINED3DPRASTERCAPS_DEPTHBIAS;
1958 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1959 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1960 WINED3DPRASTERCAPS_ZBIAS |
1961 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1964 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1965 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1966 WINED3DPRASTERCAPS_ANTIALIASEDGES
1967 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1968 WINED3DPRASTERCAPS_WBUFFER */
1970 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1971 WINED3DPCMPCAPS_EQUAL |
1972 WINED3DPCMPCAPS_GREATER |
1973 WINED3DPCMPCAPS_GREATEREQUAL |
1974 WINED3DPCMPCAPS_LESS |
1975 WINED3DPCMPCAPS_LESSEQUAL |
1976 WINED3DPCMPCAPS_NEVER |
1977 WINED3DPCMPCAPS_NOTEQUAL;
1979 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1980 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1981 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1982 WINED3DPBLENDCAPS_DESTALPHA |
1983 WINED3DPBLENDCAPS_DESTCOLOR |
1984 WINED3DPBLENDCAPS_INVDESTALPHA |
1985 WINED3DPBLENDCAPS_INVDESTCOLOR |
1986 WINED3DPBLENDCAPS_INVSRCALPHA |
1987 WINED3DPBLENDCAPS_INVSRCCOLOR |
1988 WINED3DPBLENDCAPS_ONE |
1989 WINED3DPBLENDCAPS_SRCALPHA |
1990 WINED3DPBLENDCAPS_SRCALPHASAT |
1991 WINED3DPBLENDCAPS_SRCCOLOR |
1992 WINED3DPBLENDCAPS_ZERO;
1994 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1995 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1996 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1997 WINED3DPBLENDCAPS_DESTALPHA |
1998 WINED3DPBLENDCAPS_DESTCOLOR |
1999 WINED3DPBLENDCAPS_INVDESTALPHA |
2000 WINED3DPBLENDCAPS_INVDESTCOLOR |
2001 WINED3DPBLENDCAPS_INVSRCALPHA |
2002 WINED3DPBLENDCAPS_INVSRCCOLOR |
2003 WINED3DPBLENDCAPS_ONE |
2004 WINED3DPBLENDCAPS_SRCALPHA |
2005 WINED3DPBLENDCAPS_SRCALPHASAT |
2006 WINED3DPBLENDCAPS_SRCCOLOR |
2007 WINED3DPBLENDCAPS_ZERO;
2009 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2010 WINED3DPCMPCAPS_EQUAL |
2011 WINED3DPCMPCAPS_GREATER |
2012 WINED3DPCMPCAPS_GREATEREQUAL |
2013 WINED3DPCMPCAPS_LESS |
2014 WINED3DPCMPCAPS_LESSEQUAL |
2015 WINED3DPCMPCAPS_NEVER |
2016 WINED3DPCMPCAPS_NOTEQUAL;
2018 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2019 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2020 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2021 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2022 WINED3DPSHADECAPS_COLORFLATRGB |
2023 WINED3DPSHADECAPS_FOGFLAT |
2024 WINED3DPSHADECAPS_FOGGOURAUD |
2025 WINED3DPSHADECAPS_SPECULARFLATRGB;
2027 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2028 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2029 WINED3DPTEXTURECAPS_BORDER |
2030 WINED3DPTEXTURECAPS_MIPMAP |
2031 WINED3DPTEXTURECAPS_PROJECTED |
2032 WINED3DPTEXTURECAPS_PERSPECTIVE |
2033 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2035 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2036 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2037 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2038 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2041 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2042 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2043 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2044 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2048 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2049 WINED3DPTFILTERCAPS_MAGFPOINT |
2050 WINED3DPTFILTERCAPS_MINFLINEAR |
2051 WINED3DPTFILTERCAPS_MINFPOINT |
2052 WINED3DPTFILTERCAPS_MIPFLINEAR |
2053 WINED3DPTFILTERCAPS_MIPFPOINT |
2054 WINED3DPTFILTERCAPS_LINEAR |
2055 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2056 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2057 WINED3DPTFILTERCAPS_MIPLINEAR |
2058 WINED3DPTFILTERCAPS_MIPNEAREST |
2059 WINED3DPTFILTERCAPS_NEAREST;
2061 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2062 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2063 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2066 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2067 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2068 WINED3DPTFILTERCAPS_MAGFPOINT |
2069 WINED3DPTFILTERCAPS_MINFLINEAR |
2070 WINED3DPTFILTERCAPS_MINFPOINT |
2071 WINED3DPTFILTERCAPS_MIPFLINEAR |
2072 WINED3DPTFILTERCAPS_MIPFPOINT |
2073 WINED3DPTFILTERCAPS_LINEAR |
2074 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2075 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2076 WINED3DPTFILTERCAPS_MIPLINEAR |
2077 WINED3DPTFILTERCAPS_MIPNEAREST |
2078 WINED3DPTFILTERCAPS_NEAREST;
2080 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2081 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2082 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2085 *pCaps->CubeTextureFilterCaps = 0;
2087 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2088 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2089 WINED3DPTFILTERCAPS_MAGFPOINT |
2090 WINED3DPTFILTERCAPS_MINFLINEAR |
2091 WINED3DPTFILTERCAPS_MINFPOINT |
2092 WINED3DPTFILTERCAPS_MIPFLINEAR |
2093 WINED3DPTFILTERCAPS_MIPFPOINT |
2094 WINED3DPTFILTERCAPS_LINEAR |
2095 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2096 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2097 WINED3DPTFILTERCAPS_MIPLINEAR |
2098 WINED3DPTFILTERCAPS_MIPNEAREST |
2099 WINED3DPTFILTERCAPS_NEAREST;
2101 *pCaps->VolumeTextureFilterCaps = 0;
2103 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2104 WINED3DPTADDRESSCAPS_CLAMP |
2105 WINED3DPTADDRESSCAPS_WRAP;
2107 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2108 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2110 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2111 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2113 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2114 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2117 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2118 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2119 WINED3DPTADDRESSCAPS_CLAMP |
2120 WINED3DPTADDRESSCAPS_WRAP;
2121 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2122 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2124 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2125 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2127 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2128 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2131 *pCaps->VolumeTextureAddressCaps = 0;
2133 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2134 WINED3DLINECAPS_ZTEST;
2136 WINED3DLINECAPS_BLEND
2137 WINED3DLINECAPS_ALPHACMP
2138 WINED3DLINECAPS_FOG */
2140 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2141 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2143 if(GL_SUPPORT(EXT_TEXTURE3D))
2144 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2146 *pCaps->MaxVolumeExtent = 0;
2148 *pCaps->MaxTextureRepeat = 32768;
2149 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2150 *pCaps->MaxVertexW = 1.0;
2152 *pCaps->GuardBandLeft = 0;
2153 *pCaps->GuardBandTop = 0;
2154 *pCaps->GuardBandRight = 0;
2155 *pCaps->GuardBandBottom = 0;
2157 *pCaps->ExtentsAdjust = 0;
2159 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2160 WINED3DSTENCILCAPS_INCRSAT |
2161 WINED3DSTENCILCAPS_INVERT |
2162 WINED3DSTENCILCAPS_KEEP |
2163 WINED3DSTENCILCAPS_REPLACE |
2164 WINED3DSTENCILCAPS_ZERO;
2165 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2166 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2167 WINED3DSTENCILCAPS_INCR;
2169 if ( This->dxVersion > 8 &&
2170 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2171 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2172 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2175 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2177 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2178 WINED3DTEXOPCAPS_ADDSIGNED |
2179 WINED3DTEXOPCAPS_ADDSIGNED2X |
2180 WINED3DTEXOPCAPS_MODULATE |
2181 WINED3DTEXOPCAPS_MODULATE2X |
2182 WINED3DTEXOPCAPS_MODULATE4X |
2183 WINED3DTEXOPCAPS_SELECTARG1 |
2184 WINED3DTEXOPCAPS_SELECTARG2 |
2185 WINED3DTEXOPCAPS_DISABLE;
2187 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2188 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2189 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2190 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2191 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2192 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2193 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2194 WINED3DTEXOPCAPS_LERP |
2195 WINED3DTEXOPCAPS_SUBTRACT;
2197 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2198 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2199 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2200 WINED3DTEXOPCAPS_MULTIPLYADD |
2201 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2202 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2203 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2205 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2206 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2208 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2209 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2210 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2215 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2217 WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2218 WINED3DTEXOPCAPS_PREMODULATE */
2221 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2222 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2223 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2224 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2228 #if 0 /* TODO: Blends support in drawprim */
2229 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2231 *pCaps->MaxVertexBlendMatrices = 0;
2233 *pCaps->MaxVertexBlendMatrixIndex = 1;
2235 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2236 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2239 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2240 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2241 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2242 WINED3DVTXPCAPS_LOCALVIEWER |
2243 WINED3DVTXPCAPS_VERTEXFOG |
2244 WINED3DVTXPCAPS_TEXGEN;
2246 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2248 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2249 *pCaps->MaxVertexIndex = 0xFFFFF;
2250 *pCaps->MaxStreams = MAX_STREAMS;
2251 *pCaps->MaxStreamStride = 1024;
2253 if (vs_selected_mode == SHADER_GLSL) {
2254 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2255 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2256 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2257 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2258 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2259 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2261 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2262 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2263 } else if (vs_selected_mode == SHADER_ARB) {
2264 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2265 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2266 } else if (vs_selected_mode == SHADER_SW) {
2267 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2268 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2270 *pCaps->VertexShaderVersion = 0;
2271 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2274 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2276 if (ps_selected_mode == SHADER_GLSL) {
2277 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2278 in case of GeforceFX cards. */
2279 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2280 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2282 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2283 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2284 *pCaps->PixelShader1xMaxValue = 1.0;
2285 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2286 } else if (ps_selected_mode == SHADER_ARB) {
2287 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2288 *pCaps->PixelShader1xMaxValue = 1.0;
2289 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2290 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2291 } else if (ps_selected_mode = SHADER_SW) {
2292 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2293 *pCaps->PixelShader1xMaxValue = 1.0;
2294 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2296 *pCaps->PixelShaderVersion = 0;
2297 *pCaps->PixelShader1xMaxValue = 0.0;
2298 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2301 /* ------------------------------------------------
2302 The following fields apply to d3d9 only
2303 ------------------------------------------------ */
2304 if (This->dxVersion > 8) {
2305 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2306 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2307 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2308 *pCaps->MaxNpatchTessellationLevel = 0;
2309 *pCaps->MasterAdapterOrdinal = 0;
2310 *pCaps->AdapterOrdinalInGroup = 0;
2311 *pCaps->NumberOfAdaptersInGroup = 1;
2313 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2314 /* OpenGL supports all the formats below, perhaps not always
2315 * without conversion, but it supports them.
2316 * Further GLSL doesn't seem to have an official unsigned type so
2317 * don't advertise it yet as I'm not sure how we handle it.
2318 * We might need to add some clamping in the shader engine to
2320 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2321 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2322 WINED3DDTCAPS_UBYTE4N |
2323 WINED3DDTCAPS_SHORT2N |
2324 WINED3DDTCAPS_SHORT4N |
2325 WINED3DDTCAPS_FLOAT16_2 |
2326 WINED3DDTCAPS_FLOAT16_4;
2329 *pCaps->DeclTypes = 0;
2331 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2334 *pCaps->StretchRectFilterCaps = 0;
2335 *pCaps->VertexTextureFilterCaps = 0;
2337 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2338 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2339 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2340 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2341 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2342 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2343 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2345 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2346 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2347 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2348 *pCaps->VS20Caps.Caps = 0;
2349 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2350 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2351 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2353 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2354 *pCaps->MaxVertexShader30InstructionSlots = 0;
2355 } else { /* VS 1.x */
2356 *pCaps->VS20Caps.Caps = 0;
2357 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2358 *pCaps->VS20Caps.NumTemps = 0;
2359 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2361 *pCaps->MaxVShaderInstructionsExecuted = 0;
2362 *pCaps->MaxVertexShader30InstructionSlots = 0;
2365 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2366 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2367 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2369 /* 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 */
2370 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2371 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2372 WINED3DPS20CAPS_PREDICATION |
2373 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2374 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2375 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2376 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2377 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2378 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2380 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2381 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2382 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2383 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2384 *pCaps->PS20Caps.Caps = 0;
2385 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2386 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2387 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2388 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2390 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2391 *pCaps->MaxPixelShader30InstructionSlots = 0;
2392 } else { /* PS 1.x */
2393 *pCaps->PS20Caps.Caps = 0;
2394 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2395 *pCaps->PS20Caps.NumTemps = 0;
2396 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2397 *pCaps->PS20Caps.NumInstructionSlots = 0;
2399 *pCaps->MaxPShaderInstructionsExecuted = 0;
2400 *pCaps->MaxPixelShader30InstructionSlots = 0;
2407 static unsigned int glsl_program_key_hash(void *key) {
2408 glsl_program_key_t *k = (glsl_program_key_t *)key;
2410 unsigned int hash = k->vshader | k->pshader << 16;
2411 hash += ~(hash << 15);
2412 hash ^= (hash >> 10);
2413 hash += (hash << 3);
2414 hash ^= (hash >> 6);
2415 hash += ~(hash << 11);
2416 hash ^= (hash >> 16);
2421 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2422 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2423 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2425 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2428 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2429 and fields being inserted in the middle, a new structure is used in place */
2430 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2431 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2434 IWineD3DDeviceImpl *object = NULL;
2435 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2437 HRESULT temp_result;
2439 /* Validate the adapter number */
2440 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2441 return WINED3DERR_INVALIDCALL;
2444 /* Create a WineD3DDevice object */
2445 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2446 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2447 TRACE("Created WineD3DDevice object @ %p\n", object);
2448 if (NULL == object) {
2449 return WINED3DERR_OUTOFVIDEOMEMORY;
2452 /* Set up initial COM information */
2453 object->lpVtbl = &IWineD3DDevice_Vtbl;
2455 object->wineD3D = iface;
2456 IWineD3D_AddRef(object->wineD3D);
2457 object->parent = parent;
2459 /* Set the state up as invalid until the device is fully created */
2460 object->state = WINED3DERR_DRIVERINTERNALERROR;
2462 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2463 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2465 /* Save the creation parameters */
2466 object->createParms.AdapterOrdinal = Adapter;
2467 object->createParms.DeviceType = DeviceType;
2468 object->createParms.hFocusWindow = hFocusWindow;
2469 object->createParms.BehaviorFlags = BehaviourFlags;
2471 /* Initialize other useful values */
2472 object->adapterNo = Adapter;
2473 object->devType = DeviceType;
2475 TRACE("(%p) : Creating stateblock\n", This);
2476 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2477 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2479 (IWineD3DStateBlock **)&object->stateBlock,
2480 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2481 WARN("Failed to create stateblock\n");
2482 goto create_device_error;
2484 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2485 object->updateStateBlock = object->stateBlock;
2486 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2487 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2489 /* Setup some defaults for creating the implicit swapchain */
2491 /* FIXME: GL info should be per adapter */
2492 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2494 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2495 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2496 object->shader_backend = &glsl_shader_backend;
2497 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2498 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2499 object->shader_backend = &arb_program_shader_backend;
2501 object->shader_backend = &none_shader_backend;
2504 /* This function should *not* be modifying GL caps
2505 * TODO: move the functionality where it belongs */
2506 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2508 temp_result = allocate_shader_constants(object->updateStateBlock);
2509 if (WINED3D_OK != temp_result)
2512 object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2514 object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
2516 /* set the state of the device to valid */
2517 object->state = WINED3D_OK;
2519 /* Get the initial screen setup for ddraw */
2520 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2521 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2523 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2527 create_device_error:
2529 /* Set the device state to error */
2530 object->state = WINED3DERR_DRIVERINTERNALERROR;
2532 if (object->updateStateBlock != NULL) {
2533 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2534 object->updateStateBlock = NULL;
2536 if (object->stateBlock != NULL) {
2537 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2538 object->stateBlock = NULL;
2540 if (object->render_targets[0] != NULL) {
2541 IWineD3DSurface_Release(object->render_targets[0]);
2542 object->render_targets[0] = NULL;
2544 if (object->stencilBufferTarget != NULL) {
2545 IWineD3DSurface_Release(object->stencilBufferTarget);
2546 object->stencilBufferTarget = NULL;
2548 HeapFree(GetProcessHeap(), 0, object);
2549 *ppReturnedDeviceInterface = NULL;
2550 return WINED3DERR_INVALIDCALL;
2554 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2555 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2556 IUnknown_AddRef(This->parent);
2557 *pParent = This->parent;
2561 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2562 IUnknown* surfaceParent;
2563 TRACE("(%p) call back\n", pSurface);
2565 /* Now, release the parent, which will take care of cleaning up the surface for us */
2566 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2567 IUnknown_Release(surfaceParent);
2568 return IUnknown_Release(surfaceParent);
2571 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2572 IUnknown* volumeParent;
2573 TRACE("(%p) call back\n", pVolume);
2575 /* Now, release the parent, which will take care of cleaning up the volume for us */
2576 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2577 IUnknown_Release(volumeParent);
2578 return IUnknown_Release(volumeParent);
2581 /**********************************************************
2582 * IWineD3D VTbl follows
2583 **********************************************************/
2585 const IWineD3DVtbl IWineD3D_Vtbl =
2588 IWineD3DImpl_QueryInterface,
2589 IWineD3DImpl_AddRef,
2590 IWineD3DImpl_Release,
2592 IWineD3DImpl_GetParent,
2593 IWineD3DImpl_GetAdapterCount,
2594 IWineD3DImpl_RegisterSoftwareDevice,
2595 IWineD3DImpl_GetAdapterMonitor,
2596 IWineD3DImpl_GetAdapterModeCount,
2597 IWineD3DImpl_EnumAdapterModes,
2598 IWineD3DImpl_GetAdapterDisplayMode,
2599 IWineD3DImpl_GetAdapterIdentifier,
2600 IWineD3DImpl_CheckDeviceMultiSampleType,
2601 IWineD3DImpl_CheckDepthStencilMatch,
2602 IWineD3DImpl_CheckDeviceType,
2603 IWineD3DImpl_CheckDeviceFormat,
2604 IWineD3DImpl_CheckDeviceFormatConversion,
2605 IWineD3DImpl_GetDeviceCaps,
2606 IWineD3DImpl_CreateDevice