Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / wined3d / directx.c
blobf4ebe53813725b8c363b40c5fb2da67e1bb2beef
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 static inline 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 if (wined3d_settings.vs_mode == VS_NONE) {
250 *vs_selected = SHADER_NONE;
251 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
252 *vs_selected = SHADER_GLSL;
253 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
254 *vs_selected = SHADER_ARB;
255 } else {
256 *vs_selected = SHADER_NONE;
259 if (wined3d_settings.ps_mode == PS_NONE) {
260 *ps_selected = SHADER_NONE;
261 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
262 *ps_selected = SHADER_GLSL;
263 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
264 *ps_selected = SHADER_ARB;
265 } else {
266 *ps_selected = SHADER_NONE;
270 /** Select the number of report maximum shader constants based on the selected shader modes */
271 static void select_shader_max_constants(
272 int ps_selected_mode,
273 int vs_selected_mode,
274 WineD3D_GL_Info *gl_info) {
276 switch (vs_selected_mode) {
277 case SHADER_GLSL:
278 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
279 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
280 break;
281 case SHADER_ARB:
282 /* We have to subtract any other PARAMs that we might use in our shader programs.
283 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
284 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
285 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
286 break;
287 default:
288 gl_info->max_vshader_constantsF = 0;
289 break;
292 switch (ps_selected_mode) {
293 case SHADER_GLSL:
294 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
295 * In theory the texbem instruction may need one more shader constant too. But lets assume
296 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
297 * and lets not take away a uniform needlessly from all other shaders.
299 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
300 break;
301 case SHADER_ARB:
302 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
303 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
305 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
306 break;
307 default:
308 gl_info->max_pshader_constantsF = 0;
309 break;
313 /**********************************************************
314 * IWineD3D parts follows
315 **********************************************************/
317 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
318 IWineD3DImpl *This = (IWineD3DImpl *)iface;
319 WineD3D_GL_Info *gl_info = &This->gl_info;
321 const char *GL_Extensions = NULL;
322 const char *GLX_Extensions = NULL;
323 const char *gl_string = NULL;
324 const char *gl_string_cursor = NULL;
325 GLint gl_max;
326 GLfloat gl_floatv[2];
327 Bool test = 0;
328 int major, minor;
329 BOOL return_value = TRUE;
330 int i;
332 /* Make sure that we've got a context */
333 /* TODO: CreateFakeGLContext should really take a display as a parameter */
334 /* Only save the values obtained when a display is provided */
335 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
336 return_value = FALSE;
338 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
340 gl_string = (const char *) glGetString(GL_RENDERER);
341 if (NULL == gl_string)
342 gl_string = "None";
343 strcpy(gl_info->gl_renderer, gl_string);
345 /* Fill in the GL info retrievable depending on the display */
346 if (NULL != display) {
347 test = glXQueryVersion(display, &major, &minor);
348 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
349 } else {
350 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
352 gl_string = (const char *) glGetString(GL_VENDOR);
354 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
355 if (gl_string != NULL) {
356 /* Fill in the GL vendor */
357 if (strstr(gl_string, "NVIDIA")) {
358 gl_info->gl_vendor = VENDOR_NVIDIA;
359 } else if (strstr(gl_string, "ATI")) {
360 gl_info->gl_vendor = VENDOR_ATI;
361 } else if (strstr(gl_string, "Intel(R)") ||
362 strstr(gl_info->gl_renderer, "Intel(R)")) {
363 gl_info->gl_vendor = VENDOR_INTEL;
364 } else if (strstr(gl_string, "Mesa")) {
365 gl_info->gl_vendor = VENDOR_MESA;
366 } else {
367 gl_info->gl_vendor = VENDOR_WINE;
369 } else {
370 gl_info->gl_vendor = VENDOR_WINE;
374 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
376 /* Parse the GL_VERSION field into major and minor information */
377 gl_string = (const char *) glGetString(GL_VERSION);
378 if (gl_string != NULL) {
380 switch (gl_info->gl_vendor) {
381 case VENDOR_NVIDIA:
382 gl_string_cursor = strstr(gl_string, "NVIDIA");
383 if (!gl_string_cursor) {
384 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
385 break;
388 gl_string_cursor = strstr(gl_string_cursor, " ");
389 if (!gl_string_cursor) {
390 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
391 break;
394 while (*gl_string_cursor == ' ') {
395 ++gl_string_cursor;
398 if (!*gl_string_cursor) {
399 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
400 break;
403 major = atoi(gl_string_cursor);
404 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
405 ++gl_string_cursor;
408 if (*gl_string_cursor++ != '.') {
409 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
410 break;
413 minor = atoi(gl_string_cursor);
414 minor = major*100+minor;
415 major = 10;
417 break;
419 case VENDOR_ATI:
420 major = minor = 0;
421 gl_string_cursor = strchr(gl_string, '-');
422 if (gl_string_cursor) {
423 int error = 0;
424 gl_string_cursor++;
426 /* Check if version number is of the form x.y.z */
427 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
428 error = 1;
429 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
430 error = 1;
431 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
432 error = 1;
433 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
434 error = 1;
436 /* Mark version number as malformed */
437 if (error)
438 gl_string_cursor = 0;
441 if (!gl_string_cursor)
442 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
443 else {
444 major = *gl_string_cursor - '0';
445 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
447 break;
449 case VENDOR_INTEL:
450 case VENDOR_MESA:
451 gl_string_cursor = strstr(gl_string, "Mesa");
452 gl_string_cursor = strstr(gl_string_cursor, " ");
453 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
454 if (*gl_string_cursor) {
455 char tmp[16];
456 int cursor = 0;
458 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
459 tmp[cursor++] = *gl_string_cursor;
460 ++gl_string_cursor;
462 tmp[cursor] = 0;
463 major = atoi(tmp);
465 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
466 ++gl_string_cursor;
468 cursor = 0;
469 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
470 tmp[cursor++] = *gl_string_cursor;
471 ++gl_string_cursor;
473 tmp[cursor] = 0;
474 minor = atoi(tmp);
476 break;
478 default:
479 major = 0;
480 minor = 9;
482 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
483 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
486 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
489 * Initialize openGL extension related variables
490 * with Default values
492 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
493 gl_info->max_buffers = 1;
494 gl_info->max_textures = 1;
495 gl_info->max_texture_stages = 1;
496 gl_info->max_samplers = 1;
497 gl_info->max_sampler_stages = 1;
498 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
499 gl_info->ps_arb_max_temps = 0;
500 gl_info->ps_arb_max_instructions = 0;
501 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
502 gl_info->vs_arb_max_temps = 0;
503 gl_info->vs_arb_max_instructions = 0;
504 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
505 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
506 gl_info->vs_glsl_constantsF = 0;
507 gl_info->ps_glsl_constantsF = 0;
508 gl_info->vs_arb_constantsF = 0;
509 gl_info->ps_arb_constantsF = 0;
511 /* Now work out what GL support this card really has */
512 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
513 GL_EXT_FUNCS_GEN;
514 GLX_EXT_FUNCS_GEN;
515 #undef USE_GL_FUNC
517 /* Retrieve opengl defaults */
518 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
519 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
520 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
522 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
523 gl_info->max_lights = gl_max;
524 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
526 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
527 gl_info->max_texture_size = gl_max;
528 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
530 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
531 gl_info->max_pointsize = gl_floatv[1];
532 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
534 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
535 gl_info->max_aux_buffers = gl_max;
536 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
538 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
539 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
540 TRACE_(d3d_caps)("GL_Extensions reported:\n");
542 if (NULL == GL_Extensions) {
543 ERR(" GL_Extensions returns NULL\n");
544 } else {
545 while (*GL_Extensions != 0x00) {
546 const char *Start = GL_Extensions;
547 char ThisExtn[256];
549 memset(ThisExtn, 0x00, sizeof(ThisExtn));
550 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
551 GL_Extensions++;
553 memcpy(ThisExtn, Start, (GL_Extensions - Start));
554 TRACE_(d3d_caps)("- %s\n", ThisExtn);
557 * ARB
559 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
560 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
561 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
562 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
563 gl_info->max_buffers = gl_max;
564 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
565 gl_info->ps_arb_version = PS_VERSION_11;
566 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
567 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
568 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
569 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
570 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
571 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
572 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
573 gl_info->ps_arb_constantsF = gl_max;
574 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
575 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
576 gl_info->ps_arb_max_temps = gl_max;
577 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
578 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
579 gl_info->ps_arb_max_instructions = gl_max;
580 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
581 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
582 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
583 gl_max /= 4;
584 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
585 gl_info->ps_glsl_constantsF = gl_max;
586 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
587 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
588 gl_info->supported[ARB_IMAGING] = TRUE;
589 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
590 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
591 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
592 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
593 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
594 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
595 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
596 gl_info->max_textures = min(MAX_TEXTURES, ffp_textures ? ffp_textures : gl_max);
597 gl_info->max_texture_stages = min(MAX_TEXTURES, ffp_textures ? ffp_textures : gl_max);
598 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
599 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
600 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
601 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
602 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
603 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
604 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
605 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
606 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
607 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
608 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
609 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
610 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
611 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
612 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
613 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
614 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
615 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
616 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
617 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
618 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
619 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
620 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
621 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
622 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
623 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
624 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
625 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
626 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
627 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
628 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
629 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
630 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
631 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
632 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
633 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
634 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
635 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
636 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
637 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
638 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
639 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
640 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
641 gl_info->vs_arb_version = VS_VERSION_11;
642 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
643 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
644 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
645 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
646 gl_info->vs_arb_constantsF = gl_max;
647 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
648 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
649 gl_info->vs_arb_max_temps = gl_max;
650 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
651 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
652 gl_info->vs_arb_max_instructions = gl_max;
653 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
654 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
655 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
656 gl_max /= 4;
657 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
658 gl_info->vs_glsl_constantsF = gl_max;
659 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
660 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
661 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
662 gl_info->max_blends = gl_max;
663 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
664 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
665 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
666 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
667 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
668 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
669 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
670 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
671 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
672 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
674 * EXT
676 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
677 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
678 gl_info->supported[EXT_FOG_COORD] = TRUE;
679 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
680 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
681 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
682 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
683 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
684 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
685 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
686 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
687 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
688 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
689 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
690 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
691 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
692 TRACE_(d3d_caps)(" FOUND: EXT Secondary color support\n");
693 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
694 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
695 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
696 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
697 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
698 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
699 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
700 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
701 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
702 gl_info->supported[EXT_TEXTURE3D] = TRUE;
703 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
704 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
705 gl_info->max_texture3d_size = gl_max;
706 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
707 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
708 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
709 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
710 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
711 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
712 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
713 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
714 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
715 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
716 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
717 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
718 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
719 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
720 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
721 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
722 gl_info->max_anisotropy = gl_max;
723 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
724 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
725 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
726 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
727 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
728 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
729 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
730 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
731 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
734 * NVIDIA
736 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
737 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
738 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
739 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
740 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
741 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
742 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
743 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
744 gl_info->max_texture_stages = min(MAX_TEXTURES, ffp_textures ? ffp_textures : gl_max);
745 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
746 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
747 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
748 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
749 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
750 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
751 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
752 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
753 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
754 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
755 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
756 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
757 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
758 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
759 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
760 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
761 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
762 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
763 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
764 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
765 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
766 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
767 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
768 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
769 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
770 gl_info->vs_nv_version = VS_VERSION_30;
771 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
772 gl_info->vs_nv_version = VS_VERSION_20;
773 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
774 gl_info->vs_nv_version = VS_VERSION_11;
775 else
776 gl_info->vs_nv_version = VS_VERSION_10;
777 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
778 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
779 } else if (strstr(ThisExtn, "GL_NV_fence")) {
780 if(!gl_info->supported[APPLE_FENCE]) {
781 gl_info->supported[NV_FENCE] = TRUE;
785 * ATI
787 /** TODO */
788 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
789 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
790 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
791 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
792 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
793 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
794 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
795 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
796 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
797 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
798 gl_info->vs_ati_version = VS_VERSION_11;
799 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
800 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
801 } else if (strcmp(ThisExtn, "GL_ATI_envmap_bumpmap") == 0) {
802 TRACE_(d3d_caps)(" FOUND: ATI Environment Bump Mapping support\n");
803 gl_info->supported[ATI_ENVMAP_BUMPMAP] = TRUE;
805 * Apple
807 } else if (strstr(ThisExtn, "GL_APPLE_fence")) {
808 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
809 * The apple extension interacts with some other apple exts. Disable the NV
810 * extension if the apple one is support to prevent confusion in other parts
811 * of the code
813 gl_info->supported[NV_FENCE] = FALSE;
814 gl_info->supported[APPLE_FENCE] = TRUE;
815 } else if (strstr(ThisExtn, "GL_APPLE_client_storage")) {
816 gl_info->supported[APPLE_CLIENT_STORAGE] = TRUE;
819 if (*GL_Extensions == ' ') GL_Extensions++;
822 checkGLcall("extension detection\n");
824 /* In some cases the number of texture stages can be larger than the number
825 * of samplers. The GF4 for example can use only 2 samplers (no fragment
826 * shaders), but 8 texture stages (register combiners). */
827 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
829 /* We can only use ORM_FBO when the hardware supports it. */
830 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
831 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
832 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
835 /* MRTs are currently only supported when FBOs are used. */
836 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
837 gl_info->max_buffers = 1;
840 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
841 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
842 * in case of the latest videocards in the number of pixel/vertex pipelines.
844 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
845 * rendering. Various games use this information to get a rough estimation of the features of the card
846 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
847 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
848 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
849 * not the PCI id.
851 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
852 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
853 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
854 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
855 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
856 * is used for rendering which is not always the case). This would work but it is not very portable. Second
857 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
858 * is limited.
860 * As said most games only use the PCI id to get an indication of the capabilities of the card.
861 * It doesn't really matter if the given id is the correct one if we return the id of a card with
862 * similar 3d features.
864 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
865 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
866 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
867 * won't pass we return a default card. This way is better than maintaining a full card database as even
868 * without a full database we can return a card with similar features. Second the size of the database
869 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
870 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
871 * to distinguishes between different models from that family.
873 switch (gl_info->gl_vendor) {
874 case VENDOR_NVIDIA:
875 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
876 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
878 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
879 if (strstr(gl_info->gl_renderer, "7800") ||
880 strstr(gl_info->gl_renderer, "7900") ||
881 strstr(gl_info->gl_renderer, "7950") ||
882 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
883 strstr(gl_info->gl_renderer, "Quadro FX 5"))
884 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
885 else if(strstr(gl_info->gl_renderer, "6800") ||
886 strstr(gl_info->gl_renderer, "7600"))
887 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
888 else if(strstr(gl_info->gl_renderer, "6600") ||
889 strstr(gl_info->gl_renderer, "6610") ||
890 strstr(gl_info->gl_renderer, "6700"))
891 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
892 else
893 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
894 } else if(WINE_D3D9_CAPABLE(gl_info)) {
895 if (strstr(gl_info->gl_renderer, "5800") ||
896 strstr(gl_info->gl_renderer, "5900") ||
897 strstr(gl_info->gl_renderer, "5950") ||
898 strstr(gl_info->gl_renderer, "Quadro FX"))
899 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
900 else if(strstr(gl_info->gl_renderer, "5600") ||
901 strstr(gl_info->gl_renderer, "5650") ||
902 strstr(gl_info->gl_renderer, "5700") ||
903 strstr(gl_info->gl_renderer, "5750"))
904 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
905 else
906 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
907 } else if(WINE_D3D8_CAPABLE(gl_info)) {
908 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
909 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
910 else
911 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
912 } else if(WINE_D3D7_CAPABLE(gl_info)) {
913 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
914 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
915 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
916 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
917 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
918 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
919 else
920 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
921 } else {
922 if (strstr(gl_info->gl_renderer, "TNT2"))
923 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
924 else
925 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
927 break;
928 case VENDOR_ATI:
929 if(WINE_D3D9_CAPABLE(gl_info)) {
930 /* Radeon R5xx */
931 if (strstr(gl_info->gl_renderer, "X1600") ||
932 strstr(gl_info->gl_renderer, "X1800") ||
933 strstr(gl_info->gl_renderer, "X1900") ||
934 strstr(gl_info->gl_renderer, "X1950"))
935 gl_info->gl_card = CARD_ATI_RADEON_X1600;
936 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
937 else if(strstr(gl_info->gl_renderer, "X700") ||
938 strstr(gl_info->gl_renderer, "X800") ||
939 strstr(gl_info->gl_renderer, "X850") ||
940 strstr(gl_info->gl_renderer, "X1300") ||
941 strstr(gl_info->gl_renderer, "X1400"))
942 gl_info->gl_card = CARD_ATI_RADEON_X700;
943 /* Radeon R3xx */
944 else
945 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
946 } else if(WINE_D3D8_CAPABLE(gl_info)) {
947 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
948 } else if(WINE_D3D7_CAPABLE(gl_info)) {
949 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
950 } else
951 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
952 break;
953 case VENDOR_INTEL:
954 if (strstr(gl_info->gl_renderer, "915GM")) {
955 gl_info->gl_card = CARD_INTEL_I915GM;
956 } else if (strstr(gl_info->gl_renderer, "915G")) {
957 gl_info->gl_card = CARD_INTEL_I915G;
958 } else if (strstr(gl_info->gl_renderer, "865G")) {
959 gl_info->gl_card = CARD_INTEL_I865G;
960 } else if (strstr(gl_info->gl_renderer, "855G")) {
961 gl_info->gl_card = CARD_INTEL_I855G;
962 } else if (strstr(gl_info->gl_renderer, "830G")) {
963 gl_info->gl_card = CARD_INTEL_I830G;
964 } else {
965 gl_info->gl_card = CARD_INTEL_I915G;
967 break;
968 case VENDOR_MESA:
969 case VENDOR_WINE:
970 default:
971 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
972 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
973 * them a good generic choice.
975 gl_info->gl_vendor = VENDOR_NVIDIA;
976 if(WINE_D3D9_CAPABLE(gl_info))
977 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
978 else if(WINE_D3D8_CAPABLE(gl_info))
979 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
980 else if(WINE_D3D7_CAPABLE(gl_info))
981 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
982 else if(WINE_D3D6_CAPABLE(gl_info))
983 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
984 else
985 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
987 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
989 /* Load all the lookup tables
990 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
991 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
992 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
994 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
995 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
998 for (i = 0; i < MAX_LOOKUPS; i++) {
999 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1002 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1003 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1004 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1005 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1006 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1007 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1008 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1009 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1010 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1011 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1013 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1014 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1015 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1016 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1017 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1020 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1021 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1022 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1023 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1024 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1025 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1026 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1027 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1028 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1029 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1030 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1031 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1032 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1034 /* TODO: config lookups */
1036 if (display != NULL) {
1037 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1038 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1040 if (NULL == GLX_Extensions) {
1041 ERR(" GLX_Extensions returns NULL\n");
1042 } else {
1043 while (*GLX_Extensions != 0x00) {
1044 const char *Start = GLX_Extensions;
1045 char ThisExtn[256];
1047 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1048 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1049 GLX_Extensions++;
1051 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1052 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1053 if (*GLX_Extensions == ' ') GLX_Extensions++;
1059 WineD3D_ReleaseFakeGLContext();
1060 return return_value;
1063 /**********************************************************
1064 * IWineD3D implementation follows
1065 **********************************************************/
1067 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1068 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1070 /* FIXME: Set to one for now to imply the display */
1071 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1072 return 1;
1075 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1076 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1077 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1078 return WINED3D_OK;
1081 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1082 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1083 POINT pt = { -1, -1 };
1085 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1086 return NULL;
1089 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1090 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1093 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1094 of the same bpp but different resolutions */
1096 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1097 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1098 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1099 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1101 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1102 return 0;
1105 if (Adapter == 0) { /* Display */
1106 int i = 0;
1107 int j = 0;
1109 if (!DEBUG_SINGLE_MODE) {
1110 DEVMODEW DevModeW;
1112 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1113 j++;
1114 switch (Format)
1116 case WINED3DFMT_UNKNOWN:
1117 /* This is for D3D8, do not enumerate P8 here */
1118 if (DevModeW.dmBitsPerPel == 32 ||
1119 DevModeW.dmBitsPerPel == 16) i++;
1120 break;
1121 case WINED3DFMT_X8R8G8B8:
1122 if (DevModeW.dmBitsPerPel == 32) i++;
1123 break;
1124 case WINED3DFMT_R5G6B5:
1125 if (DevModeW.dmBitsPerPel == 16) i++;
1126 break;
1127 case WINED3DFMT_P8:
1128 if (DevModeW.dmBitsPerPel == 8) i++;
1129 break;
1130 default:
1131 /* Skip other modes as they do not match the requested format */
1132 break;
1135 } else {
1136 i = 1;
1137 j = 1;
1140 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1141 return i;
1142 } else {
1143 FIXME_(d3d_caps)("Adapter not primary display\n");
1145 return 0;
1148 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1149 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1150 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1151 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1153 /* Validate the parameters as much as possible */
1154 if (NULL == pMode ||
1155 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1156 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1157 return WINED3DERR_INVALIDCALL;
1160 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1161 DEVMODEW DevModeW;
1162 int ModeIdx = 0;
1163 int i = 0;
1164 int j = 0;
1166 /* If we are filtering to a specific format (D3D9), then need to skip
1167 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1168 just count through the ones with valid bit depths */
1169 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1170 switch (Format)
1172 case WINED3DFMT_UNKNOWN:
1173 /* This is D3D8. Do not enumerate P8 here */
1174 if (DevModeW.dmBitsPerPel == 32 ||
1175 DevModeW.dmBitsPerPel == 16) i++;
1176 break;
1177 case WINED3DFMT_X8R8G8B8:
1178 if (DevModeW.dmBitsPerPel == 32) i++;
1179 break;
1180 case WINED3DFMT_R5G6B5:
1181 if (DevModeW.dmBitsPerPel == 16) i++;
1182 break;
1183 case WINED3DFMT_P8:
1184 if (DevModeW.dmBitsPerPel == 8) i++;
1185 break;
1186 default:
1187 /* Modes that don't match what we support can get an early-out */
1188 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1189 return WINED3DERR_INVALIDCALL;
1193 if (i == 0) {
1194 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1195 return WINED3DERR_INVALIDCALL;
1197 ModeIdx = j - 1;
1199 /* Now get the display mode via the calculated index */
1200 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1201 pMode->Width = DevModeW.dmPelsWidth;
1202 pMode->Height = DevModeW.dmPelsHeight;
1203 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1204 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1205 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1207 if (Format == WINED3DFMT_UNKNOWN)
1209 switch (DevModeW.dmBitsPerPel)
1211 case 8:
1212 pMode->Format = WINED3DFMT_P8;
1213 break;
1214 case 16:
1215 pMode->Format = WINED3DFMT_R5G6B5;
1216 break;
1217 case 32:
1218 pMode->Format = WINED3DFMT_X8R8G8B8;
1219 break;
1220 default:
1221 pMode->Format = WINED3DFMT_UNKNOWN;
1222 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1224 } else {
1225 pMode->Format = Format;
1227 } else {
1228 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1229 return WINED3DERR_INVALIDCALL;
1232 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1233 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1234 DevModeW.dmBitsPerPel);
1236 } else if (DEBUG_SINGLE_MODE) {
1237 /* Return one setting of the format requested */
1238 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1239 pMode->Width = 800;
1240 pMode->Height = 600;
1241 pMode->RefreshRate = 60;
1242 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1243 } else {
1244 FIXME_(d3d_caps)("Adapter not primary display\n");
1247 return WINED3D_OK;
1250 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1251 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1252 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1254 if (NULL == pMode ||
1255 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1256 return WINED3DERR_INVALIDCALL;
1259 if (Adapter == 0) { /* Display */
1260 int bpp = 0;
1261 DEVMODEW DevModeW;
1263 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1264 pMode->Width = DevModeW.dmPelsWidth;
1265 pMode->Height = DevModeW.dmPelsHeight;
1266 bpp = DevModeW.dmBitsPerPel;
1267 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1268 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1270 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1273 switch (bpp) {
1274 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1275 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1276 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1277 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1278 default: pMode->Format = WINED3DFMT_UNKNOWN;
1281 } else {
1282 FIXME_(d3d_caps)("Adapter not primary display\n");
1285 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1286 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1287 return WINED3D_OK;
1290 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1291 Display *display;
1292 HDC device_context;
1293 /* only works with one adapter at the moment... */
1295 /* Get the display */
1296 device_context = GetDC(0);
1297 display = get_display(device_context);
1298 ReleaseDC(0, device_context);
1299 return display;
1302 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1303 and fields being inserted in the middle, a new structure is used in place */
1304 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1305 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1306 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1308 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1310 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1311 return WINED3DERR_INVALIDCALL;
1314 if (Adapter == 0) { /* Display - only device supported for now */
1316 BOOL isGLInfoValid = This->isGLInfoValid;
1318 /* FillGLCaps updates gl_info, but we only want to store and
1319 reuse the values once we have a context which is valid. Values from
1320 a temporary context may differ from the final ones */
1321 if (!isGLInfoValid) {
1322 /* If we don't know the device settings, go query them now */
1323 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1326 /* If it worked, return the information requested */
1327 if (isGLInfoValid) {
1328 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1329 strcpy(pIdentifier->Driver, "Display");
1330 strcpy(pIdentifier->Description, "Direct3D HAL");
1332 /* Note dx8 doesn't supply a DeviceName */
1333 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1334 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1335 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1336 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1337 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1338 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1339 *(pIdentifier->SubSysId) = 0;
1340 *(pIdentifier->Revision) = 0;
1342 } else {
1344 /* If it failed, return dummy values from an NVidia driver */
1345 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1346 strcpy(pIdentifier->Driver, "Display");
1347 strcpy(pIdentifier->Description, "Direct3D HAL");
1348 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1349 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1350 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1351 /* 71.74 is a current Linux Nvidia driver version */
1352 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1353 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1354 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1355 *(pIdentifier->SubSysId) = 0;
1356 *(pIdentifier->Revision) = 0;
1359 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1360 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1361 *(pIdentifier->WHQLLevel) = 0;
1362 } else {
1363 *(pIdentifier->WHQLLevel) = 1;
1366 } else {
1367 FIXME_(d3d_caps)("Adapter not primary display\n");
1370 return WINED3D_OK;
1373 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1374 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1375 int gl_test;
1376 int rb, gb, bb, ab, type, buf_sz;
1378 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1379 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1380 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1381 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1382 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1383 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1385 switch (Format) {
1386 case WINED3DFMT_X8R8G8B8:
1387 case WINED3DFMT_R8G8B8:
1388 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1389 break;
1390 case WINED3DFMT_A8R8G8B8:
1391 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1392 break;
1393 case WINED3DFMT_A2R10G10B10:
1394 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1395 break;
1396 case WINED3DFMT_X1R5G5B5:
1397 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1398 break;
1399 case WINED3DFMT_A1R5G5B5:
1400 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1401 break;
1402 case WINED3DFMT_X4R4G4B4:
1403 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1404 break;
1405 case WINED3DFMT_R5G6B5:
1406 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1407 break;
1408 case WINED3DFMT_R3G3B2:
1409 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1410 break;
1411 case WINED3DFMT_A8P8:
1412 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1413 break;
1414 case WINED3DFMT_P8:
1415 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1416 break;
1417 default:
1418 break;
1420 return FALSE;
1421 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1422 switch (Format) {
1423 case WINED3DFMT_X8R8G8B8:
1424 case WINED3DFMT_R8G8B8:
1425 case WINED3DFMT_A8R8G8B8:
1426 case WINED3DFMT_A2R10G10B10:
1427 case WINED3DFMT_X1R5G5B5:
1428 case WINED3DFMT_A1R5G5B5:
1429 case WINED3DFMT_R5G6B5:
1430 case WINED3DFMT_R3G3B2:
1431 case WINED3DFMT_A8P8:
1432 case WINED3DFMT_P8:
1433 return TRUE;
1434 default:
1435 break;
1437 return FALSE;
1438 #endif
1441 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1442 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1443 int gl_test;
1444 int db, sb;
1446 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1447 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1449 switch (Format) {
1450 case WINED3DFMT_D16:
1451 case WINED3DFMT_D16_LOCKABLE:
1452 if (16 == db) return TRUE;
1453 break;
1454 case WINED3DFMT_D32:
1455 if (32 == db) return TRUE;
1456 break;
1457 case WINED3DFMT_D15S1:
1458 if (15 == db) return TRUE;
1459 break;
1460 case WINED3DFMT_D24S8:
1461 if (24 == db && 8 == sb) return TRUE;
1462 break;
1463 case WINED3DFMT_D24FS8:
1464 if (24 == db && 8 == sb) return TRUE;
1465 break;
1466 case WINED3DFMT_D24X8:
1467 if (24 == db) return TRUE;
1468 break;
1469 case WINED3DFMT_D24X4S4:
1470 if (24 == db && 4 == sb) return TRUE;
1471 break;
1472 case WINED3DFMT_D32F_LOCKABLE:
1473 if (32 == db) return TRUE;
1474 break;
1475 default:
1476 break;
1478 return FALSE;
1479 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1480 switch (Format) {
1481 case WINED3DFMT_D16:
1482 case WINED3DFMT_D16_LOCKABLE:
1483 case WINED3DFMT_D32:
1484 case WINED3DFMT_D15S1:
1485 case WINED3DFMT_D24S8:
1486 case WINED3DFMT_D24FS8:
1487 case WINED3DFMT_D24X8:
1488 case WINED3DFMT_D24X4S4:
1489 case WINED3DFMT_D32F_LOCKABLE:
1490 return TRUE;
1491 default:
1492 break;
1494 return FALSE;
1495 #endif
1498 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1499 WINED3DFORMAT AdapterFormat,
1500 WINED3DFORMAT RenderTargetFormat,
1501 WINED3DFORMAT DepthStencilFormat) {
1502 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1503 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1504 GLXFBConfig* cfgs = NULL;
1505 int nCfgs = 0;
1506 int it;
1508 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1509 This, Adapter,
1510 DeviceType, debug_d3ddevicetype(DeviceType),
1511 AdapterFormat, debug_d3dformat(AdapterFormat),
1512 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1513 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1515 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1516 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1517 return WINED3DERR_INVALIDCALL;
1520 if(WineD3D_CreateFakeGLContext())
1521 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1523 if (cfgs) {
1524 for (it = 0; it < nCfgs; ++it) {
1525 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1526 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1527 hr = WINED3D_OK;
1528 break ;
1532 XFree(cfgs);
1533 if(hr != WINED3D_OK)
1534 ERR("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1535 } else {
1536 ERR_(d3d_caps)("returning WINED3D_OK even so CreateFakeGLContext or glXGetFBConfigs failed\n");
1537 hr = WINED3D_OK;
1540 WineD3D_ReleaseFakeGLContext();
1542 if (hr != WINED3D_OK)
1543 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1545 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1546 return hr;
1549 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1550 WINED3DFORMAT SurfaceFormat,
1551 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1553 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1554 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1555 This,
1556 Adapter,
1557 DeviceType, debug_d3ddevicetype(DeviceType),
1558 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1559 Windowed,
1560 MultiSampleType,
1561 pQualityLevels);
1563 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1564 return WINED3DERR_INVALIDCALL;
1567 if (pQualityLevels != NULL) {
1568 static int s_single_shot = 0;
1569 if (!s_single_shot) {
1570 FIXME("Quality levels unsupported at present\n");
1571 s_single_shot = 1;
1573 *pQualityLevels = 1; /* Guess at a value! */
1576 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1577 return WINED3DERR_NOTAVAILABLE;
1580 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1581 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1583 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1584 GLXFBConfig* cfgs = NULL;
1585 int nCfgs = 0;
1586 int it;
1587 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1589 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1590 This,
1591 Adapter,
1592 CheckType, debug_d3ddevicetype(CheckType),
1593 DisplayFormat, debug_d3dformat(DisplayFormat),
1594 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1595 Windowed);
1597 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1598 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1599 return WINED3DERR_INVALIDCALL;
1602 if (WineD3D_CreateFakeGLContext()) {
1603 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1604 for (it = 0; it < nCfgs; ++it) {
1605 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1606 hr = WINED3D_OK;
1607 TRACE_(d3d_caps)("OK\n");
1608 break ;
1611 if(cfgs) XFree(cfgs);
1612 if(hr != WINED3D_OK)
1613 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1614 WineD3D_ReleaseFakeGLContext();
1617 if(hr != WINED3D_OK)
1618 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1620 return hr;
1623 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1624 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1625 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1626 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1627 This,
1628 Adapter,
1629 DeviceType, debug_d3ddevicetype(DeviceType),
1630 AdapterFormat, debug_d3dformat(AdapterFormat),
1631 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1632 RType, debug_d3dresourcetype(RType),
1633 CheckFormat, debug_d3dformat(CheckFormat));
1635 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1636 return WINED3DERR_INVALIDCALL;
1639 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1640 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1641 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1642 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1643 TRACE_(d3d_caps)("[FAILED]\n");
1644 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1647 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1648 switch (CheckFormat) {
1649 case WINED3DFMT_D16_LOCKABLE:
1650 case WINED3DFMT_D32:
1651 case WINED3DFMT_D15S1:
1652 case WINED3DFMT_D24S8:
1653 case WINED3DFMT_D24X8:
1654 case WINED3DFMT_D24X4S4:
1655 case WINED3DFMT_D16:
1656 case WINED3DFMT_L16:
1657 case WINED3DFMT_D32F_LOCKABLE:
1658 case WINED3DFMT_D24FS8:
1659 TRACE_(d3d_caps)("[OK]\n");
1660 return WINED3D_OK;
1661 default:
1662 TRACE_(d3d_caps)("[FAILED]\n");
1663 return WINED3DERR_NOTAVAILABLE;
1665 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1666 switch (CheckFormat) {
1667 case WINED3DFMT_R8G8B8:
1668 case WINED3DFMT_A8R8G8B8:
1669 case WINED3DFMT_X8R8G8B8:
1670 case WINED3DFMT_R5G6B5:
1671 case WINED3DFMT_X1R5G5B5:
1672 case WINED3DFMT_A1R5G5B5:
1673 case WINED3DFMT_A4R4G4B4:
1674 case WINED3DFMT_R3G3B2:
1675 case WINED3DFMT_X4R4G4B4:
1676 case WINED3DFMT_A8B8G8R8:
1677 case WINED3DFMT_X8B8G8R8:
1678 case WINED3DFMT_P8:
1679 TRACE_(d3d_caps)("[OK]\n");
1680 return WINED3D_OK;
1681 default:
1682 TRACE_(d3d_caps)("[FAILED]\n");
1683 return WINED3DERR_NOTAVAILABLE;
1687 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1688 switch (CheckFormat) {
1689 case WINED3DFMT_DXT1:
1690 case WINED3DFMT_DXT2:
1691 case WINED3DFMT_DXT3:
1692 case WINED3DFMT_DXT4:
1693 case WINED3DFMT_DXT5:
1694 TRACE_(d3d_caps)("[OK]\n");
1695 return WINED3D_OK;
1696 default:
1697 break; /* Avoid compiler warnings */
1701 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1703 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1705 switch (CheckFormat) {
1706 case WINED3DFMT_R16F:
1707 case WINED3DFMT_A16B16G16R16F:
1708 if (!half_pixel_support) break;
1709 case WINED3DFMT_R32F:
1710 case WINED3DFMT_A32B32G32R32F:
1711 TRACE_(d3d_caps)("[OK]\n");
1712 return WINED3D_OK;
1713 default:
1714 break; /* Avoid compiler warnings */
1718 /* This format is nothing special and it is supported perfectly.
1719 * However, ati and nvidia driver on windows do not mark this format as
1720 * supported (tested with the dxCapsViewer) and pretending to
1721 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1722 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1723 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1725 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1726 TRACE_(d3d_caps)("[FAILED]\n");
1727 return WINED3DERR_NOTAVAILABLE;
1730 switch (CheckFormat) {
1732 /*****
1733 * supported: RGB(A) formats
1735 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1736 case WINED3DFMT_A8R8G8B8:
1737 case WINED3DFMT_X8R8G8B8:
1738 case WINED3DFMT_R5G6B5:
1739 case WINED3DFMT_X1R5G5B5:
1740 case WINED3DFMT_A1R5G5B5:
1741 case WINED3DFMT_A4R4G4B4:
1742 case WINED3DFMT_R3G3B2:
1743 case WINED3DFMT_A8:
1744 case WINED3DFMT_A8R3G3B2:
1745 case WINED3DFMT_X4R4G4B4:
1746 case WINED3DFMT_A8B8G8R8:
1747 case WINED3DFMT_X8B8G8R8:
1748 case WINED3DFMT_A2R10G10B10:
1749 case WINED3DFMT_A2B10G10R10:
1750 TRACE_(d3d_caps)("[OK]\n");
1751 return WINED3D_OK;
1753 /*****
1754 * supported: Palettized
1756 case WINED3DFMT_P8:
1757 TRACE_(d3d_caps)("[OK]\n");
1758 return WINED3D_OK;
1760 /*****
1761 * Supported: (Alpha)-Luminance
1763 case WINED3DFMT_L8:
1764 case WINED3DFMT_A8L8:
1765 case WINED3DFMT_A4L4:
1766 TRACE_(d3d_caps)("[OK]\n");
1767 return WINED3D_OK;
1769 /*****
1770 * Not supported for now: Bump mapping formats
1771 * Enable some because games often fail when they are not available
1772 * and are still playable even without bump mapping
1774 case WINED3DFMT_V8U8:
1775 case WINED3DFMT_V16U16:
1776 case WINED3DFMT_L6V5U5:
1777 case WINED3DFMT_X8L8V8U8:
1778 case WINED3DFMT_Q8W8V8U8:
1779 case WINED3DFMT_W11V11U10:
1780 case WINED3DFMT_A2W10V10U10:
1781 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1782 return WINED3D_OK;
1784 /*****
1785 * DXTN Formats: Handled above
1786 * WINED3DFMT_DXT1
1787 * WINED3DFMT_DXT2
1788 * WINED3DFMT_DXT3
1789 * WINED3DFMT_DXT4
1790 * WINED3DFMT_DXT5
1793 /*****
1794 * Odd formats - not supported
1796 case WINED3DFMT_VERTEXDATA:
1797 case WINED3DFMT_INDEX16:
1798 case WINED3DFMT_INDEX32:
1799 case WINED3DFMT_Q16W16V16U16:
1800 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1801 return WINED3DERR_NOTAVAILABLE;
1803 /*****
1804 * Float formats: Not supported right now
1806 case WINED3DFMT_G16R16F:
1807 case WINED3DFMT_G32R32F:
1808 case WINED3DFMT_CxV8U8:
1809 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1810 return WINED3DERR_NOTAVAILABLE;
1812 /* Not supported */
1813 case WINED3DFMT_G16R16:
1814 case WINED3DFMT_A16B16G16R16:
1815 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1816 return WINED3DERR_NOTAVAILABLE;
1818 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1819 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1820 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1821 * We can do instancing with all shader versions, but we need vertex shaders.
1823 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1824 * to enable instancing. WineD3D doesn't need that and just ignores it.
1826 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1828 case MAKEFOURCC('I','N','S','T'):
1829 TRACE("ATI Instancing check hack\n");
1830 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1831 TRACE_(d3d_caps)("[OK]\n");
1832 return WINED3D_OK;
1833 } else {
1834 TRACE_(d3d_caps)("[FAILED]\n");
1835 return WINED3DERR_NOTAVAILABLE;
1838 default:
1839 break;
1842 TRACE_(d3d_caps)("[FAILED]\n");
1843 return WINED3DERR_NOTAVAILABLE;
1846 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1847 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1848 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1850 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1851 This,
1852 Adapter,
1853 DeviceType, debug_d3ddevicetype(DeviceType),
1854 SourceFormat, debug_d3dformat(SourceFormat),
1855 TargetFormat, debug_d3dformat(TargetFormat));
1856 return WINED3D_OK;
1859 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1860 subset of a D3DCAPS9 structure. However, it has to come via a void *
1861 as the d3d8 interface cannot import the d3d9 header */
1862 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1864 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1865 int vs_selected_mode;
1866 int ps_selected_mode;
1868 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1870 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1871 return WINED3DERR_INVALIDCALL;
1874 /* FIXME: GL info should be per adapter */
1876 /* If we don't know the device settings, go query them now */
1877 if (!This->isGLInfoValid) {
1878 /* use the desktop window to fill gl caps */
1879 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1881 /* We are running off a real context, save the values */
1882 if (rc) This->isGLInfoValid = TRUE;
1884 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1886 /* This function should *not* be modifying GL caps
1887 * TODO: move the functionality where it belongs */
1888 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1890 /* ------------------------------------------------
1891 The following fields apply to both d3d8 and d3d9
1892 ------------------------------------------------ */
1893 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1894 *pCaps->AdapterOrdinal = Adapter;
1896 *pCaps->Caps = 0;
1897 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1898 WINED3DCAPS2_FULLSCREENGAMMA |
1899 WINED3DCAPS2_DYNAMICTEXTURES;
1900 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1901 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1903 *pCaps->CursorCaps = 0;
1906 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1907 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1908 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1909 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1910 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1911 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1912 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1913 WINED3DDEVCAPS_PUREDEVICE |
1914 WINED3DDEVCAPS_HWRASTERIZATION |
1915 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1916 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1917 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1918 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1919 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1921 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1922 WINED3DPMISCCAPS_CULLCCW |
1923 WINED3DPMISCCAPS_CULLCW |
1924 WINED3DPMISCCAPS_COLORWRITEENABLE |
1925 WINED3DPMISCCAPS_CLIPTLVERTS |
1926 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1927 WINED3DPMISCCAPS_MASKZ |
1928 WINED3DPMISCCAPS_BLENDOP;
1929 /* TODO:
1930 WINED3DPMISCCAPS_NULLREFERENCE
1931 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1932 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1933 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1934 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1935 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1936 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1938 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1939 #if 0
1940 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1941 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1942 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1943 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1944 #endif
1946 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1947 WINED3DPRASTERCAPS_PAT |
1948 WINED3DPRASTERCAPS_WFOG |
1949 WINED3DPRASTERCAPS_ZFOG |
1950 WINED3DPRASTERCAPS_FOGVERTEX |
1951 WINED3DPRASTERCAPS_FOGTABLE |
1952 WINED3DPRASTERCAPS_FOGRANGE |
1953 WINED3DPRASTERCAPS_STIPPLE |
1954 WINED3DPRASTERCAPS_SUBPIXEL |
1955 WINED3DPRASTERCAPS_ZTEST |
1956 WINED3DPRASTERCAPS_SCISSORTEST |
1957 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1958 WINED3DPRASTERCAPS_DEPTHBIAS;
1960 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1961 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1962 WINED3DPRASTERCAPS_ZBIAS |
1963 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1965 /* FIXME Add:
1966 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1967 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1968 WINED3DPRASTERCAPS_ANTIALIASEDGES
1969 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1970 WINED3DPRASTERCAPS_WBUFFER */
1972 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1973 WINED3DPCMPCAPS_EQUAL |
1974 WINED3DPCMPCAPS_GREATER |
1975 WINED3DPCMPCAPS_GREATEREQUAL |
1976 WINED3DPCMPCAPS_LESS |
1977 WINED3DPCMPCAPS_LESSEQUAL |
1978 WINED3DPCMPCAPS_NEVER |
1979 WINED3DPCMPCAPS_NOTEQUAL;
1981 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1982 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1983 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1984 WINED3DPBLENDCAPS_DESTALPHA |
1985 WINED3DPBLENDCAPS_DESTCOLOR |
1986 WINED3DPBLENDCAPS_INVDESTALPHA |
1987 WINED3DPBLENDCAPS_INVDESTCOLOR |
1988 WINED3DPBLENDCAPS_INVSRCALPHA |
1989 WINED3DPBLENDCAPS_INVSRCCOLOR |
1990 WINED3DPBLENDCAPS_ONE |
1991 WINED3DPBLENDCAPS_SRCALPHA |
1992 WINED3DPBLENDCAPS_SRCALPHASAT |
1993 WINED3DPBLENDCAPS_SRCCOLOR |
1994 WINED3DPBLENDCAPS_ZERO;
1996 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1997 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1998 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1999 WINED3DPBLENDCAPS_DESTALPHA |
2000 WINED3DPBLENDCAPS_DESTCOLOR |
2001 WINED3DPBLENDCAPS_INVDESTALPHA |
2002 WINED3DPBLENDCAPS_INVDESTCOLOR |
2003 WINED3DPBLENDCAPS_INVSRCALPHA |
2004 WINED3DPBLENDCAPS_INVSRCCOLOR |
2005 WINED3DPBLENDCAPS_ONE |
2006 WINED3DPBLENDCAPS_SRCALPHA |
2007 WINED3DPBLENDCAPS_SRCALPHASAT |
2008 WINED3DPBLENDCAPS_SRCCOLOR |
2009 WINED3DPBLENDCAPS_ZERO;
2011 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2012 WINED3DPCMPCAPS_EQUAL |
2013 WINED3DPCMPCAPS_GREATER |
2014 WINED3DPCMPCAPS_GREATEREQUAL |
2015 WINED3DPCMPCAPS_LESS |
2016 WINED3DPCMPCAPS_LESSEQUAL |
2017 WINED3DPCMPCAPS_NEVER |
2018 WINED3DPCMPCAPS_NOTEQUAL;
2020 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2021 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2022 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2023 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2024 WINED3DPSHADECAPS_COLORFLATRGB |
2025 WINED3DPSHADECAPS_FOGFLAT |
2026 WINED3DPSHADECAPS_FOGGOURAUD |
2027 WINED3DPSHADECAPS_SPECULARFLATRGB;
2029 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2030 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2031 WINED3DPTEXTURECAPS_BORDER |
2032 WINED3DPTEXTURECAPS_MIPMAP |
2033 WINED3DPTEXTURECAPS_PROJECTED |
2034 WINED3DPTEXTURECAPS_PERSPECTIVE |
2035 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2037 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2038 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2039 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2040 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2043 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2044 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2045 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2046 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2050 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2051 WINED3DPTFILTERCAPS_MAGFPOINT |
2052 WINED3DPTFILTERCAPS_MINFLINEAR |
2053 WINED3DPTFILTERCAPS_MINFPOINT |
2054 WINED3DPTFILTERCAPS_MIPFLINEAR |
2055 WINED3DPTFILTERCAPS_MIPFPOINT |
2056 WINED3DPTFILTERCAPS_LINEAR |
2057 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2058 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2059 WINED3DPTFILTERCAPS_MIPLINEAR |
2060 WINED3DPTFILTERCAPS_MIPNEAREST |
2061 WINED3DPTFILTERCAPS_NEAREST;
2063 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2064 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2065 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2068 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2069 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2070 WINED3DPTFILTERCAPS_MAGFPOINT |
2071 WINED3DPTFILTERCAPS_MINFLINEAR |
2072 WINED3DPTFILTERCAPS_MINFPOINT |
2073 WINED3DPTFILTERCAPS_MIPFLINEAR |
2074 WINED3DPTFILTERCAPS_MIPFPOINT |
2075 WINED3DPTFILTERCAPS_LINEAR |
2076 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2077 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2078 WINED3DPTFILTERCAPS_MIPLINEAR |
2079 WINED3DPTFILTERCAPS_MIPNEAREST |
2080 WINED3DPTFILTERCAPS_NEAREST;
2082 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2083 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2084 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2086 } else
2087 *pCaps->CubeTextureFilterCaps = 0;
2089 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2090 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2091 WINED3DPTFILTERCAPS_MAGFPOINT |
2092 WINED3DPTFILTERCAPS_MINFLINEAR |
2093 WINED3DPTFILTERCAPS_MINFPOINT |
2094 WINED3DPTFILTERCAPS_MIPFLINEAR |
2095 WINED3DPTFILTERCAPS_MIPFPOINT |
2096 WINED3DPTFILTERCAPS_LINEAR |
2097 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2098 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2099 WINED3DPTFILTERCAPS_MIPLINEAR |
2100 WINED3DPTFILTERCAPS_MIPNEAREST |
2101 WINED3DPTFILTERCAPS_NEAREST;
2102 } else
2103 *pCaps->VolumeTextureFilterCaps = 0;
2105 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2106 WINED3DPTADDRESSCAPS_CLAMP |
2107 WINED3DPTADDRESSCAPS_WRAP;
2109 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2110 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2112 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2113 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2115 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2116 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2119 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2120 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2121 WINED3DPTADDRESSCAPS_CLAMP |
2122 WINED3DPTADDRESSCAPS_WRAP;
2123 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2124 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2126 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2127 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2129 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2130 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2132 } else
2133 *pCaps->VolumeTextureAddressCaps = 0;
2135 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2136 WINED3DLINECAPS_ZTEST;
2137 /* FIXME: Add
2138 WINED3DLINECAPS_BLEND
2139 WINED3DLINECAPS_ALPHACMP
2140 WINED3DLINECAPS_FOG */
2142 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2143 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2145 if(GL_SUPPORT(EXT_TEXTURE3D))
2146 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2147 else
2148 *pCaps->MaxVolumeExtent = 0;
2150 *pCaps->MaxTextureRepeat = 32768;
2151 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2152 *pCaps->MaxVertexW = 1.0;
2154 *pCaps->GuardBandLeft = 0;
2155 *pCaps->GuardBandTop = 0;
2156 *pCaps->GuardBandRight = 0;
2157 *pCaps->GuardBandBottom = 0;
2159 *pCaps->ExtentsAdjust = 0;
2161 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2162 WINED3DSTENCILCAPS_INCRSAT |
2163 WINED3DSTENCILCAPS_INVERT |
2164 WINED3DSTENCILCAPS_KEEP |
2165 WINED3DSTENCILCAPS_REPLACE |
2166 WINED3DSTENCILCAPS_ZERO;
2167 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2168 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2169 WINED3DSTENCILCAPS_INCR;
2171 if ( This->dxVersion > 8 &&
2172 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2173 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2174 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2177 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2179 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2180 WINED3DTEXOPCAPS_ADDSIGNED |
2181 WINED3DTEXOPCAPS_ADDSIGNED2X |
2182 WINED3DTEXOPCAPS_MODULATE |
2183 WINED3DTEXOPCAPS_MODULATE2X |
2184 WINED3DTEXOPCAPS_MODULATE4X |
2185 WINED3DTEXOPCAPS_SELECTARG1 |
2186 WINED3DTEXOPCAPS_SELECTARG2 |
2187 WINED3DTEXOPCAPS_DISABLE;
2189 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2190 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2191 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2192 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2193 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2194 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2195 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2196 WINED3DTEXOPCAPS_LERP |
2197 WINED3DTEXOPCAPS_SUBTRACT;
2199 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2200 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2201 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2202 WINED3DTEXOPCAPS_MULTIPLYADD |
2203 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2204 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2205 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2207 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2208 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2210 if (GL_SUPPORT(NV_REGISTER_COMBINERS) || forceModulateInvAlphaAddColor) {
2211 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2212 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2216 #if 0
2217 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2218 /* FIXME: Add
2219 WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2220 WINED3DTEXOPCAPS_PREMODULATE */
2221 #endif
2223 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2224 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2225 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2226 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2230 #if 0 /* TODO: Blends support in drawprim */
2231 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2232 #else
2233 *pCaps->MaxVertexBlendMatrices = 0;
2234 #endif
2235 *pCaps->MaxVertexBlendMatrixIndex = 1;
2237 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2238 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2241 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2242 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2243 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2244 WINED3DVTXPCAPS_LOCALVIEWER |
2245 WINED3DVTXPCAPS_VERTEXFOG |
2246 WINED3DVTXPCAPS_TEXGEN;
2247 /* FIXME: Add
2248 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2250 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2251 *pCaps->MaxVertexIndex = 0xFFFFF;
2252 *pCaps->MaxStreams = MAX_STREAMS;
2253 *pCaps->MaxStreamStride = 1024;
2255 if (vs_selected_mode == SHADER_GLSL) {
2256 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2257 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2258 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2259 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2260 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2261 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2262 else
2263 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2264 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2265 } else if (vs_selected_mode == SHADER_ARB) {
2266 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2267 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2268 } else {
2269 *pCaps->VertexShaderVersion = 0;
2270 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2273 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2275 if (ps_selected_mode == SHADER_GLSL) {
2276 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2277 in case of GeforceFX cards. */
2278 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2279 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2280 else
2281 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2282 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2283 *pCaps->PixelShader1xMaxValue = 1.0;
2284 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2285 } else if (ps_selected_mode == SHADER_ARB) {
2286 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2287 *pCaps->PixelShader1xMaxValue = 1.0;
2288 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2289 } else {
2290 *pCaps->PixelShaderVersion = 0;
2291 *pCaps->PixelShader1xMaxValue = 0.0;
2292 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2295 /* ------------------------------------------------
2296 The following fields apply to d3d9 only
2297 ------------------------------------------------ */
2298 if (This->dxVersion > 8) {
2299 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2300 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2301 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2302 *pCaps->MaxNpatchTessellationLevel = 0;
2303 *pCaps->MasterAdapterOrdinal = 0;
2304 *pCaps->AdapterOrdinalInGroup = 0;
2305 *pCaps->NumberOfAdaptersInGroup = 1;
2307 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2308 /* OpenGL supports all the formats below, perhaps not always
2309 * without conversion, but it supports them.
2310 * Further GLSL doesn't seem to have an official unsigned type so
2311 * don't advertise it yet as I'm not sure how we handle it.
2312 * We might need to add some clamping in the shader engine to
2313 * support it.
2314 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2315 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2316 WINED3DDTCAPS_UBYTE4N |
2317 WINED3DDTCAPS_SHORT2N |
2318 WINED3DDTCAPS_SHORT4N |
2319 WINED3DDTCAPS_FLOAT16_2 |
2320 WINED3DDTCAPS_FLOAT16_4;
2322 } else
2323 *pCaps->DeclTypes = 0;
2325 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2328 *pCaps->StretchRectFilterCaps = 0;
2329 *pCaps->VertexTextureFilterCaps = 0;
2331 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2332 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2333 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2334 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2335 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2336 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2337 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2339 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2340 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2341 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2342 *pCaps->VS20Caps.Caps = 0;
2343 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2344 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2345 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2347 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2348 *pCaps->MaxVertexShader30InstructionSlots = 0;
2349 } else { /* VS 1.x */
2350 *pCaps->VS20Caps.Caps = 0;
2351 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2352 *pCaps->VS20Caps.NumTemps = 0;
2353 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2355 *pCaps->MaxVShaderInstructionsExecuted = 0;
2356 *pCaps->MaxVertexShader30InstructionSlots = 0;
2359 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2360 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2361 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2363 /* 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 */
2364 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2365 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2366 WINED3DPS20CAPS_PREDICATION |
2367 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2368 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2369 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2370 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2371 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2372 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2374 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2375 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2376 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2377 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2378 *pCaps->PS20Caps.Caps = 0;
2379 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2380 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2381 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2382 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2384 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2385 *pCaps->MaxPixelShader30InstructionSlots = 0;
2386 } else { /* PS 1.x */
2387 *pCaps->PS20Caps.Caps = 0;
2388 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2389 *pCaps->PS20Caps.NumTemps = 0;
2390 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2391 *pCaps->PS20Caps.NumInstructionSlots = 0;
2393 *pCaps->MaxPShaderInstructionsExecuted = 0;
2394 *pCaps->MaxPixelShader30InstructionSlots = 0;
2398 return WINED3D_OK;
2401 static unsigned int glsl_program_key_hash(void *key) {
2402 glsl_program_key_t *k = (glsl_program_key_t *)key;
2404 unsigned int hash = k->vshader | k->pshader << 16;
2405 hash += ~(hash << 15);
2406 hash ^= (hash >> 10);
2407 hash += (hash << 3);
2408 hash ^= (hash >> 6);
2409 hash += ~(hash << 11);
2410 hash ^= (hash >> 16);
2412 return hash;
2415 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2416 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2417 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2419 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2422 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2423 and fields being inserted in the middle, a new structure is used in place */
2424 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2425 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2426 IUnknown *parent) {
2428 IWineD3DDeviceImpl *object = NULL;
2429 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2430 HDC hDC;
2431 HRESULT temp_result;
2433 /* Validate the adapter number */
2434 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2435 return WINED3DERR_INVALIDCALL;
2438 /* Create a WineD3DDevice object */
2439 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2440 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2441 TRACE("Created WineD3DDevice object @ %p\n", object);
2442 if (NULL == object) {
2443 return WINED3DERR_OUTOFVIDEOMEMORY;
2446 /* Set up initial COM information */
2447 object->lpVtbl = &IWineD3DDevice_Vtbl;
2448 object->ref = 1;
2449 object->wineD3D = iface;
2450 IWineD3D_AddRef(object->wineD3D);
2451 object->parent = parent;
2453 /* Set the state up as invalid until the device is fully created */
2454 object->state = WINED3DERR_DRIVERINTERNALERROR;
2456 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2457 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2459 /* Save the creation parameters */
2460 object->createParms.AdapterOrdinal = Adapter;
2461 object->createParms.DeviceType = DeviceType;
2462 object->createParms.hFocusWindow = hFocusWindow;
2463 object->createParms.BehaviorFlags = BehaviourFlags;
2465 /* Initialize other useful values */
2466 object->adapterNo = Adapter;
2467 object->devType = DeviceType;
2469 TRACE("(%p) : Creating stateblock\n", This);
2470 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2471 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2472 WINED3DSBT_INIT,
2473 (IWineD3DStateBlock **)&object->stateBlock,
2474 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2475 WARN("Failed to create stateblock\n");
2476 goto create_device_error;
2478 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2479 object->updateStateBlock = object->stateBlock;
2480 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2481 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2483 /* Setup some defaults for creating the implicit swapchain */
2484 ENTER_GL();
2485 /* FIXME: GL info should be per adapter */
2486 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2487 LEAVE_GL();
2488 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2489 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2490 object->shader_backend = &glsl_shader_backend;
2491 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2492 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2493 object->shader_backend = &arb_program_shader_backend;
2494 } else {
2495 object->shader_backend = &none_shader_backend;
2498 /* This function should *not* be modifying GL caps
2499 * TODO: move the functionality where it belongs */
2500 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2502 temp_result = allocate_shader_constants(object->updateStateBlock);
2503 if (WINED3D_OK != temp_result)
2504 return temp_result;
2506 object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2508 object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
2510 /* set the state of the device to valid */
2511 object->state = WINED3D_OK;
2513 /* Get the initial screen setup for ddraw */
2514 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2515 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2516 hDC = GetDC(0);
2517 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2518 ReleaseDC(0, hDC);
2520 deviceCreated = TRUE;
2521 return WINED3D_OK;
2522 create_device_error:
2524 /* Set the device state to error */
2525 object->state = WINED3DERR_DRIVERINTERNALERROR;
2527 if (object->updateStateBlock != NULL) {
2528 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2529 object->updateStateBlock = NULL;
2531 if (object->stateBlock != NULL) {
2532 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2533 object->stateBlock = NULL;
2535 if (object->render_targets[0] != NULL) {
2536 IWineD3DSurface_Release(object->render_targets[0]);
2537 object->render_targets[0] = NULL;
2539 if (object->stencilBufferTarget != NULL) {
2540 IWineD3DSurface_Release(object->stencilBufferTarget);
2541 object->stencilBufferTarget = NULL;
2543 HeapFree(GetProcessHeap(), 0, object);
2544 *ppReturnedDeviceInterface = NULL;
2545 return WINED3DERR_INVALIDCALL;
2549 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2550 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2551 IUnknown_AddRef(This->parent);
2552 *pParent = This->parent;
2553 return WINED3D_OK;
2556 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2557 IUnknown* surfaceParent;
2558 TRACE("(%p) call back\n", pSurface);
2560 /* Now, release the parent, which will take care of cleaning up the surface for us */
2561 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2562 IUnknown_Release(surfaceParent);
2563 return IUnknown_Release(surfaceParent);
2566 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2567 IUnknown* volumeParent;
2568 TRACE("(%p) call back\n", pVolume);
2570 /* Now, release the parent, which will take care of cleaning up the volume for us */
2571 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2572 IUnknown_Release(volumeParent);
2573 return IUnknown_Release(volumeParent);
2576 /**********************************************************
2577 * IWineD3D VTbl follows
2578 **********************************************************/
2580 const IWineD3DVtbl IWineD3D_Vtbl =
2582 /* IUnknown */
2583 IWineD3DImpl_QueryInterface,
2584 IWineD3DImpl_AddRef,
2585 IWineD3DImpl_Release,
2586 /* IWineD3D */
2587 IWineD3DImpl_GetParent,
2588 IWineD3DImpl_GetAdapterCount,
2589 IWineD3DImpl_RegisterSoftwareDevice,
2590 IWineD3DImpl_GetAdapterMonitor,
2591 IWineD3DImpl_GetAdapterModeCount,
2592 IWineD3DImpl_EnumAdapterModes,
2593 IWineD3DImpl_GetAdapterDisplayMode,
2594 IWineD3DImpl_GetAdapterIdentifier,
2595 IWineD3DImpl_CheckDeviceMultiSampleType,
2596 IWineD3DImpl_CheckDepthStencilMatch,
2597 IWineD3DImpl_CheckDeviceType,
2598 IWineD3DImpl_CheckDeviceFormat,
2599 IWineD3DImpl_CheckDeviceFormatConversion,
2600 IWineD3DImpl_GetDeviceCaps,
2601 IWineD3DImpl_CreateDevice