wined3d: replace #ifdef with if() for DEBUG_SINGLE_MODE.
[wine/wine64.git] / dlls / wined3d / directx.c
blob58b00d7c23ca1c7c91261dba4142d86a49f38a16
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
29 #endif
32 #include "config.h"
33 #include <assert.h>
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
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 )
56 Display *display;
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;
61 return display;
64 /* lookup tables */
65 int minLookup[MAX_LOOKUPS];
66 int maxLookup[MAX_LOOKUPS];
67 DWORD *stateLookup[MAX_LOOKUPS];
69 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
72 /**
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) {
94 GLXContext glCtx;
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);
101 return;
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);
118 LEAVE_GL();
121 static BOOL WineD3D_CreateFakeGLContext(void) {
122 XVisualInfo* visInfo;
123 GLXContext glCtx;
125 ENTER_GL();
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);
141 visInfo = NULL;
142 glCtx = glXGetCurrentContext();
144 if (!glCtx) {
145 Drawable drawable;
146 XVisualInfo template;
147 Visual* visual;
148 int num;
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;
159 } else {
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);
164 if (!visInfo) {
165 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
166 goto fail;
169 /* Create a GL context */
170 glCtx = glXCreateContext(wined3d_fake_gl_context_display, visInfo, NULL, GL_TRUE);
171 if (!glCtx) {
172 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
173 goto fail;
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");
179 goto fail;
182 XFree(visInfo);
186 ret:
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);
191 return TRUE;
192 fail:
193 if(visInfo) XFree(visInfo);
194 if(glCtx) glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
195 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
196 LEAVE_GL();
197 return FALSE;
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);
213 *ppobj = This;
214 return S_OK;
216 *ppobj = NULL;
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);
225 return refCount;
228 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
229 IWineD3DImpl *This = (IWineD3DImpl *)iface;
230 ULONG ref;
231 TRACE("(%p) : Releasing from %d\n", This, This->ref);
232 ref = InterlockedDecrement(&This->ref);
233 if (ref == 0) {
234 HeapFree(GetProcessHeap(), 0, This);
237 return ref;
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,
246 int* ps_selected,
247 int* vs_selected) {
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;
261 } else {
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;
274 } else {
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) {
286 case SHADER_GLSL:
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 - MAX_CONST_I - 1;
289 break;
290 case SHADER_ARB:
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;
295 break;
296 case SHADER_SW:
297 gl_info->max_vshader_constantsF = 96; /* TODO: Fixup software shaders */
298 break;
299 default:
300 gl_info->max_vshader_constantsF = 0;
301 break;
304 switch (ps_selected_mode) {
305 case SHADER_GLSL:
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 - MAX_CONST_I;
312 break;
313 case SHADER_ARB:
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;
318 break;
319 case SHADER_SW:
320 gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */
321 break;
322 default:
323 gl_info->max_pshader_constantsF = 0;
324 break;
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;
340 GLint gl_max;
341 GLfloat gl_floatv[2];
342 Bool test = 0;
343 int major, minor;
344 BOOL return_value = TRUE;
345 int i;
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)
357 gl_string = "None";
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);
364 } else {
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;
381 } else {
382 gl_info->gl_vendor = VENDOR_WINE;
384 } else {
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) {
396 case VENDOR_NVIDIA:
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));
400 break;
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));
406 break;
409 while (*gl_string_cursor == ' ') {
410 ++gl_string_cursor;
413 if (!*gl_string_cursor) {
414 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
415 break;
418 major = atoi(gl_string_cursor);
419 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
420 ++gl_string_cursor;
423 if (*gl_string_cursor++ != '.') {
424 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
425 break;
428 minor = atoi(gl_string_cursor);
429 minor = major*100+minor;
430 major = 10;
432 break;
434 case VENDOR_ATI:
435 major = minor = 0;
436 gl_string_cursor = strchr(gl_string, '-');
437 if (gl_string_cursor) {
438 int error = 0;
439 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')
443 error = 1;
444 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
445 error = 1;
446 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
447 error = 1;
448 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
449 error = 1;
451 /* Mark version number as malformed */
452 if (error)
453 gl_string_cursor = 0;
456 if (!gl_string_cursor)
457 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
458 else {
459 major = *gl_string_cursor - '0';
460 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
462 break;
464 case VENDOR_INTEL:
465 case VENDOR_MESA:
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) {
470 char tmp[16];
471 int cursor = 0;
473 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
474 tmp[cursor++] = *gl_string_cursor;
475 ++gl_string_cursor;
477 tmp[cursor] = 0;
478 major = atoi(tmp);
480 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
481 ++gl_string_cursor;
483 cursor = 0;
484 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
485 tmp[cursor++] = *gl_string_cursor;
486 ++gl_string_cursor;
488 tmp[cursor] = 0;
489 minor = atoi(tmp);
491 break;
493 default:
494 major = 0;
495 minor = 9;
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);
528 GL_EXT_FUNCS_GEN;
529 GLX_EXT_FUNCS_GEN;
530 #undef USE_GL_FUNC
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 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
550 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
551 TRACE_(d3d_caps)("GL_Extensions reported:\n");
553 if (NULL == GL_Extensions) {
554 ERR(" GL_Extensions returns NULL\n");
555 } else {
556 while (*GL_Extensions != 0x00) {
557 const char *Start = GL_Extensions;
558 char ThisExtn[256];
560 memset(ThisExtn, 0x00, sizeof(ThisExtn));
561 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
562 GL_Extensions++;
564 memcpy(ThisExtn, Start, (GL_Extensions - Start));
565 TRACE_(d3d_caps)("- %s\n", ThisExtn);
568 * ARB
570 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
571 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
572 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
573 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
574 gl_info->max_buffers = gl_max;
575 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
576 gl_info->ps_arb_version = PS_VERSION_11;
577 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
578 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
579 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
580 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
581 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
582 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
583 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
584 gl_info->ps_arb_constantsF = gl_max;
585 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
586 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
587 gl_info->ps_arb_max_temps = gl_max;
588 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
589 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
590 gl_info->ps_arb_max_instructions = gl_max;
591 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
592 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
593 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
594 gl_max /= 4;
595 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
596 gl_info->ps_glsl_constantsF = gl_max;
597 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
598 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
599 gl_info->supported[ARB_IMAGING] = TRUE;
600 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
601 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
602 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
603 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
604 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
605 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
606 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
607 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
608 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
609 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
610 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
611 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
612 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
613 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
614 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
615 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
616 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
617 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
618 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
619 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
620 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
621 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
622 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
623 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
624 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
625 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
626 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
627 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
628 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
629 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
630 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
631 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
632 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
633 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
634 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
635 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
636 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
637 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
638 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
639 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
640 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
641 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
642 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
643 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
644 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
645 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
646 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
647 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
648 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
649 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
650 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
651 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
652 gl_info->vs_arb_version = VS_VERSION_11;
653 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
654 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
655 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
656 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
657 gl_info->vs_arb_constantsF = gl_max;
658 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
659 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
660 gl_info->vs_arb_max_temps = gl_max;
661 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
662 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
663 gl_info->vs_arb_max_instructions = gl_max;
664 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
665 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
666 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
667 gl_max /= 4;
668 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
669 gl_info->vs_glsl_constantsF = gl_max;
670 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
671 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
672 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
673 gl_info->max_blends = gl_max;
674 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
675 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
676 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
677 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
678 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
679 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
680 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
681 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
682 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
683 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
685 * EXT
687 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
688 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
689 gl_info->supported[EXT_FOG_COORD] = TRUE;
690 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
691 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
692 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
693 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
694 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
695 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
696 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
697 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
698 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
699 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
700 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
701 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
702 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
703 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
704 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
705 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
706 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
707 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
708 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
709 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
710 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
711 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
712 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
713 gl_info->supported[EXT_TEXTURE3D] = TRUE;
714 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
715 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
716 gl_info->max_texture3d_size = gl_max;
717 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
718 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
719 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
720 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
721 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
722 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
723 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
724 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
725 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
726 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
727 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
728 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
729 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
730 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
731 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
732 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
733 gl_info->max_anisotropy = gl_max;
734 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
735 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
736 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
737 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
738 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
739 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
740 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
741 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
742 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
745 * NVIDIA
747 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
748 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
749 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
750 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
751 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
752 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
753 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
754 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
755 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
756 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
757 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
758 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
759 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
760 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
761 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
762 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
763 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
764 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
765 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
766 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
767 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
768 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
769 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
770 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
771 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
772 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
773 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
774 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
775 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
776 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
777 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
778 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
779 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
780 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
781 gl_info->vs_nv_version = VS_VERSION_30;
782 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
783 gl_info->vs_nv_version = VS_VERSION_20;
784 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
785 gl_info->vs_nv_version = VS_VERSION_11;
786 else
787 gl_info->vs_nv_version = VS_VERSION_10;
788 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
789 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
792 * ATI
794 /** TODO */
795 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
796 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
797 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
798 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
799 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
800 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
801 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
802 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
803 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
804 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
805 gl_info->vs_ati_version = VS_VERSION_11;
806 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
807 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
811 if (*GL_Extensions == ' ') GL_Extensions++;
814 checkGLcall("extension detection\n");
816 /* In some cases the number of texture stages can be larger than the number
817 * of samplers. The GF4 for example can use only 2 samplers (no fragment
818 * shaders), but 8 texture stages (register combiners). */
819 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
821 /* We can only use ORM_FBO when the hardware supports it. */
822 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
823 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
824 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
827 /* MRTs are currently only supported when FBOs are used. */
828 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
829 gl_info->max_buffers = 1;
832 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
833 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
834 * in case of the latest videocards in the number of pixel/vertex pipelines.
836 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
837 * rendering. Various games use this information to get a rough estimation of the features of the card
838 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
839 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
840 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
841 * not the PCI id.
843 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
844 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
845 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
846 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
847 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
848 * is used for rendering which is not always the case). This would work but it is not very portable. Second
849 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
850 * is limited.
852 * As said most games only use the PCI id to get an indication of the capabilities of the card.
853 * It doesn't really matter if the given id is the correct one if we return the id of a card with
854 * similar 3d features.
856 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
857 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
858 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
859 * won't pass we return a default card. This way is better than maintaining a full card database as even
860 * without a full database we can return a card with similar features. Second the size of the database
861 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
862 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
863 * to distinguishes between different models from that family.
865 switch (gl_info->gl_vendor) {
866 case VENDOR_NVIDIA:
867 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
868 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
870 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
871 if (strstr(gl_info->gl_renderer, "7800") ||
872 strstr(gl_info->gl_renderer, "7900") ||
873 strstr(gl_info->gl_renderer, "7950") ||
874 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
875 strstr(gl_info->gl_renderer, "Quadro FX 5"))
876 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
877 else if(strstr(gl_info->gl_renderer, "6800") ||
878 strstr(gl_info->gl_renderer, "7600"))
879 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
880 else if(strstr(gl_info->gl_renderer, "6600") ||
881 strstr(gl_info->gl_renderer, "6610") ||
882 strstr(gl_info->gl_renderer, "6700"))
883 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
884 else
885 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
886 } else if(WINE_D3D9_CAPABLE(gl_info)) {
887 if (strstr(gl_info->gl_renderer, "5800") ||
888 strstr(gl_info->gl_renderer, "5900") ||
889 strstr(gl_info->gl_renderer, "5950") ||
890 strstr(gl_info->gl_renderer, "Quadro FX"))
891 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
892 else if(strstr(gl_info->gl_renderer, "5600") ||
893 strstr(gl_info->gl_renderer, "5650") ||
894 strstr(gl_info->gl_renderer, "5700") ||
895 strstr(gl_info->gl_renderer, "5750"))
896 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
897 else
898 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
899 } else if(WINE_D3D8_CAPABLE(gl_info)) {
900 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
901 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
902 else
903 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
904 } else if(WINE_D3D7_CAPABLE(gl_info)) {
905 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
906 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
907 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
908 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
909 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
910 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
911 else
912 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
913 } else {
914 if (strstr(gl_info->gl_renderer, "TNT2"))
915 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
916 else
917 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
919 break;
920 case VENDOR_ATI:
921 if(WINE_D3D9_CAPABLE(gl_info)) {
922 /* Radeon R5xx */
923 if (strstr(gl_info->gl_renderer, "X1600") ||
924 strstr(gl_info->gl_renderer, "X1800") ||
925 strstr(gl_info->gl_renderer, "X1900") ||
926 strstr(gl_info->gl_renderer, "X1950"))
927 gl_info->gl_card = CARD_ATI_RADEON_X1600;
928 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
929 else if(strstr(gl_info->gl_renderer, "X700") ||
930 strstr(gl_info->gl_renderer, "X800") ||
931 strstr(gl_info->gl_renderer, "X850") ||
932 strstr(gl_info->gl_renderer, "X1300") ||
933 strstr(gl_info->gl_renderer, "X1400"))
934 gl_info->gl_card = CARD_ATI_RADEON_X700;
935 /* Radeon R3xx */
936 else
937 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
938 } else if(WINE_D3D8_CAPABLE(gl_info)) {
939 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
940 } else if(WINE_D3D7_CAPABLE(gl_info)) {
941 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
942 } else
943 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
944 break;
945 case VENDOR_INTEL:
946 if (strstr(gl_info->gl_renderer, "915GM")) {
947 gl_info->gl_card = CARD_INTEL_I915GM;
948 } else if (strstr(gl_info->gl_renderer, "915G")) {
949 gl_info->gl_card = CARD_INTEL_I915G;
950 } else if (strstr(gl_info->gl_renderer, "865G")) {
951 gl_info->gl_card = CARD_INTEL_I865G;
952 } else if (strstr(gl_info->gl_renderer, "855G")) {
953 gl_info->gl_card = CARD_INTEL_I855G;
954 } else if (strstr(gl_info->gl_renderer, "830G")) {
955 gl_info->gl_card = CARD_INTEL_I830G;
956 } else {
957 gl_info->gl_card = CARD_INTEL_I915G;
959 break;
960 case VENDOR_MESA:
961 case VENDOR_WINE:
962 default:
963 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
964 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
965 * them a good generic choice.
967 gl_info->gl_vendor = VENDOR_NVIDIA;
968 if(WINE_D3D9_CAPABLE(gl_info))
969 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
970 else if(WINE_D3D8_CAPABLE(gl_info))
971 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
972 else if(WINE_D3D7_CAPABLE(gl_info))
973 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
974 else if(WINE_D3D6_CAPABLE(gl_info))
975 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
976 else
977 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
979 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
981 /* Load all the lookup tables
982 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
983 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
984 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
986 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
987 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
990 for (i = 0; i < MAX_LOOKUPS; i++) {
991 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
994 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
995 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
996 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
997 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
998 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
999 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1000 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1001 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1002 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1003 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1005 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1006 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1007 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1008 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1009 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1012 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1013 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1014 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1015 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1016 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1017 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1018 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1019 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1020 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1021 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1022 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1023 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1024 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1026 /* TODO: config lookups */
1028 if (display != NULL) {
1029 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1030 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1032 if (NULL == GLX_Extensions) {
1033 ERR(" GLX_Extensions returns NULL\n");
1034 } else {
1035 while (*GLX_Extensions != 0x00) {
1036 const char *Start = GLX_Extensions;
1037 char ThisExtn[256];
1039 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1040 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1041 GLX_Extensions++;
1043 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1044 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1045 if (*GLX_Extensions == ' ') GLX_Extensions++;
1051 WineD3D_ReleaseFakeGLContext();
1052 return return_value;
1055 /**********************************************************
1056 * IWineD3D implementation follows
1057 **********************************************************/
1059 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1060 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1062 /* FIXME: Set to one for now to imply the display */
1063 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1064 return 1;
1067 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1068 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1069 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1070 return WINED3D_OK;
1073 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1074 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1075 POINT pt = { -1, -1 };
1077 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1078 return NULL;
1081 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1082 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1085 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1086 of the same bpp but different resolutions */
1088 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1089 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1090 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1091 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1093 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1094 return 0;
1097 if (Adapter == 0) { /* Display */
1098 int i = 0;
1099 int j = 0;
1101 if (!DEBUG_SINGLE_MODE) {
1102 DEVMODEW DevModeW;
1104 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1105 j++;
1106 switch (Format)
1108 case WINED3DFMT_UNKNOWN:
1109 if (DevModeW.dmBitsPerPel == 32 ||
1110 DevModeW.dmBitsPerPel == 16) i++;
1111 break;
1112 case WINED3DFMT_X8R8G8B8:
1113 if (DevModeW.dmBitsPerPel == 32) i++;
1114 break;
1115 case WINED3DFMT_R5G6B5:
1116 if (DevModeW.dmBitsPerPel == 16) i++;
1117 break;
1118 default:
1119 /* Skip other modes as they do not match the requested format */
1120 break;
1123 } else {
1124 i = 1;
1125 j = 1;
1128 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1129 return i;
1130 } else {
1131 FIXME_(d3d_caps)("Adapter not primary display\n");
1133 return 0;
1136 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1137 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1138 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1139 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1141 /* Validate the parameters as much as possible */
1142 if (NULL == pMode ||
1143 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1144 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1145 return WINED3DERR_INVALIDCALL;
1148 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1149 DEVMODEW DevModeW;
1150 int ModeIdx = 0;
1151 int i = 0;
1152 int j = 0;
1154 /* If we are filtering to a specific format (D3D9), then need to skip
1155 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1156 just count through the ones with valid bit depths */
1157 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1158 switch (Format)
1160 case WINED3DFMT_UNKNOWN:
1161 if (DevModeW.dmBitsPerPel == 32 ||
1162 DevModeW.dmBitsPerPel == 16) i++;
1163 break;
1164 case WINED3DFMT_X8R8G8B8:
1165 if (DevModeW.dmBitsPerPel == 32) i++;
1166 break;
1167 case WINED3DFMT_R5G6B5:
1168 if (DevModeW.dmBitsPerPel == 16) i++;
1169 break;
1170 default:
1171 /* Modes that don't match what we support can get an early-out */
1172 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1173 return WINED3DERR_INVALIDCALL;
1177 if (i == 0) {
1178 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1179 return WINED3DERR_INVALIDCALL;
1181 ModeIdx = j - 1;
1183 /* Now get the display mode via the calculated index */
1184 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1185 pMode->Width = DevModeW.dmPelsWidth;
1186 pMode->Height = DevModeW.dmPelsHeight;
1187 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1188 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1189 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1191 if (Format == WINED3DFMT_UNKNOWN)
1193 switch (DevModeW.dmBitsPerPel)
1195 case 16:
1196 pMode->Format = WINED3DFMT_R5G6B5;
1197 break;
1198 case 32:
1199 pMode->Format = WINED3DFMT_X8R8G8B8;
1200 break;
1201 default:
1202 pMode->Format = WINED3DFMT_UNKNOWN;
1203 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1205 } else {
1206 pMode->Format = Format;
1208 } else {
1209 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1210 return WINED3DERR_INVALIDCALL;
1213 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1214 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1215 DevModeW.dmBitsPerPel);
1217 } else if (DEBUG_SINGLE_MODE) {
1218 /* Return one setting of the format requested */
1219 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1220 pMode->Width = 800;
1221 pMode->Height = 600;
1222 pMode->RefreshRate = 60;
1223 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1224 } else {
1225 FIXME_(d3d_caps)("Adapter not primary display\n");
1228 return WINED3D_OK;
1231 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1232 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1233 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1235 if (NULL == pMode ||
1236 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1237 return WINED3DERR_INVALIDCALL;
1240 if (Adapter == 0) { /* Display */
1241 int bpp = 0;
1242 DEVMODEW DevModeW;
1244 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1245 pMode->Width = DevModeW.dmPelsWidth;
1246 pMode->Height = DevModeW.dmPelsHeight;
1247 bpp = DevModeW.dmBitsPerPel;
1248 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1249 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1251 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1254 switch (bpp) {
1255 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1256 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1257 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1258 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1259 default: pMode->Format = WINED3DFMT_UNKNOWN;
1262 } else {
1263 FIXME_(d3d_caps)("Adapter not primary display\n");
1266 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1267 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1268 return WINED3D_OK;
1271 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1272 Display *display;
1273 HDC device_context;
1274 /* only works with one adapter at the moment... */
1276 /* Get the display */
1277 device_context = GetDC(0);
1278 display = get_display(device_context);
1279 ReleaseDC(0, device_context);
1280 return display;
1283 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1284 and fields being inserted in the middle, a new structure is used in place */
1285 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1286 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1287 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1289 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1291 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1292 return WINED3DERR_INVALIDCALL;
1295 if (Adapter == 0) { /* Display - only device supported for now */
1297 BOOL isGLInfoValid = This->isGLInfoValid;
1299 /* FillGLCaps updates gl_info, but we only want to store and
1300 reuse the values once we have a context which is valid. Values from
1301 a temporary context may differ from the final ones */
1302 if (!isGLInfoValid) {
1303 /* If we don't know the device settings, go query them now */
1304 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1307 /* If it worked, return the information requested */
1308 if (isGLInfoValid) {
1309 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1310 strcpy(pIdentifier->Driver, "Display");
1311 strcpy(pIdentifier->Description, "Direct3D HAL");
1313 /* Note dx8 doesn't supply a DeviceName */
1314 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1315 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1316 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1317 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1318 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1319 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1320 *(pIdentifier->SubSysId) = 0;
1321 *(pIdentifier->Revision) = 0;
1323 } else {
1325 /* If it failed, return dummy values from an NVidia driver */
1326 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1327 strcpy(pIdentifier->Driver, "Display");
1328 strcpy(pIdentifier->Description, "Direct3D HAL");
1329 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1330 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1331 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1332 /* 71.74 is a current Linux Nvidia driver version */
1333 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1334 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1335 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1336 *(pIdentifier->SubSysId) = 0;
1337 *(pIdentifier->Revision) = 0;
1340 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1341 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1342 *(pIdentifier->WHQLLevel) = 0;
1343 } else {
1344 *(pIdentifier->WHQLLevel) = 1;
1347 } else {
1348 FIXME_(d3d_caps)("Adapter not primary display\n");
1351 return WINED3D_OK;
1354 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1355 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1356 int gl_test;
1357 int rb, gb, bb, ab, type, buf_sz;
1359 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1360 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1361 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1362 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1363 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1364 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1366 switch (Format) {
1367 case WINED3DFMT_X8R8G8B8:
1368 case WINED3DFMT_R8G8B8:
1369 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1370 break;
1371 case WINED3DFMT_A8R8G8B8:
1372 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1373 break;
1374 case WINED3DFMT_A2R10G10B10:
1375 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1376 break;
1377 case WINED3DFMT_X1R5G5B5:
1378 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1379 break;
1380 case WINED3DFMT_A1R5G5B5:
1381 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1382 break;
1383 case WINED3DFMT_X4R4G4B4:
1384 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1385 break;
1386 case WINED3DFMT_R5G6B5:
1387 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1388 break;
1389 case WINED3DFMT_R3G3B2:
1390 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1391 break;
1392 case WINED3DFMT_A8P8:
1393 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1394 break;
1395 case WINED3DFMT_P8:
1396 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1397 break;
1398 default:
1399 break;
1401 return FALSE;
1402 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1403 switch (Format) {
1404 case WINED3DFMT_X8R8G8B8:
1405 case WINED3DFMT_R8G8B8:
1406 case WINED3DFMT_A8R8G8B8:
1407 case WINED3DFMT_A2R10G10B10:
1408 case WINED3DFMT_X1R5G5B5:
1409 case WINED3DFMT_A1R5G5B5:
1410 case WINED3DFMT_R5G6B5:
1411 case WINED3DFMT_R3G3B2:
1412 case WINED3DFMT_A8P8:
1413 case WINED3DFMT_P8:
1414 return TRUE;
1415 default:
1416 break;
1418 return FALSE;
1419 #endif
1422 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1423 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1424 int gl_test;
1425 int db, sb;
1427 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1428 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1430 switch (Format) {
1431 case WINED3DFMT_D16:
1432 case WINED3DFMT_D16_LOCKABLE:
1433 if (16 == db) return TRUE;
1434 break;
1435 case WINED3DFMT_D32:
1436 if (32 == db) return TRUE;
1437 break;
1438 case WINED3DFMT_D15S1:
1439 if (15 == db) return TRUE;
1440 break;
1441 case WINED3DFMT_D24S8:
1442 if (24 == db && 8 == sb) return TRUE;
1443 break;
1444 case WINED3DFMT_D24FS8:
1445 if (24 == db && 8 == sb) return TRUE;
1446 break;
1447 case WINED3DFMT_D24X8:
1448 if (24 == db) return TRUE;
1449 break;
1450 case WINED3DFMT_D24X4S4:
1451 if (24 == db && 4 == sb) return TRUE;
1452 break;
1453 case WINED3DFMT_D32F_LOCKABLE:
1454 if (32 == db) return TRUE;
1455 break;
1456 default:
1457 break;
1459 return FALSE;
1460 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1461 switch (Format) {
1462 case WINED3DFMT_D16:
1463 case WINED3DFMT_D16_LOCKABLE:
1464 case WINED3DFMT_D32:
1465 case WINED3DFMT_D15S1:
1466 case WINED3DFMT_D24S8:
1467 case WINED3DFMT_D24FS8:
1468 case WINED3DFMT_D24X8:
1469 case WINED3DFMT_D24X4S4:
1470 case WINED3DFMT_D32F_LOCKABLE:
1471 return TRUE;
1472 default:
1473 break;
1475 return FALSE;
1476 #endif
1479 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1480 WINED3DFORMAT AdapterFormat,
1481 WINED3DFORMAT RenderTargetFormat,
1482 WINED3DFORMAT DepthStencilFormat) {
1483 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1484 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1485 GLXFBConfig* cfgs = NULL;
1486 int nCfgs = 0;
1487 int it;
1489 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1490 This, Adapter,
1491 DeviceType, debug_d3ddevicetype(DeviceType),
1492 AdapterFormat, debug_d3dformat(AdapterFormat),
1493 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1494 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1496 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1497 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1498 return WINED3DERR_INVALIDCALL;
1501 if(WineD3D_CreateFakeGLContext())
1502 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1504 if (cfgs) {
1505 for (it = 0; it < nCfgs; ++it) {
1506 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1507 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1508 hr = WINED3D_OK;
1509 break ;
1513 XFree(cfgs);
1514 if(hr != WINED3D_OK)
1515 ERR("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1516 } else {
1517 ERR_(d3d_caps)("returning WINED3D_OK even so CreateFakeGLContext or glXGetFBConfigs failed\n");
1518 hr = WINED3D_OK;
1521 WineD3D_ReleaseFakeGLContext();
1523 if (hr != WINED3D_OK)
1524 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1526 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1527 return hr;
1530 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1531 WINED3DFORMAT SurfaceFormat,
1532 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1534 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1535 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1536 This,
1537 Adapter,
1538 DeviceType, debug_d3ddevicetype(DeviceType),
1539 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1540 Windowed,
1541 MultiSampleType,
1542 pQualityLevels);
1544 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1545 return WINED3DERR_INVALIDCALL;
1548 if (pQualityLevels != NULL) {
1549 static int s_single_shot = 0;
1550 if (!s_single_shot) {
1551 FIXME("Quality levels unsupported at present\n");
1552 s_single_shot = 1;
1554 *pQualityLevels = 1; /* Guess at a value! */
1557 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1558 return WINED3DERR_NOTAVAILABLE;
1561 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1562 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1564 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1565 GLXFBConfig* cfgs = NULL;
1566 int nCfgs = 0;
1567 int it;
1568 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1570 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1571 This,
1572 Adapter,
1573 CheckType, debug_d3ddevicetype(CheckType),
1574 DisplayFormat, debug_d3dformat(DisplayFormat),
1575 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1576 Windowed);
1578 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1579 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1580 return WINED3DERR_INVALIDCALL;
1583 if (WineD3D_CreateFakeGLContext()) {
1584 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1585 for (it = 0; it < nCfgs; ++it) {
1586 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1587 hr = WINED3D_OK;
1588 TRACE_(d3d_caps)("OK\n");
1589 break ;
1592 if(cfgs) XFree(cfgs);
1593 if(hr != WINED3D_OK)
1594 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1595 WineD3D_ReleaseFakeGLContext();
1598 if(hr != WINED3D_OK)
1599 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1601 return hr;
1604 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1605 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1606 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1607 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1608 This,
1609 Adapter,
1610 DeviceType, debug_d3ddevicetype(DeviceType),
1611 AdapterFormat, debug_d3dformat(AdapterFormat),
1612 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1613 RType, debug_d3dresourcetype(RType),
1614 CheckFormat, debug_d3dformat(CheckFormat));
1616 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1617 return WINED3DERR_INVALIDCALL;
1620 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1621 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1622 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1623 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1624 TRACE_(d3d_caps)("[FAILED]\n");
1625 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1628 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1629 switch (CheckFormat) {
1630 case WINED3DFMT_D16_LOCKABLE:
1631 case WINED3DFMT_D32:
1632 case WINED3DFMT_D15S1:
1633 case WINED3DFMT_D24S8:
1634 case WINED3DFMT_D24X8:
1635 case WINED3DFMT_D24X4S4:
1636 case WINED3DFMT_D16:
1637 case WINED3DFMT_L16:
1638 case WINED3DFMT_D32F_LOCKABLE:
1639 case WINED3DFMT_D24FS8:
1640 TRACE_(d3d_caps)("[OK]\n");
1641 return WINED3D_OK;
1642 default:
1643 TRACE_(d3d_caps)("[FAILED]\n");
1644 return WINED3DERR_NOTAVAILABLE;
1646 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1647 switch (CheckFormat) {
1648 case WINED3DFMT_R8G8B8:
1649 case WINED3DFMT_A8R8G8B8:
1650 case WINED3DFMT_X8R8G8B8:
1651 case WINED3DFMT_R5G6B5:
1652 case WINED3DFMT_X1R5G5B5:
1653 case WINED3DFMT_A1R5G5B5:
1654 case WINED3DFMT_A4R4G4B4:
1655 case WINED3DFMT_R3G3B2:
1656 case WINED3DFMT_X4R4G4B4:
1657 case WINED3DFMT_A8B8G8R8:
1658 case WINED3DFMT_X8B8G8R8:
1659 case WINED3DFMT_P8:
1660 TRACE_(d3d_caps)("[OK]\n");
1661 return WINED3D_OK;
1662 default:
1663 TRACE_(d3d_caps)("[FAILED]\n");
1664 return WINED3DERR_NOTAVAILABLE;
1668 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1669 switch (CheckFormat) {
1670 case WINED3DFMT_DXT1:
1671 case WINED3DFMT_DXT2:
1672 case WINED3DFMT_DXT3:
1673 case WINED3DFMT_DXT4:
1674 case WINED3DFMT_DXT5:
1675 TRACE_(d3d_caps)("[OK]\n");
1676 return WINED3D_OK;
1677 default:
1678 break; /* Avoid compiler warnings */
1682 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1684 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1686 switch (CheckFormat) {
1687 case WINED3DFMT_R16F:
1688 case WINED3DFMT_A16B16G16R16F:
1689 if (!half_pixel_support) break;
1690 case WINED3DFMT_R32F:
1691 case WINED3DFMT_A32B32G32R32F:
1692 TRACE_(d3d_caps)("[OK]\n");
1693 return WINED3D_OK;
1694 default:
1695 break; /* Avoid compiler warnings */
1699 /* This format is nothing special and it is supported perfectly.
1700 * However, ati and nvidia driver on windows do not mark this format as
1701 * supported (tested with the dxCapsViewer) and pretending to
1702 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1703 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1704 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1706 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1707 TRACE_(d3d_caps)("[FAILED]\n");
1708 return WINED3DERR_NOTAVAILABLE;
1711 switch (CheckFormat) {
1713 /*****
1714 * supported: RGB(A) formats
1716 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1717 case WINED3DFMT_A8R8G8B8:
1718 case WINED3DFMT_X8R8G8B8:
1719 case WINED3DFMT_R5G6B5:
1720 case WINED3DFMT_X1R5G5B5:
1721 case WINED3DFMT_A1R5G5B5:
1722 case WINED3DFMT_A4R4G4B4:
1723 case WINED3DFMT_R3G3B2:
1724 case WINED3DFMT_A8:
1725 case WINED3DFMT_A8R3G3B2:
1726 case WINED3DFMT_X4R4G4B4:
1727 case WINED3DFMT_A8B8G8R8:
1728 case WINED3DFMT_X8B8G8R8:
1729 case WINED3DFMT_A2R10G10B10:
1730 case WINED3DFMT_A2B10G10R10:
1731 TRACE_(d3d_caps)("[OK]\n");
1732 return WINED3D_OK;
1734 /*****
1735 * supported: Palettized
1737 case WINED3DFMT_P8:
1738 TRACE_(d3d_caps)("[OK]\n");
1739 return WINED3D_OK;
1741 /*****
1742 * Supported: (Alpha)-Luminance
1744 case WINED3DFMT_L8:
1745 case WINED3DFMT_A8L8:
1746 case WINED3DFMT_A4L4:
1747 TRACE_(d3d_caps)("[OK]\n");
1748 return WINED3D_OK;
1750 /*****
1751 * Not supported for now: Bump mapping formats
1752 * Enable some because games often fail when they are not available
1753 * and are still playable even without bump mapping
1755 case WINED3DFMT_V8U8:
1756 case WINED3DFMT_V16U16:
1757 case WINED3DFMT_L6V5U5:
1758 case WINED3DFMT_X8L8V8U8:
1759 case WINED3DFMT_Q8W8V8U8:
1760 case WINED3DFMT_W11V11U10:
1761 case WINED3DFMT_A2W10V10U10:
1762 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1763 return WINED3D_OK;
1765 /*****
1766 * DXTN Formats: Handled above
1767 * WINED3DFMT_DXT1
1768 * WINED3DFMT_DXT2
1769 * WINED3DFMT_DXT3
1770 * WINED3DFMT_DXT4
1771 * WINED3DFMT_DXT5
1774 /*****
1775 * Odd formats - not supported
1777 case WINED3DFMT_VERTEXDATA:
1778 case WINED3DFMT_INDEX16:
1779 case WINED3DFMT_INDEX32:
1780 case WINED3DFMT_Q16W16V16U16:
1781 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1782 return WINED3DERR_NOTAVAILABLE;
1784 /*****
1785 * Float formats: Not supported right now
1787 case WINED3DFMT_G16R16F:
1788 case WINED3DFMT_G32R32F:
1789 case WINED3DFMT_CxV8U8:
1790 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1791 return WINED3DERR_NOTAVAILABLE;
1793 /* Not supported */
1794 case WINED3DFMT_G16R16:
1795 case WINED3DFMT_A16B16G16R16:
1796 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1797 return WINED3DERR_NOTAVAILABLE;
1799 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1800 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1801 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1802 * We can do instancing with all shader versions, but we need vertex shaders.
1804 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1805 * to enable instancing. WineD3D doesn't need that and just ignores it.
1807 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1809 case MAKEFOURCC('I','N','S','T'):
1810 TRACE("ATI Instancing check hack\n");
1811 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1812 TRACE_(d3d_caps)("[OK]\n");
1813 return WINED3D_OK;
1814 } else {
1815 TRACE_(d3d_caps)("[FAILED]\n");
1816 return WINED3DERR_NOTAVAILABLE;
1819 default:
1820 break;
1823 TRACE_(d3d_caps)("[FAILED]\n");
1824 return WINED3DERR_NOTAVAILABLE;
1827 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1828 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1829 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1831 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1832 This,
1833 Adapter,
1834 DeviceType, debug_d3ddevicetype(DeviceType),
1835 SourceFormat, debug_d3dformat(SourceFormat),
1836 TargetFormat, debug_d3dformat(TargetFormat));
1837 return WINED3D_OK;
1840 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1841 subset of a D3DCAPS9 structure. However, it has to come via a void *
1842 as the d3d8 interface cannot import the d3d9 header */
1843 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1845 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1846 int vs_selected_mode;
1847 int ps_selected_mode;
1849 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1851 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1852 return WINED3DERR_INVALIDCALL;
1855 /* FIXME: GL info should be per adapter */
1857 /* If we don't know the device settings, go query them now */
1858 if (!This->isGLInfoValid) {
1859 /* use the desktop window to fill gl caps */
1860 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1862 /* We are running off a real context, save the values */
1863 if (rc) This->isGLInfoValid = TRUE;
1865 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1867 /* This function should *not* be modifying GL caps
1868 * TODO: move the functionality where it belongs */
1869 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1871 /* ------------------------------------------------
1872 The following fields apply to both d3d8 and d3d9
1873 ------------------------------------------------ */
1874 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1875 *pCaps->AdapterOrdinal = Adapter;
1877 *pCaps->Caps = 0;
1878 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1879 WINED3DCAPS2_FULLSCREENGAMMA;
1880 *pCaps->Caps3 = 0;
1881 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1883 *pCaps->CursorCaps = 0;
1886 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1887 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1888 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1889 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1890 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1891 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1892 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1893 WINED3DDEVCAPS_PUREDEVICE |
1894 WINED3DDEVCAPS_HWRASTERIZATION |
1895 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1896 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1897 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1898 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1899 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1901 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1902 WINED3DPMISCCAPS_CULLCCW |
1903 WINED3DPMISCCAPS_CULLCW |
1904 WINED3DPMISCCAPS_COLORWRITEENABLE |
1905 WINED3DPMISCCAPS_CLIPTLVERTS |
1906 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1907 WINED3DPMISCCAPS_MASKZ |
1908 WINED3DPMISCCAPS_BLENDOP;
1909 /* TODO:
1910 WINED3DPMISCCAPS_NULLREFERENCE
1911 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1912 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1913 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1914 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1915 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1916 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1918 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1919 #if 0
1920 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1921 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1922 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1923 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1924 #endif
1926 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1927 WINED3DPRASTERCAPS_PAT |
1928 WINED3DPRASTERCAPS_WFOG |
1929 WINED3DPRASTERCAPS_ZFOG |
1930 WINED3DPRASTERCAPS_FOGVERTEX |
1931 WINED3DPRASTERCAPS_FOGTABLE |
1932 WINED3DPRASTERCAPS_FOGRANGE |
1933 WINED3DPRASTERCAPS_STIPPLE |
1934 WINED3DPRASTERCAPS_SUBPIXEL |
1935 WINED3DPRASTERCAPS_ZTEST |
1936 WINED3DPRASTERCAPS_SCISSORTEST |
1937 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1938 WINED3DPRASTERCAPS_DEPTHBIAS;
1940 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1941 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1942 WINED3DPRASTERCAPS_ZBIAS |
1943 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1945 /* FIXME Add:
1946 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1947 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1948 WINED3DPRASTERCAPS_ANTIALIASEDGES
1949 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1950 WINED3DPRASTERCAPS_WBUFFER */
1952 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1953 WINED3DPCMPCAPS_EQUAL |
1954 WINED3DPCMPCAPS_GREATER |
1955 WINED3DPCMPCAPS_GREATEREQUAL |
1956 WINED3DPCMPCAPS_LESS |
1957 WINED3DPCMPCAPS_LESSEQUAL |
1958 WINED3DPCMPCAPS_NEVER |
1959 WINED3DPCMPCAPS_NOTEQUAL;
1961 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1962 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1963 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1964 WINED3DPBLENDCAPS_DESTALPHA |
1965 WINED3DPBLENDCAPS_DESTCOLOR |
1966 WINED3DPBLENDCAPS_INVDESTALPHA |
1967 WINED3DPBLENDCAPS_INVDESTCOLOR |
1968 WINED3DPBLENDCAPS_INVSRCALPHA |
1969 WINED3DPBLENDCAPS_INVSRCCOLOR |
1970 WINED3DPBLENDCAPS_ONE |
1971 WINED3DPBLENDCAPS_SRCALPHA |
1972 WINED3DPBLENDCAPS_SRCALPHASAT |
1973 WINED3DPBLENDCAPS_SRCCOLOR |
1974 WINED3DPBLENDCAPS_ZERO;
1976 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1977 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1978 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1979 WINED3DPBLENDCAPS_DESTALPHA |
1980 WINED3DPBLENDCAPS_DESTCOLOR |
1981 WINED3DPBLENDCAPS_INVDESTALPHA |
1982 WINED3DPBLENDCAPS_INVDESTCOLOR |
1983 WINED3DPBLENDCAPS_INVSRCALPHA |
1984 WINED3DPBLENDCAPS_INVSRCCOLOR |
1985 WINED3DPBLENDCAPS_ONE |
1986 WINED3DPBLENDCAPS_SRCALPHA |
1987 WINED3DPBLENDCAPS_SRCALPHASAT |
1988 WINED3DPBLENDCAPS_SRCCOLOR |
1989 WINED3DPBLENDCAPS_ZERO;
1991 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1992 WINED3DPCMPCAPS_EQUAL |
1993 WINED3DPCMPCAPS_GREATER |
1994 WINED3DPCMPCAPS_GREATEREQUAL |
1995 WINED3DPCMPCAPS_LESS |
1996 WINED3DPCMPCAPS_LESSEQUAL |
1997 WINED3DPCMPCAPS_NEVER |
1998 WINED3DPCMPCAPS_NOTEQUAL;
2000 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2001 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2002 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2003 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2004 WINED3DPSHADECAPS_COLORFLATRGB |
2005 WINED3DPSHADECAPS_FOGFLAT |
2006 WINED3DPSHADECAPS_FOGGOURAUD |
2007 WINED3DPSHADECAPS_SPECULARFLATRGB;
2009 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2010 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2011 WINED3DPTEXTURECAPS_BORDER |
2012 WINED3DPTEXTURECAPS_MIPMAP |
2013 WINED3DPTEXTURECAPS_PROJECTED |
2014 WINED3DPTEXTURECAPS_PERSPECTIVE |
2015 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2017 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2018 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2019 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2020 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2023 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2024 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2025 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2026 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2030 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2031 WINED3DPTFILTERCAPS_MAGFPOINT |
2032 WINED3DPTFILTERCAPS_MINFLINEAR |
2033 WINED3DPTFILTERCAPS_MINFPOINT |
2034 WINED3DPTFILTERCAPS_MIPFLINEAR |
2035 WINED3DPTFILTERCAPS_MIPFPOINT |
2036 WINED3DPTFILTERCAPS_LINEAR |
2037 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2038 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2039 WINED3DPTFILTERCAPS_MIPLINEAR |
2040 WINED3DPTFILTERCAPS_MIPNEAREST |
2041 WINED3DPTFILTERCAPS_NEAREST;
2043 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2044 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2045 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2048 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2049 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2050 WINED3DPTFILTERCAPS_MAGFPOINT |
2051 WINED3DPTFILTERCAPS_MINFLINEAR |
2052 WINED3DPTFILTERCAPS_MINFPOINT |
2053 WINED3DPTFILTERCAPS_MIPFLINEAR |
2054 WINED3DPTFILTERCAPS_MIPFPOINT |
2055 WINED3DPTFILTERCAPS_LINEAR |
2056 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2057 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2058 WINED3DPTFILTERCAPS_MIPLINEAR |
2059 WINED3DPTFILTERCAPS_MIPNEAREST |
2060 WINED3DPTFILTERCAPS_NEAREST;
2062 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2063 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2064 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2066 } else
2067 *pCaps->CubeTextureFilterCaps = 0;
2069 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2070 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2071 WINED3DPTFILTERCAPS_MAGFPOINT |
2072 WINED3DPTFILTERCAPS_MINFLINEAR |
2073 WINED3DPTFILTERCAPS_MINFPOINT |
2074 WINED3DPTFILTERCAPS_MIPFLINEAR |
2075 WINED3DPTFILTERCAPS_MIPFPOINT |
2076 WINED3DPTFILTERCAPS_LINEAR |
2077 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2078 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2079 WINED3DPTFILTERCAPS_MIPLINEAR |
2080 WINED3DPTFILTERCAPS_MIPNEAREST |
2081 WINED3DPTFILTERCAPS_NEAREST;
2082 } else
2083 *pCaps->VolumeTextureFilterCaps = 0;
2085 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2086 WINED3DPTADDRESSCAPS_CLAMP |
2087 WINED3DPTADDRESSCAPS_WRAP;
2089 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2090 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2092 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2093 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2095 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2096 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2099 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2100 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2101 WINED3DPTADDRESSCAPS_CLAMP |
2102 WINED3DPTADDRESSCAPS_WRAP;
2103 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2104 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2106 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2107 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2109 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2110 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2112 } else
2113 *pCaps->VolumeTextureAddressCaps = 0;
2115 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2116 WINED3DLINECAPS_ZTEST;
2117 /* FIXME: Add
2118 WINED3DLINECAPS_BLEND
2119 WINED3DLINECAPS_ALPHACMP
2120 WINED3DLINECAPS_FOG */
2122 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2123 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2125 if(GL_SUPPORT(EXT_TEXTURE3D))
2126 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2127 else
2128 *pCaps->MaxVolumeExtent = 0;
2130 *pCaps->MaxTextureRepeat = 32768;
2131 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2132 *pCaps->MaxVertexW = 1.0;
2134 *pCaps->GuardBandLeft = 0;
2135 *pCaps->GuardBandTop = 0;
2136 *pCaps->GuardBandRight = 0;
2137 *pCaps->GuardBandBottom = 0;
2139 *pCaps->ExtentsAdjust = 0;
2141 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2142 WINED3DSTENCILCAPS_INCRSAT |
2143 WINED3DSTENCILCAPS_INVERT |
2144 WINED3DSTENCILCAPS_KEEP |
2145 WINED3DSTENCILCAPS_REPLACE |
2146 WINED3DSTENCILCAPS_ZERO;
2147 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2148 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2149 WINED3DSTENCILCAPS_INCR;
2151 if ( This->dxVersion > 8 &&
2152 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2153 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2154 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2157 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2159 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2160 WINED3DTEXOPCAPS_ADDSIGNED |
2161 WINED3DTEXOPCAPS_ADDSIGNED2X |
2162 WINED3DTEXOPCAPS_MODULATE |
2163 WINED3DTEXOPCAPS_MODULATE2X |
2164 WINED3DTEXOPCAPS_MODULATE4X |
2165 WINED3DTEXOPCAPS_SELECTARG1 |
2166 WINED3DTEXOPCAPS_SELECTARG2 |
2167 WINED3DTEXOPCAPS_DISABLE;
2169 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2170 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2171 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2172 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2173 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2174 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2175 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2176 WINED3DTEXOPCAPS_LERP |
2177 WINED3DTEXOPCAPS_SUBTRACT;
2179 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2180 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2181 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2182 WINED3DTEXOPCAPS_MULTIPLYADD |
2183 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2184 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2185 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2187 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2188 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2190 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2191 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2192 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2196 #if 0
2197 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2198 /* FIXME: Add
2199 WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2200 WINED3DTEXOPCAPS_PREMODULATE */
2201 #endif
2203 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2204 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2205 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2206 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2210 #if 0 /* TODO: Blends support in drawprim */
2211 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2212 #else
2213 *pCaps->MaxVertexBlendMatrices = 0;
2214 #endif
2215 *pCaps->MaxVertexBlendMatrixIndex = 1;
2217 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2218 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2221 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2222 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2223 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2224 WINED3DVTXPCAPS_LOCALVIEWER |
2225 WINED3DVTXPCAPS_VERTEXFOG |
2226 WINED3DVTXPCAPS_TEXGEN;
2227 /* FIXME: Add
2228 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2230 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2231 *pCaps->MaxVertexIndex = 0xFFFFF;
2232 *pCaps->MaxStreams = MAX_STREAMS;
2233 *pCaps->MaxStreamStride = 1024;
2235 if (vs_selected_mode == SHADER_GLSL) {
2236 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2237 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2238 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2239 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2240 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2241 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2242 else
2243 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2244 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2245 } else if (vs_selected_mode == SHADER_ARB) {
2246 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2247 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2248 } else if (vs_selected_mode == SHADER_SW) {
2249 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2250 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2251 } else {
2252 *pCaps->VertexShaderVersion = 0;
2253 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2256 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2258 if (ps_selected_mode == SHADER_GLSL) {
2259 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2260 in case of GeforceFX cards. */
2261 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2262 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2263 else
2264 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2265 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2266 *pCaps->PixelShader1xMaxValue = 1.0;
2267 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2268 } else if (ps_selected_mode == SHADER_ARB) {
2269 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2270 *pCaps->PixelShader1xMaxValue = 1.0;
2271 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2272 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2273 } else if (ps_selected_mode = SHADER_SW) {
2274 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2275 *pCaps->PixelShader1xMaxValue = 1.0;
2276 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2277 } else {
2278 *pCaps->PixelShaderVersion = 0;
2279 *pCaps->PixelShader1xMaxValue = 0.0;
2280 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2283 /* ------------------------------------------------
2284 The following fields apply to d3d9 only
2285 ------------------------------------------------ */
2286 if (This->dxVersion > 8) {
2287 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2288 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2289 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2290 *pCaps->MaxNpatchTessellationLevel = 0;
2291 *pCaps->MasterAdapterOrdinal = 0;
2292 *pCaps->AdapterOrdinalInGroup = 0;
2293 *pCaps->NumberOfAdaptersInGroup = 1;
2295 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2296 /* OpenGL supports all the formats below, perhaps not always
2297 * without conversion, but it supports them.
2298 * Further GLSL doesn't seem to have an official unsigned type so
2299 * don't advertise it yet as I'm not sure how we handle it.
2300 * We might need to add some clamping in the shader engine to
2301 * support it.
2302 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2303 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2304 WINED3DDTCAPS_UBYTE4N |
2305 WINED3DDTCAPS_SHORT2N |
2306 WINED3DDTCAPS_SHORT4N |
2307 WINED3DDTCAPS_FLOAT16_2 |
2308 WINED3DDTCAPS_FLOAT16_4;
2310 } else
2311 *pCaps->DeclTypes = 0;
2313 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2316 *pCaps->StretchRectFilterCaps = 0;
2317 *pCaps->VertexTextureFilterCaps = 0;
2319 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2320 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2321 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2322 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2323 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2324 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2325 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2327 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2328 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2329 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2330 *pCaps->VS20Caps.Caps = 0;
2331 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2332 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2333 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2335 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2336 *pCaps->MaxVertexShader30InstructionSlots = 0;
2337 } else { /* VS 1.x */
2338 *pCaps->VS20Caps.Caps = 0;
2339 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2340 *pCaps->VS20Caps.NumTemps = 0;
2341 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2343 *pCaps->MaxVShaderInstructionsExecuted = 0;
2344 *pCaps->MaxVertexShader30InstructionSlots = 0;
2347 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2348 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2349 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2351 /* Caps is more or less undocumented on MSDN but it appears to be used for PS20Caps based on results from R9600/FX5900/Geforce6800 cards from Windows */
2352 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2353 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2354 WINED3DPS20CAPS_PREDICATION |
2355 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2356 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2357 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2358 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2359 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2360 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2362 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2363 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2364 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2365 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2366 *pCaps->PS20Caps.Caps = 0;
2367 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2368 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2369 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2370 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2372 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2373 *pCaps->MaxPixelShader30InstructionSlots = 0;
2374 } else { /* PS 1.x */
2375 *pCaps->PS20Caps.Caps = 0;
2376 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2377 *pCaps->PS20Caps.NumTemps = 0;
2378 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2379 *pCaps->PS20Caps.NumInstructionSlots = 0;
2381 *pCaps->MaxPShaderInstructionsExecuted = 0;
2382 *pCaps->MaxPixelShader30InstructionSlots = 0;
2386 return WINED3D_OK;
2390 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2391 and fields being inserted in the middle, a new structure is used in place */
2392 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2393 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2394 IUnknown *parent) {
2396 IWineD3DDeviceImpl *object = NULL;
2397 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2398 HDC hDC;
2399 HRESULT temp_result;
2401 /* Validate the adapter number */
2402 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2403 return WINED3DERR_INVALIDCALL;
2406 /* Create a WineD3DDevice object */
2407 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2408 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2409 TRACE("Created WineD3DDevice object @ %p\n", object);
2410 if (NULL == object) {
2411 return WINED3DERR_OUTOFVIDEOMEMORY;
2414 /* Set up initial COM information */
2415 object->lpVtbl = &IWineD3DDevice_Vtbl;
2416 object->ref = 1;
2417 object->wineD3D = iface;
2418 IWineD3D_AddRef(object->wineD3D);
2419 object->parent = parent;
2421 /* Set the state up as invalid until the device is fully created */
2422 object->state = WINED3DERR_DRIVERINTERNALERROR;
2424 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2425 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2427 /* Save the creation parameters */
2428 object->createParms.AdapterOrdinal = Adapter;
2429 object->createParms.DeviceType = DeviceType;
2430 object->createParms.hFocusWindow = hFocusWindow;
2431 object->createParms.BehaviorFlags = BehaviourFlags;
2433 /* Initialize other useful values */
2434 object->adapterNo = Adapter;
2435 object->devType = DeviceType;
2437 TRACE("(%p) : Creating stateblock\n", This);
2438 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2439 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2440 WINED3DSBT_INIT,
2441 (IWineD3DStateBlock **)&object->stateBlock,
2442 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2443 WARN("Failed to create stateblock\n");
2444 goto create_device_error;
2446 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2447 object->updateStateBlock = object->stateBlock;
2448 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2449 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2451 /* Setup some defaults for creating the implicit swapchain */
2452 ENTER_GL();
2453 /* FIXME: GL info should be per adapter */
2454 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2455 LEAVE_GL();
2456 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2457 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2458 object->shader_backend = &glsl_shader_backend;
2459 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2460 object->shader_backend = &arb_program_shader_backend;
2461 } else {
2462 object->shader_backend = &none_shader_backend;
2465 /* This function should *not* be modifying GL caps
2466 * TODO: move the functionality where it belongs */
2467 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2469 temp_result = allocate_shader_constants(object->updateStateBlock);
2470 if (WINED3D_OK != temp_result)
2471 return temp_result;
2473 object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2475 object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
2477 /* set the state of the device to valid */
2478 object->state = WINED3D_OK;
2480 /* Get the initial screen setup for ddraw */
2481 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2482 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2483 hDC = GetDC(0);
2484 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2485 ReleaseDC(0, hDC);
2487 return WINED3D_OK;
2488 create_device_error:
2490 /* Set the device state to error */
2491 object->state = WINED3DERR_DRIVERINTERNALERROR;
2493 if (object->updateStateBlock != NULL) {
2494 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2495 object->updateStateBlock = NULL;
2497 if (object->stateBlock != NULL) {
2498 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2499 object->stateBlock = NULL;
2501 if (object->render_targets[0] != NULL) {
2502 IWineD3DSurface_Release(object->render_targets[0]);
2503 object->render_targets[0] = NULL;
2505 if (object->stencilBufferTarget != NULL) {
2506 IWineD3DSurface_Release(object->stencilBufferTarget);
2507 object->stencilBufferTarget = NULL;
2509 HeapFree(GetProcessHeap(), 0, object);
2510 *ppReturnedDeviceInterface = NULL;
2511 return WINED3DERR_INVALIDCALL;
2515 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2516 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2517 IUnknown_AddRef(This->parent);
2518 *pParent = This->parent;
2519 return WINED3D_OK;
2522 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2523 IUnknown* surfaceParent;
2524 TRACE("(%p) call back\n", pSurface);
2526 /* Now, release the parent, which will take care of cleaning up the surface for us */
2527 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2528 IUnknown_Release(surfaceParent);
2529 return IUnknown_Release(surfaceParent);
2532 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2533 IUnknown* volumeParent;
2534 TRACE("(%p) call back\n", pVolume);
2536 /* Now, release the parent, which will take care of cleaning up the volume for us */
2537 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2538 IUnknown_Release(volumeParent);
2539 return IUnknown_Release(volumeParent);
2542 /**********************************************************
2543 * IWineD3D VTbl follows
2544 **********************************************************/
2546 const IWineD3DVtbl IWineD3D_Vtbl =
2548 /* IUnknown */
2549 IWineD3DImpl_QueryInterface,
2550 IWineD3DImpl_AddRef,
2551 IWineD3DImpl_Release,
2552 /* IWineD3D */
2553 IWineD3DImpl_GetParent,
2554 IWineD3DImpl_GetAdapterCount,
2555 IWineD3DImpl_RegisterSoftwareDevice,
2556 IWineD3DImpl_GetAdapterMonitor,
2557 IWineD3DImpl_GetAdapterModeCount,
2558 IWineD3DImpl_EnumAdapterModes,
2559 IWineD3DImpl_GetAdapterDisplayMode,
2560 IWineD3DImpl_GetAdapterIdentifier,
2561 IWineD3DImpl_CheckDeviceMultiSampleType,
2562 IWineD3DImpl_CheckDepthStencilMatch,
2563 IWineD3DImpl_CheckDeviceType,
2564 IWineD3DImpl_CheckDeviceFormat,
2565 IWineD3DImpl_CheckDeviceFormatConversion,
2566 IWineD3DImpl_GetDeviceCaps,
2567 IWineD3DImpl_CreateDevice