wined3d: Support bump environment mapping using GL_NV_texture_shader.
[wine.git] / dlls / wined3d / directx.c
blob4f1caec9605a69e4069c2ce13420bc033cfe3f76
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, gl_max);
597 gl_info->max_texture_stages = min(MAX_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_framebuffer_blit") == 0) {
683 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Blit support\n");
684 gl_info->supported[EXT_FRAMEBUFFER_BLIT] = TRUE;
685 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
686 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
687 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
688 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
689 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
690 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
691 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
692 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
693 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
694 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
695 TRACE_(d3d_caps)(" FOUND: EXT Secondary color support\n");
696 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
697 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
698 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
699 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
700 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
701 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
702 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
703 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
704 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
705 gl_info->supported[EXT_TEXTURE3D] = TRUE;
706 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
707 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
708 gl_info->max_texture3d_size = gl_max;
709 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
710 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
711 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
712 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
713 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
714 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
715 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
716 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
717 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
718 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
719 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
720 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
721 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
722 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
723 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
724 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
725 gl_info->max_anisotropy = gl_max;
726 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
727 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
728 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
729 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
730 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
731 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
732 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
733 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
734 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
737 * NVIDIA
739 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
740 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
741 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
742 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
743 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
744 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
745 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
746 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
747 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
748 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
749 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
750 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
751 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
752 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
753 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
754 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
755 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
756 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
757 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
758 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
759 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
760 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
761 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
762 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
763 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
764 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
765 /* Prevent both extensions to be used at the same time. I don't expect them to play nice together */
766 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
767 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
768 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
769 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
770 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
771 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
772 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
773 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
774 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
775 gl_info->vs_nv_version = VS_VERSION_30;
776 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
777 gl_info->vs_nv_version = VS_VERSION_20;
778 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
779 gl_info->vs_nv_version = VS_VERSION_11;
780 else
781 gl_info->vs_nv_version = VS_VERSION_10;
782 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
783 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
784 } else if (strstr(ThisExtn, "GL_NV_fence")) {
785 if(!gl_info->supported[APPLE_FENCE]) {
786 gl_info->supported[NV_FENCE] = TRUE;
790 * ATI
792 /** TODO */
793 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
794 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
795 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
796 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
797 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
798 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
799 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
800 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
801 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
802 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
803 gl_info->vs_ati_version = VS_VERSION_11;
804 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
805 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
806 } else if (strcmp(ThisExtn, "GL_ATI_envmap_bumpmap") == 0) {
807 TRACE_(d3d_caps)(" FOUND: ATI Environment Bump Mapping support\n");
808 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
809 * Won't occur in any real world situation though
811 if(!gl_info->supported[NV_TEXTURE_SHADER2]) {
812 gl_info->supported[ATI_ENVMAP_BUMPMAP] = TRUE;
815 * Apple
817 } else if (strstr(ThisExtn, "GL_APPLE_fence")) {
818 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
819 * The apple extension interacts with some other apple exts. Disable the NV
820 * extension if the apple one is support to prevent confusion in other parts
821 * of the code
823 gl_info->supported[NV_FENCE] = FALSE;
824 gl_info->supported[APPLE_FENCE] = TRUE;
825 } else if (strstr(ThisExtn, "GL_APPLE_client_storage")) {
826 gl_info->supported[APPLE_CLIENT_STORAGE] = TRUE;
829 if (*GL_Extensions == ' ') GL_Extensions++;
832 checkGLcall("extension detection\n");
834 /* In some cases the number of texture stages can be larger than the number
835 * of samplers. The GF4 for example can use only 2 samplers (no fragment
836 * shaders), but 8 texture stages (register combiners). */
837 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
839 /* We can only use ORM_FBO when the hardware supports it. */
840 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
841 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
842 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
845 /* MRTs are currently only supported when FBOs are used. */
846 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
847 gl_info->max_buffers = 1;
850 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
851 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
852 * in case of the latest videocards in the number of pixel/vertex pipelines.
854 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
855 * rendering. Various games use this information to get a rough estimation of the features of the card
856 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
857 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
858 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
859 * not the PCI id.
861 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
862 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
863 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
864 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
865 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
866 * is used for rendering which is not always the case). This would work but it is not very portable. Second
867 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
868 * is limited.
870 * As said most games only use the PCI id to get an indication of the capabilities of the card.
871 * It doesn't really matter if the given id is the correct one if we return the id of a card with
872 * similar 3d features.
874 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
875 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
876 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
877 * won't pass we return a default card. This way is better than maintaining a full card database as even
878 * without a full database we can return a card with similar features. Second the size of the database
879 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
880 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
881 * to distinguishes between different models from that family.
883 switch (gl_info->gl_vendor) {
884 case VENDOR_NVIDIA:
885 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
886 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
888 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
889 if (strstr(gl_info->gl_renderer, "7800") ||
890 strstr(gl_info->gl_renderer, "7900") ||
891 strstr(gl_info->gl_renderer, "7950") ||
892 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
893 strstr(gl_info->gl_renderer, "Quadro FX 5"))
894 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
895 else if(strstr(gl_info->gl_renderer, "6800") ||
896 strstr(gl_info->gl_renderer, "7600"))
897 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
898 else if(strstr(gl_info->gl_renderer, "6600") ||
899 strstr(gl_info->gl_renderer, "6610") ||
900 strstr(gl_info->gl_renderer, "6700"))
901 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
902 else
903 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
904 } else if(WINE_D3D9_CAPABLE(gl_info)) {
905 if (strstr(gl_info->gl_renderer, "5800") ||
906 strstr(gl_info->gl_renderer, "5900") ||
907 strstr(gl_info->gl_renderer, "5950") ||
908 strstr(gl_info->gl_renderer, "Quadro FX"))
909 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
910 else if(strstr(gl_info->gl_renderer, "5600") ||
911 strstr(gl_info->gl_renderer, "5650") ||
912 strstr(gl_info->gl_renderer, "5700") ||
913 strstr(gl_info->gl_renderer, "5750"))
914 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
915 else
916 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
917 } else if(WINE_D3D8_CAPABLE(gl_info)) {
918 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
919 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
920 else
921 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
922 } else if(WINE_D3D7_CAPABLE(gl_info)) {
923 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
924 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
925 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
926 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
927 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
928 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
929 else
930 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
931 } else {
932 if (strstr(gl_info->gl_renderer, "TNT2"))
933 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
934 else
935 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
937 break;
938 case VENDOR_ATI:
939 if(WINE_D3D9_CAPABLE(gl_info)) {
940 /* Radeon R5xx */
941 if (strstr(gl_info->gl_renderer, "X1600") ||
942 strstr(gl_info->gl_renderer, "X1800") ||
943 strstr(gl_info->gl_renderer, "X1900") ||
944 strstr(gl_info->gl_renderer, "X1950"))
945 gl_info->gl_card = CARD_ATI_RADEON_X1600;
946 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
947 else if(strstr(gl_info->gl_renderer, "X700") ||
948 strstr(gl_info->gl_renderer, "X800") ||
949 strstr(gl_info->gl_renderer, "X850") ||
950 strstr(gl_info->gl_renderer, "X1300") ||
951 strstr(gl_info->gl_renderer, "X1400"))
952 gl_info->gl_card = CARD_ATI_RADEON_X700;
953 /* Radeon R3xx */
954 else
955 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
956 } else if(WINE_D3D8_CAPABLE(gl_info)) {
957 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
958 } else if(WINE_D3D7_CAPABLE(gl_info)) {
959 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
960 } else
961 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
962 break;
963 case VENDOR_INTEL:
964 if (strstr(gl_info->gl_renderer, "915GM")) {
965 gl_info->gl_card = CARD_INTEL_I915GM;
966 } else if (strstr(gl_info->gl_renderer, "915G")) {
967 gl_info->gl_card = CARD_INTEL_I915G;
968 } else if (strstr(gl_info->gl_renderer, "865G")) {
969 gl_info->gl_card = CARD_INTEL_I865G;
970 } else if (strstr(gl_info->gl_renderer, "855G")) {
971 gl_info->gl_card = CARD_INTEL_I855G;
972 } else if (strstr(gl_info->gl_renderer, "830G")) {
973 gl_info->gl_card = CARD_INTEL_I830G;
974 } else {
975 gl_info->gl_card = CARD_INTEL_I915G;
977 break;
978 case VENDOR_MESA:
979 case VENDOR_WINE:
980 default:
981 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
982 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
983 * them a good generic choice.
985 gl_info->gl_vendor = VENDOR_NVIDIA;
986 if(WINE_D3D9_CAPABLE(gl_info))
987 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
988 else if(WINE_D3D8_CAPABLE(gl_info))
989 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
990 else if(WINE_D3D7_CAPABLE(gl_info))
991 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
992 else if(WINE_D3D6_CAPABLE(gl_info))
993 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
994 else
995 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
997 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
999 /* Load all the lookup tables
1000 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1001 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1002 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1004 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1005 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1008 for (i = 0; i < MAX_LOOKUPS; i++) {
1009 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1012 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1013 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1014 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1015 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1016 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1017 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1018 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1019 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1020 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1021 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1023 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1024 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1025 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1026 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1027 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1030 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1031 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1032 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1033 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1034 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1035 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1036 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1037 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1038 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1039 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1040 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1041 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1042 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1044 /* TODO: config lookups */
1046 if (display != NULL) {
1047 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1048 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1050 if (NULL == GLX_Extensions) {
1051 ERR(" GLX_Extensions returns NULL\n");
1052 } else {
1053 while (*GLX_Extensions != 0x00) {
1054 const char *Start = GLX_Extensions;
1055 char ThisExtn[256];
1057 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1058 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1059 GLX_Extensions++;
1061 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1062 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1063 if (*GLX_Extensions == ' ') GLX_Extensions++;
1069 WineD3D_ReleaseFakeGLContext();
1070 return return_value;
1073 /**********************************************************
1074 * IWineD3D implementation follows
1075 **********************************************************/
1077 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1078 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1080 /* FIXME: Set to one for now to imply the display */
1081 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1082 return 1;
1085 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1086 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1087 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1088 return WINED3D_OK;
1091 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1092 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1093 POINT pt = { -1, -1 };
1095 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1096 return NULL;
1099 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1100 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1103 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1104 of the same bpp but different resolutions */
1106 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1107 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1108 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1109 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1111 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1112 return 0;
1115 if (Adapter == 0) { /* Display */
1116 int i = 0;
1117 int j = 0;
1119 if (!DEBUG_SINGLE_MODE) {
1120 DEVMODEW DevModeW;
1122 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1123 j++;
1124 switch (Format)
1126 case WINED3DFMT_UNKNOWN:
1127 /* This is for D3D8, do not enumerate P8 here */
1128 if (DevModeW.dmBitsPerPel == 32 ||
1129 DevModeW.dmBitsPerPel == 16) i++;
1130 break;
1131 case WINED3DFMT_X8R8G8B8:
1132 if (DevModeW.dmBitsPerPel == 32) i++;
1133 break;
1134 case WINED3DFMT_R5G6B5:
1135 if (DevModeW.dmBitsPerPel == 16) i++;
1136 break;
1137 case WINED3DFMT_P8:
1138 if (DevModeW.dmBitsPerPel == 8) i++;
1139 break;
1140 default:
1141 /* Skip other modes as they do not match the requested format */
1142 break;
1145 } else {
1146 i = 1;
1147 j = 1;
1150 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1151 return i;
1152 } else {
1153 FIXME_(d3d_caps)("Adapter not primary display\n");
1155 return 0;
1158 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1159 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1160 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1161 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1163 /* Validate the parameters as much as possible */
1164 if (NULL == pMode ||
1165 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1166 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1167 return WINED3DERR_INVALIDCALL;
1170 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1171 DEVMODEW DevModeW;
1172 int ModeIdx = 0;
1173 int i = 0;
1174 int j = 0;
1176 /* If we are filtering to a specific format (D3D9), then need to skip
1177 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1178 just count through the ones with valid bit depths */
1179 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1180 switch (Format)
1182 case WINED3DFMT_UNKNOWN:
1183 /* This is D3D8. Do not enumerate P8 here */
1184 if (DevModeW.dmBitsPerPel == 32 ||
1185 DevModeW.dmBitsPerPel == 16) i++;
1186 break;
1187 case WINED3DFMT_X8R8G8B8:
1188 if (DevModeW.dmBitsPerPel == 32) i++;
1189 break;
1190 case WINED3DFMT_R5G6B5:
1191 if (DevModeW.dmBitsPerPel == 16) i++;
1192 break;
1193 case WINED3DFMT_P8:
1194 if (DevModeW.dmBitsPerPel == 8) i++;
1195 break;
1196 default:
1197 /* Modes that don't match what we support can get an early-out */
1198 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1199 return WINED3DERR_INVALIDCALL;
1203 if (i == 0) {
1204 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1205 return WINED3DERR_INVALIDCALL;
1207 ModeIdx = j - 1;
1209 /* Now get the display mode via the calculated index */
1210 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1211 pMode->Width = DevModeW.dmPelsWidth;
1212 pMode->Height = DevModeW.dmPelsHeight;
1213 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1214 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1215 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1217 if (Format == WINED3DFMT_UNKNOWN)
1219 switch (DevModeW.dmBitsPerPel)
1221 case 8:
1222 pMode->Format = WINED3DFMT_P8;
1223 break;
1224 case 16:
1225 pMode->Format = WINED3DFMT_R5G6B5;
1226 break;
1227 case 32:
1228 pMode->Format = WINED3DFMT_X8R8G8B8;
1229 break;
1230 default:
1231 pMode->Format = WINED3DFMT_UNKNOWN;
1232 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1234 } else {
1235 pMode->Format = Format;
1237 } else {
1238 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1239 return WINED3DERR_INVALIDCALL;
1242 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1243 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1244 DevModeW.dmBitsPerPel);
1246 } else if (DEBUG_SINGLE_MODE) {
1247 /* Return one setting of the format requested */
1248 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1249 pMode->Width = 800;
1250 pMode->Height = 600;
1251 pMode->RefreshRate = 60;
1252 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1253 } else {
1254 FIXME_(d3d_caps)("Adapter not primary display\n");
1257 return WINED3D_OK;
1260 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1261 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1262 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1264 if (NULL == pMode ||
1265 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1266 return WINED3DERR_INVALIDCALL;
1269 if (Adapter == 0) { /* Display */
1270 int bpp = 0;
1271 DEVMODEW DevModeW;
1273 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1274 pMode->Width = DevModeW.dmPelsWidth;
1275 pMode->Height = DevModeW.dmPelsHeight;
1276 bpp = DevModeW.dmBitsPerPel;
1277 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1278 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1280 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1283 switch (bpp) {
1284 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1285 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1286 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1287 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1288 default: pMode->Format = WINED3DFMT_UNKNOWN;
1291 } else {
1292 FIXME_(d3d_caps)("Adapter not primary display\n");
1295 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1296 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1297 return WINED3D_OK;
1300 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1301 Display *display;
1302 HDC device_context;
1303 /* only works with one adapter at the moment... */
1305 /* Get the display */
1306 device_context = GetDC(0);
1307 display = get_display(device_context);
1308 ReleaseDC(0, device_context);
1309 return display;
1312 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1313 and fields being inserted in the middle, a new structure is used in place */
1314 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1315 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1316 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1318 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1320 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1321 return WINED3DERR_INVALIDCALL;
1324 if (Adapter == 0) { /* Display - only device supported for now */
1326 BOOL isGLInfoValid = This->isGLInfoValid;
1328 /* FillGLCaps updates gl_info, but we only want to store and
1329 reuse the values once we have a context which is valid. Values from
1330 a temporary context may differ from the final ones */
1331 if (!isGLInfoValid) {
1332 /* If we don't know the device settings, go query them now */
1333 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1336 /* Return the information requested */
1337 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1338 strcpy(pIdentifier->Driver, "Display");
1339 strcpy(pIdentifier->Description, "Direct3D HAL");
1341 /* Note dx8 doesn't supply a DeviceName */
1342 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1343 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1344 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1345 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1346 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1347 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1348 *(pIdentifier->SubSysId) = 0;
1349 *(pIdentifier->Revision) = 0;
1351 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1352 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1353 *(pIdentifier->WHQLLevel) = 0;
1354 } else {
1355 *(pIdentifier->WHQLLevel) = 1;
1358 } else {
1359 FIXME_(d3d_caps)("Adapter not primary display\n");
1362 return WINED3D_OK;
1365 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1366 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1367 int gl_test;
1368 int rb, gb, bb, ab, type, buf_sz;
1370 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1371 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1372 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1373 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1374 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1375 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1377 switch (Format) {
1378 case WINED3DFMT_X8R8G8B8:
1379 case WINED3DFMT_R8G8B8:
1380 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1381 break;
1382 case WINED3DFMT_A8R8G8B8:
1383 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1384 break;
1385 case WINED3DFMT_A2R10G10B10:
1386 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1387 break;
1388 case WINED3DFMT_X1R5G5B5:
1389 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1390 break;
1391 case WINED3DFMT_A1R5G5B5:
1392 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1393 break;
1394 case WINED3DFMT_X4R4G4B4:
1395 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1396 break;
1397 case WINED3DFMT_R5G6B5:
1398 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1399 break;
1400 case WINED3DFMT_R3G3B2:
1401 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1402 break;
1403 case WINED3DFMT_A8P8:
1404 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1405 break;
1406 case WINED3DFMT_P8:
1407 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1408 break;
1409 default:
1410 break;
1412 return FALSE;
1413 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1414 switch (Format) {
1415 case WINED3DFMT_X8R8G8B8:
1416 case WINED3DFMT_R8G8B8:
1417 case WINED3DFMT_A8R8G8B8:
1418 case WINED3DFMT_A2R10G10B10:
1419 case WINED3DFMT_X1R5G5B5:
1420 case WINED3DFMT_A1R5G5B5:
1421 case WINED3DFMT_R5G6B5:
1422 case WINED3DFMT_R3G3B2:
1423 case WINED3DFMT_A8P8:
1424 case WINED3DFMT_P8:
1425 return TRUE;
1426 default:
1427 break;
1429 return FALSE;
1430 #endif
1433 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1434 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1435 int gl_test;
1436 int db, sb;
1438 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1439 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1441 switch (Format) {
1442 case WINED3DFMT_D16:
1443 case WINED3DFMT_D16_LOCKABLE:
1444 if (16 == db) return TRUE;
1445 break;
1446 case WINED3DFMT_D32:
1447 if (32 == db) return TRUE;
1448 break;
1449 case WINED3DFMT_D15S1:
1450 if (15 == db) return TRUE;
1451 break;
1452 case WINED3DFMT_D24S8:
1453 if (24 == db && 8 == sb) return TRUE;
1454 break;
1455 case WINED3DFMT_D24FS8:
1456 if (24 == db && 8 == sb) return TRUE;
1457 break;
1458 case WINED3DFMT_D24X8:
1459 if (24 == db) return TRUE;
1460 break;
1461 case WINED3DFMT_D24X4S4:
1462 if (24 == db && 4 == sb) return TRUE;
1463 break;
1464 case WINED3DFMT_D32F_LOCKABLE:
1465 if (32 == db) return TRUE;
1466 break;
1467 default:
1468 break;
1470 return FALSE;
1471 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1472 switch (Format) {
1473 case WINED3DFMT_D16:
1474 case WINED3DFMT_D16_LOCKABLE:
1475 case WINED3DFMT_D32:
1476 case WINED3DFMT_D15S1:
1477 case WINED3DFMT_D24S8:
1478 case WINED3DFMT_D24FS8:
1479 case WINED3DFMT_D24X8:
1480 case WINED3DFMT_D24X4S4:
1481 case WINED3DFMT_D32F_LOCKABLE:
1482 return TRUE;
1483 default:
1484 break;
1486 return FALSE;
1487 #endif
1490 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1491 WINED3DFORMAT AdapterFormat,
1492 WINED3DFORMAT RenderTargetFormat,
1493 WINED3DFORMAT DepthStencilFormat) {
1494 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1495 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1496 GLXFBConfig* cfgs = NULL;
1497 int nCfgs = 0;
1498 int it;
1500 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1501 This, Adapter,
1502 DeviceType, debug_d3ddevicetype(DeviceType),
1503 AdapterFormat, debug_d3dformat(AdapterFormat),
1504 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1505 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1507 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1508 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1509 return WINED3DERR_INVALIDCALL;
1512 if(WineD3D_CreateFakeGLContext())
1513 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1515 if (cfgs) {
1516 for (it = 0; it < nCfgs; ++it) {
1517 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1518 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1519 hr = WINED3D_OK;
1520 break ;
1524 XFree(cfgs);
1525 if(hr != WINED3D_OK)
1526 ERR("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1527 } else {
1528 ERR_(d3d_caps)("returning WINED3D_OK even so CreateFakeGLContext or glXGetFBConfigs failed\n");
1529 hr = WINED3D_OK;
1532 WineD3D_ReleaseFakeGLContext();
1534 if (hr != WINED3D_OK)
1535 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1537 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1538 return hr;
1541 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1542 WINED3DFORMAT SurfaceFormat,
1543 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1545 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1546 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1547 This,
1548 Adapter,
1549 DeviceType, debug_d3ddevicetype(DeviceType),
1550 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1551 Windowed,
1552 MultiSampleType,
1553 pQualityLevels);
1555 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1556 return WINED3DERR_INVALIDCALL;
1559 if (pQualityLevels != NULL) {
1560 static int s_single_shot = 0;
1561 if (!s_single_shot) {
1562 FIXME("Quality levels unsupported at present\n");
1563 s_single_shot = 1;
1565 *pQualityLevels = 1; /* Guess at a value! */
1568 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1569 return WINED3DERR_NOTAVAILABLE;
1572 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1573 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1575 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1576 GLXFBConfig* cfgs = NULL;
1577 int nCfgs = 0;
1578 int it;
1579 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1581 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1582 This,
1583 Adapter,
1584 CheckType, debug_d3ddevicetype(CheckType),
1585 DisplayFormat, debug_d3dformat(DisplayFormat),
1586 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1587 Windowed);
1589 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1590 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1591 return WINED3DERR_INVALIDCALL;
1594 if (WineD3D_CreateFakeGLContext()) {
1595 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1596 for (it = 0; it < nCfgs; ++it) {
1597 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1598 hr = WINED3D_OK;
1599 TRACE_(d3d_caps)("OK\n");
1600 break ;
1603 if(cfgs) XFree(cfgs);
1604 if(hr != WINED3D_OK)
1605 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1606 WineD3D_ReleaseFakeGLContext();
1609 if(hr != WINED3D_OK)
1610 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1612 return hr;
1615 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1616 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1617 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1618 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1619 This,
1620 Adapter,
1621 DeviceType, debug_d3ddevicetype(DeviceType),
1622 AdapterFormat, debug_d3dformat(AdapterFormat),
1623 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1624 RType, debug_d3dresourcetype(RType),
1625 CheckFormat, debug_d3dformat(CheckFormat));
1627 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1628 return WINED3DERR_INVALIDCALL;
1631 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1632 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1633 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1634 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1635 TRACE_(d3d_caps)("[FAILED]\n");
1636 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1639 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1640 switch (CheckFormat) {
1641 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1642 * Windows supports only those 3, and enumerating the other formats confuses applications
1644 case WINED3DFMT_D24S8:
1645 case WINED3DFMT_D24X8:
1646 case WINED3DFMT_D16:
1647 TRACE_(d3d_caps)("[OK]\n");
1648 return WINED3D_OK;
1649 case WINED3DFMT_D16_LOCKABLE:
1650 case WINED3DFMT_D24FS8:
1651 case WINED3DFMT_D32F_LOCKABLE:
1652 case WINED3DFMT_D24X4S4:
1653 case WINED3DFMT_D15S1:
1654 case WINED3DFMT_D32:
1655 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1656 return WINED3DERR_NOTAVAILABLE;
1657 default:
1658 TRACE_(d3d_caps)("[FAILED]\n");
1659 return WINED3DERR_NOTAVAILABLE;
1661 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1662 switch (CheckFormat) {
1663 case WINED3DFMT_R8G8B8:
1664 case WINED3DFMT_A8R8G8B8:
1665 case WINED3DFMT_X8R8G8B8:
1666 case WINED3DFMT_R5G6B5:
1667 case WINED3DFMT_X1R5G5B5:
1668 case WINED3DFMT_A1R5G5B5:
1669 case WINED3DFMT_A4R4G4B4:
1670 case WINED3DFMT_R3G3B2:
1671 case WINED3DFMT_X4R4G4B4:
1672 case WINED3DFMT_A8B8G8R8:
1673 case WINED3DFMT_X8B8G8R8:
1674 case WINED3DFMT_P8:
1675 TRACE_(d3d_caps)("[OK]\n");
1676 return WINED3D_OK;
1677 case WINED3DFMT_R16F:
1678 case WINED3DFMT_A16B16G16R16F:
1679 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1680 TRACE_(d3d_caps)("[FAILED]\n");
1681 return WINED3DERR_NOTAVAILABLE;
1683 TRACE_(d3d_caps)("[OK]\n");
1684 return WINED3D_OK;
1685 default:
1686 TRACE_(d3d_caps)("[FAILED]\n");
1687 return WINED3DERR_NOTAVAILABLE;
1689 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1690 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1691 switch (CheckFormat) {
1692 case WINED3DFMT_V8U8:
1693 TRACE_(d3d_caps)("[OK]\n");
1694 return WINED3D_OK;
1695 /* TODO: Other bump map formats */
1696 default:
1697 TRACE_(d3d_caps)("[FAILED]\n");
1698 return WINED3DERR_NOTAVAILABLE;
1701 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1702 switch (CheckFormat) {
1703 case WINED3DFMT_V8U8:
1704 TRACE_(d3d_caps)("[OK]\n");
1705 return WINED3D_OK;
1706 default:
1707 TRACE_(d3d_caps)("[FAILED]\n");
1708 return WINED3DERR_NOTAVAILABLE;
1711 TRACE_(d3d_caps)("[FAILED]\n");
1712 return WINED3DERR_NOTAVAILABLE;
1715 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1716 switch (CheckFormat) {
1717 case WINED3DFMT_DXT1:
1718 case WINED3DFMT_DXT2:
1719 case WINED3DFMT_DXT3:
1720 case WINED3DFMT_DXT4:
1721 case WINED3DFMT_DXT5:
1722 TRACE_(d3d_caps)("[OK]\n");
1723 return WINED3D_OK;
1724 default:
1725 break; /* Avoid compiler warnings */
1729 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1731 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1733 switch (CheckFormat) {
1734 case WINED3DFMT_R16F:
1735 case WINED3DFMT_A16B16G16R16F:
1736 if (!half_pixel_support) break;
1737 case WINED3DFMT_R32F:
1738 case WINED3DFMT_A32B32G32R32F:
1739 TRACE_(d3d_caps)("[OK]\n");
1740 return WINED3D_OK;
1741 default:
1742 break; /* Avoid compiler warnings */
1746 /* This format is nothing special and it is supported perfectly.
1747 * However, ati and nvidia driver on windows do not mark this format as
1748 * supported (tested with the dxCapsViewer) and pretending to
1749 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1750 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1751 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1753 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1754 TRACE_(d3d_caps)("[FAILED]\n");
1755 return WINED3DERR_NOTAVAILABLE;
1758 switch (CheckFormat) {
1760 /*****
1761 * supported: RGB(A) formats
1763 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1764 case WINED3DFMT_A8R8G8B8:
1765 case WINED3DFMT_X8R8G8B8:
1766 case WINED3DFMT_R5G6B5:
1767 case WINED3DFMT_X1R5G5B5:
1768 case WINED3DFMT_A1R5G5B5:
1769 case WINED3DFMT_A4R4G4B4:
1770 case WINED3DFMT_R3G3B2:
1771 case WINED3DFMT_A8:
1772 case WINED3DFMT_A8R3G3B2:
1773 case WINED3DFMT_X4R4G4B4:
1774 case WINED3DFMT_A8B8G8R8:
1775 case WINED3DFMT_X8B8G8R8:
1776 case WINED3DFMT_A2R10G10B10:
1777 case WINED3DFMT_A2B10G10R10:
1778 TRACE_(d3d_caps)("[OK]\n");
1779 return WINED3D_OK;
1781 /*****
1782 * supported: Palettized
1784 case WINED3DFMT_P8:
1785 TRACE_(d3d_caps)("[OK]\n");
1786 return WINED3D_OK;
1788 /*****
1789 * Supported: (Alpha)-Luminance
1791 case WINED3DFMT_L8:
1792 case WINED3DFMT_A8L8:
1793 case WINED3DFMT_A4L4:
1794 TRACE_(d3d_caps)("[OK]\n");
1795 return WINED3D_OK;
1797 /*****
1798 * Not supported for now: Bump mapping formats
1799 * Enable some because games often fail when they are not available
1800 * and are still playable even without bump mapping
1802 case WINED3DFMT_V8U8:
1803 case WINED3DFMT_V16U16:
1804 case WINED3DFMT_L6V5U5:
1805 case WINED3DFMT_X8L8V8U8:
1806 case WINED3DFMT_Q8W8V8U8:
1807 case WINED3DFMT_W11V11U10:
1808 case WINED3DFMT_A2W10V10U10:
1809 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1810 return WINED3D_OK;
1812 /*****
1813 * DXTN Formats: Handled above
1814 * WINED3DFMT_DXT1
1815 * WINED3DFMT_DXT2
1816 * WINED3DFMT_DXT3
1817 * WINED3DFMT_DXT4
1818 * WINED3DFMT_DXT5
1821 /*****
1822 * Odd formats - not supported
1824 case WINED3DFMT_VERTEXDATA:
1825 case WINED3DFMT_INDEX16:
1826 case WINED3DFMT_INDEX32:
1827 case WINED3DFMT_Q16W16V16U16:
1828 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1829 return WINED3DERR_NOTAVAILABLE;
1831 /*****
1832 * Float formats: Not supported right now
1834 case WINED3DFMT_G16R16F:
1835 case WINED3DFMT_G32R32F:
1836 case WINED3DFMT_CxV8U8:
1837 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1838 return WINED3DERR_NOTAVAILABLE;
1840 /* Not supported */
1841 case WINED3DFMT_G16R16:
1842 case WINED3DFMT_A16B16G16R16:
1843 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1844 return WINED3DERR_NOTAVAILABLE;
1846 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1847 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1848 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1849 * We can do instancing with all shader versions, but we need vertex shaders.
1851 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1852 * to enable instancing. WineD3D doesn't need that and just ignores it.
1854 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1856 case WINEMAKEFOURCC('I','N','S','T'):
1857 TRACE("ATI Instancing check hack\n");
1858 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1859 TRACE_(d3d_caps)("[OK]\n");
1860 return WINED3D_OK;
1861 } else {
1862 TRACE_(d3d_caps)("[FAILED]\n");
1863 return WINED3DERR_NOTAVAILABLE;
1866 default:
1867 break;
1870 TRACE_(d3d_caps)("[FAILED]\n");
1871 return WINED3DERR_NOTAVAILABLE;
1874 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1875 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1876 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1878 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1879 This,
1880 Adapter,
1881 DeviceType, debug_d3ddevicetype(DeviceType),
1882 SourceFormat, debug_d3dformat(SourceFormat),
1883 TargetFormat, debug_d3dformat(TargetFormat));
1884 return WINED3D_OK;
1887 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1888 subset of a D3DCAPS9 structure. However, it has to come via a void *
1889 as the d3d8 interface cannot import the d3d9 header */
1890 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1892 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1893 int vs_selected_mode;
1894 int ps_selected_mode;
1896 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1898 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1899 return WINED3DERR_INVALIDCALL;
1902 /* FIXME: GL info should be per adapter */
1904 /* If we don't know the device settings, go query them now */
1905 if (!This->isGLInfoValid) {
1906 /* use the desktop window to fill gl caps */
1907 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1909 /* We are running off a real context, save the values */
1910 if (rc) This->isGLInfoValid = TRUE;
1912 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1914 /* This function should *not* be modifying GL caps
1915 * TODO: move the functionality where it belongs */
1916 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1918 /* ------------------------------------------------
1919 The following fields apply to both d3d8 and d3d9
1920 ------------------------------------------------ */
1921 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1922 *pCaps->AdapterOrdinal = Adapter;
1924 *pCaps->Caps = 0;
1925 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1926 WINED3DCAPS2_FULLSCREENGAMMA |
1927 WINED3DCAPS2_DYNAMICTEXTURES;
1928 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1929 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1931 *pCaps->CursorCaps = 0;
1934 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1935 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1936 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1937 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1938 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1939 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1940 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1941 WINED3DDEVCAPS_PUREDEVICE |
1942 WINED3DDEVCAPS_HWRASTERIZATION |
1943 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1944 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1945 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1946 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1947 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1949 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1950 WINED3DPMISCCAPS_CULLCCW |
1951 WINED3DPMISCCAPS_CULLCW |
1952 WINED3DPMISCCAPS_COLORWRITEENABLE |
1953 WINED3DPMISCCAPS_CLIPTLVERTS |
1954 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1955 WINED3DPMISCCAPS_MASKZ |
1956 WINED3DPMISCCAPS_BLENDOP;
1957 /* TODO:
1958 WINED3DPMISCCAPS_NULLREFERENCE
1959 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1960 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1961 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1962 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1963 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1964 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1966 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1967 #if 0
1968 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1969 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1970 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1971 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1972 #endif
1974 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1975 WINED3DPRASTERCAPS_PAT |
1976 WINED3DPRASTERCAPS_WFOG |
1977 WINED3DPRASTERCAPS_ZFOG |
1978 WINED3DPRASTERCAPS_FOGVERTEX |
1979 WINED3DPRASTERCAPS_FOGTABLE |
1980 WINED3DPRASTERCAPS_FOGRANGE |
1981 WINED3DPRASTERCAPS_STIPPLE |
1982 WINED3DPRASTERCAPS_SUBPIXEL |
1983 WINED3DPRASTERCAPS_ZTEST |
1984 WINED3DPRASTERCAPS_SCISSORTEST |
1985 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1986 WINED3DPRASTERCAPS_DEPTHBIAS;
1988 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1989 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1990 WINED3DPRASTERCAPS_ZBIAS |
1991 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1993 /* FIXME Add:
1994 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1995 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1996 WINED3DPRASTERCAPS_ANTIALIASEDGES
1997 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1998 WINED3DPRASTERCAPS_WBUFFER */
2000 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2001 WINED3DPCMPCAPS_EQUAL |
2002 WINED3DPCMPCAPS_GREATER |
2003 WINED3DPCMPCAPS_GREATEREQUAL |
2004 WINED3DPCMPCAPS_LESS |
2005 WINED3DPCMPCAPS_LESSEQUAL |
2006 WINED3DPCMPCAPS_NEVER |
2007 WINED3DPCMPCAPS_NOTEQUAL;
2009 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2010 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2011 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2012 WINED3DPBLENDCAPS_DESTALPHA |
2013 WINED3DPBLENDCAPS_DESTCOLOR |
2014 WINED3DPBLENDCAPS_INVDESTALPHA |
2015 WINED3DPBLENDCAPS_INVDESTCOLOR |
2016 WINED3DPBLENDCAPS_INVSRCALPHA |
2017 WINED3DPBLENDCAPS_INVSRCCOLOR |
2018 WINED3DPBLENDCAPS_ONE |
2019 WINED3DPBLENDCAPS_SRCALPHA |
2020 WINED3DPBLENDCAPS_SRCALPHASAT |
2021 WINED3DPBLENDCAPS_SRCCOLOR |
2022 WINED3DPBLENDCAPS_ZERO;
2024 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2025 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2026 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2027 WINED3DPBLENDCAPS_DESTALPHA |
2028 WINED3DPBLENDCAPS_DESTCOLOR |
2029 WINED3DPBLENDCAPS_INVDESTALPHA |
2030 WINED3DPBLENDCAPS_INVDESTCOLOR |
2031 WINED3DPBLENDCAPS_INVSRCALPHA |
2032 WINED3DPBLENDCAPS_INVSRCCOLOR |
2033 WINED3DPBLENDCAPS_ONE |
2034 WINED3DPBLENDCAPS_SRCALPHA |
2035 WINED3DPBLENDCAPS_SRCALPHASAT |
2036 WINED3DPBLENDCAPS_SRCCOLOR |
2037 WINED3DPBLENDCAPS_ZERO;
2039 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2040 WINED3DPCMPCAPS_EQUAL |
2041 WINED3DPCMPCAPS_GREATER |
2042 WINED3DPCMPCAPS_GREATEREQUAL |
2043 WINED3DPCMPCAPS_LESS |
2044 WINED3DPCMPCAPS_LESSEQUAL |
2045 WINED3DPCMPCAPS_NEVER |
2046 WINED3DPCMPCAPS_NOTEQUAL;
2048 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2049 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2050 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2051 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2052 WINED3DPSHADECAPS_COLORFLATRGB |
2053 WINED3DPSHADECAPS_FOGFLAT |
2054 WINED3DPSHADECAPS_FOGGOURAUD |
2055 WINED3DPSHADECAPS_SPECULARFLATRGB;
2057 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2058 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2059 WINED3DPTEXTURECAPS_BORDER |
2060 WINED3DPTEXTURECAPS_MIPMAP |
2061 WINED3DPTEXTURECAPS_PROJECTED |
2062 WINED3DPTEXTURECAPS_PERSPECTIVE |
2063 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2065 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2066 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2067 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2068 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2071 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2072 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2073 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2074 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2078 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2079 WINED3DPTFILTERCAPS_MAGFPOINT |
2080 WINED3DPTFILTERCAPS_MINFLINEAR |
2081 WINED3DPTFILTERCAPS_MINFPOINT |
2082 WINED3DPTFILTERCAPS_MIPFLINEAR |
2083 WINED3DPTFILTERCAPS_MIPFPOINT |
2084 WINED3DPTFILTERCAPS_LINEAR |
2085 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2086 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2087 WINED3DPTFILTERCAPS_MIPLINEAR |
2088 WINED3DPTFILTERCAPS_MIPNEAREST |
2089 WINED3DPTFILTERCAPS_NEAREST;
2091 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2092 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2093 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2096 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2097 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2098 WINED3DPTFILTERCAPS_MAGFPOINT |
2099 WINED3DPTFILTERCAPS_MINFLINEAR |
2100 WINED3DPTFILTERCAPS_MINFPOINT |
2101 WINED3DPTFILTERCAPS_MIPFLINEAR |
2102 WINED3DPTFILTERCAPS_MIPFPOINT |
2103 WINED3DPTFILTERCAPS_LINEAR |
2104 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2105 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2106 WINED3DPTFILTERCAPS_MIPLINEAR |
2107 WINED3DPTFILTERCAPS_MIPNEAREST |
2108 WINED3DPTFILTERCAPS_NEAREST;
2110 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2111 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2112 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2114 } else
2115 *pCaps->CubeTextureFilterCaps = 0;
2117 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2118 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2119 WINED3DPTFILTERCAPS_MAGFPOINT |
2120 WINED3DPTFILTERCAPS_MINFLINEAR |
2121 WINED3DPTFILTERCAPS_MINFPOINT |
2122 WINED3DPTFILTERCAPS_MIPFLINEAR |
2123 WINED3DPTFILTERCAPS_MIPFPOINT |
2124 WINED3DPTFILTERCAPS_LINEAR |
2125 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2126 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2127 WINED3DPTFILTERCAPS_MIPLINEAR |
2128 WINED3DPTFILTERCAPS_MIPNEAREST |
2129 WINED3DPTFILTERCAPS_NEAREST;
2130 } else
2131 *pCaps->VolumeTextureFilterCaps = 0;
2133 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2134 WINED3DPTADDRESSCAPS_CLAMP |
2135 WINED3DPTADDRESSCAPS_WRAP;
2137 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2138 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2140 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2141 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2143 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2144 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2147 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2148 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2149 WINED3DPTADDRESSCAPS_CLAMP |
2150 WINED3DPTADDRESSCAPS_WRAP;
2151 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2152 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2154 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2155 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2157 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2158 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2160 } else
2161 *pCaps->VolumeTextureAddressCaps = 0;
2163 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2164 WINED3DLINECAPS_ZTEST;
2165 /* FIXME: Add
2166 WINED3DLINECAPS_BLEND
2167 WINED3DLINECAPS_ALPHACMP
2168 WINED3DLINECAPS_FOG */
2170 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2171 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2173 if(GL_SUPPORT(EXT_TEXTURE3D))
2174 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2175 else
2176 *pCaps->MaxVolumeExtent = 0;
2178 *pCaps->MaxTextureRepeat = 32768;
2179 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2180 *pCaps->MaxVertexW = 1.0;
2182 *pCaps->GuardBandLeft = 0;
2183 *pCaps->GuardBandTop = 0;
2184 *pCaps->GuardBandRight = 0;
2185 *pCaps->GuardBandBottom = 0;
2187 *pCaps->ExtentsAdjust = 0;
2189 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2190 WINED3DSTENCILCAPS_INCRSAT |
2191 WINED3DSTENCILCAPS_INVERT |
2192 WINED3DSTENCILCAPS_KEEP |
2193 WINED3DSTENCILCAPS_REPLACE |
2194 WINED3DSTENCILCAPS_ZERO;
2195 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2196 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2197 WINED3DSTENCILCAPS_INCR;
2199 if ( This->dxVersion > 8 &&
2200 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2201 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2202 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2205 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2207 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2208 WINED3DTEXOPCAPS_ADDSIGNED |
2209 WINED3DTEXOPCAPS_ADDSIGNED2X |
2210 WINED3DTEXOPCAPS_MODULATE |
2211 WINED3DTEXOPCAPS_MODULATE2X |
2212 WINED3DTEXOPCAPS_MODULATE4X |
2213 WINED3DTEXOPCAPS_SELECTARG1 |
2214 WINED3DTEXOPCAPS_SELECTARG2 |
2215 WINED3DTEXOPCAPS_DISABLE;
2217 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2218 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2219 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2220 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2221 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2222 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2223 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2224 WINED3DTEXOPCAPS_LERP |
2225 WINED3DTEXOPCAPS_SUBTRACT;
2227 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2228 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2229 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2230 WINED3DTEXOPCAPS_MULTIPLYADD |
2231 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2232 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2233 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2235 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2236 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2238 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2239 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2240 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2243 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2244 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2245 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2246 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2247 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2248 * and 3D textures. It also allows us to keep the code simpler by having texture
2249 * shaders constantly enabled.
2251 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2252 /* TODO: Luminance bump map? */
2254 #if 0
2255 /* FIXME: Add
2256 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2257 WINED3DTEXOPCAPS_PREMODULATE */
2258 #endif
2260 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2261 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2262 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2263 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2265 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2266 *pCaps->MaxVertexBlendMatrixIndex = 0;
2268 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2269 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2272 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2273 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2274 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2275 WINED3DVTXPCAPS_LOCALVIEWER |
2276 WINED3DVTXPCAPS_VERTEXFOG |
2277 WINED3DVTXPCAPS_TEXGEN;
2278 /* FIXME: Add
2279 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2281 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2282 *pCaps->MaxVertexIndex = 0xFFFFF;
2283 *pCaps->MaxStreams = MAX_STREAMS;
2284 *pCaps->MaxStreamStride = 1024;
2286 if (vs_selected_mode == SHADER_GLSL) {
2287 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2288 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2289 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2290 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2291 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2292 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2293 else
2294 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2295 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2296 } else if (vs_selected_mode == SHADER_ARB) {
2297 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2298 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2299 } else {
2300 *pCaps->VertexShaderVersion = 0;
2301 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2304 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2306 if (ps_selected_mode == SHADER_GLSL) {
2307 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2308 in case of GeforceFX cards. */
2309 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2310 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2311 else
2312 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2313 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2314 *pCaps->PixelShader1xMaxValue = 1.0;
2315 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2316 } else if (ps_selected_mode == SHADER_ARB) {
2317 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2318 *pCaps->PixelShader1xMaxValue = 1.0;
2319 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2320 } else {
2321 *pCaps->PixelShaderVersion = 0;
2322 *pCaps->PixelShader1xMaxValue = 0.0;
2323 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2326 /* ------------------------------------------------
2327 The following fields apply to d3d9 only
2328 ------------------------------------------------ */
2329 if (This->dxVersion > 8) {
2330 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2331 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2332 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2333 *pCaps->MaxNpatchTessellationLevel = 0;
2334 *pCaps->MasterAdapterOrdinal = 0;
2335 *pCaps->AdapterOrdinalInGroup = 0;
2336 *pCaps->NumberOfAdaptersInGroup = 1;
2338 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2339 /* OpenGL supports all the formats below, perhaps not always
2340 * without conversion, but it supports them.
2341 * Further GLSL doesn't seem to have an official unsigned type so
2342 * don't advertise it yet as I'm not sure how we handle it.
2343 * We might need to add some clamping in the shader engine to
2344 * support it.
2345 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2346 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2347 WINED3DDTCAPS_UBYTE4N |
2348 WINED3DDTCAPS_SHORT2N |
2349 WINED3DDTCAPS_SHORT4N |
2350 WINED3DDTCAPS_FLOAT16_2 |
2351 WINED3DDTCAPS_FLOAT16_4;
2353 } else
2354 *pCaps->DeclTypes = 0;
2356 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2359 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2360 WINED3DPTFILTERCAPS_MAGFPOINT |
2361 WINED3DPTFILTERCAPS_MINFLINEAR |
2362 WINED3DPTFILTERCAPS_MAGFLINEAR;
2363 *pCaps->VertexTextureFilterCaps = 0;
2365 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2366 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2367 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2368 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2369 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2370 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2371 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2373 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2374 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2375 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2376 *pCaps->VS20Caps.Caps = 0;
2377 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2378 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2379 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2381 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2382 *pCaps->MaxVertexShader30InstructionSlots = 0;
2383 } else { /* VS 1.x */
2384 *pCaps->VS20Caps.Caps = 0;
2385 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2386 *pCaps->VS20Caps.NumTemps = 0;
2387 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2389 *pCaps->MaxVShaderInstructionsExecuted = 0;
2390 *pCaps->MaxVertexShader30InstructionSlots = 0;
2393 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2394 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2395 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2397 /* 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 */
2398 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2399 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2400 WINED3DPS20CAPS_PREDICATION |
2401 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2402 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2403 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2404 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2405 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2406 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2408 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2409 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2410 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2411 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2412 *pCaps->PS20Caps.Caps = 0;
2413 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2414 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2415 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2416 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2418 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2419 *pCaps->MaxPixelShader30InstructionSlots = 0;
2420 } else { /* PS 1.x */
2421 *pCaps->PS20Caps.Caps = 0;
2422 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2423 *pCaps->PS20Caps.NumTemps = 0;
2424 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2425 *pCaps->PS20Caps.NumInstructionSlots = 0;
2427 *pCaps->MaxPShaderInstructionsExecuted = 0;
2428 *pCaps->MaxPixelShader30InstructionSlots = 0;
2432 return WINED3D_OK;
2435 static unsigned int glsl_program_key_hash(void *key) {
2436 glsl_program_key_t *k = (glsl_program_key_t *)key;
2438 unsigned int hash = k->vshader | k->pshader << 16;
2439 hash += ~(hash << 15);
2440 hash ^= (hash >> 10);
2441 hash += (hash << 3);
2442 hash ^= (hash >> 6);
2443 hash += ~(hash << 11);
2444 hash ^= (hash >> 16);
2446 return hash;
2449 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2450 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2451 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2453 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2456 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2457 and fields being inserted in the middle, a new structure is used in place */
2458 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2459 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2460 IUnknown *parent) {
2462 IWineD3DDeviceImpl *object = NULL;
2463 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2464 HDC hDC;
2465 HRESULT temp_result;
2467 /* Validate the adapter number */
2468 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2469 return WINED3DERR_INVALIDCALL;
2472 /* Create a WineD3DDevice object */
2473 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2474 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2475 TRACE("Created WineD3DDevice object @ %p\n", object);
2476 if (NULL == object) {
2477 return WINED3DERR_OUTOFVIDEOMEMORY;
2480 /* Set up initial COM information */
2481 object->lpVtbl = &IWineD3DDevice_Vtbl;
2482 object->ref = 1;
2483 object->wineD3D = iface;
2484 IWineD3D_AddRef(object->wineD3D);
2485 object->parent = parent;
2487 /* Set the state up as invalid until the device is fully created */
2488 object->state = WINED3DERR_DRIVERINTERNALERROR;
2490 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2491 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2493 /* Save the creation parameters */
2494 object->createParms.AdapterOrdinal = Adapter;
2495 object->createParms.DeviceType = DeviceType;
2496 object->createParms.hFocusWindow = hFocusWindow;
2497 object->createParms.BehaviorFlags = BehaviourFlags;
2499 /* Initialize other useful values */
2500 object->adapterNo = Adapter;
2501 object->devType = DeviceType;
2503 TRACE("(%p) : Creating stateblock\n", This);
2504 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2505 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2506 WINED3DSBT_INIT,
2507 (IWineD3DStateBlock **)&object->stateBlock,
2508 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2509 WARN("Failed to create stateblock\n");
2510 goto create_device_error;
2512 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2513 object->updateStateBlock = object->stateBlock;
2514 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2515 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2517 /* Setup some defaults for creating the implicit swapchain */
2518 ENTER_GL();
2519 /* FIXME: GL info should be per adapter */
2520 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2521 LEAVE_GL();
2522 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2523 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2524 object->shader_backend = &glsl_shader_backend;
2525 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2526 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2527 object->shader_backend = &arb_program_shader_backend;
2528 } else {
2529 object->shader_backend = &none_shader_backend;
2532 /* This function should *not* be modifying GL caps
2533 * TODO: move the functionality where it belongs */
2534 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2536 temp_result = allocate_shader_constants(object->updateStateBlock);
2537 if (WINED3D_OK != temp_result)
2538 return temp_result;
2540 object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2541 object->fbo_color_attachments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2542 object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
2544 /* set the state of the device to valid */
2545 object->state = WINED3D_OK;
2547 /* Get the initial screen setup for ddraw */
2548 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2549 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2550 hDC = GetDC(0);
2551 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2552 ReleaseDC(0, hDC);
2554 return WINED3D_OK;
2555 create_device_error:
2557 /* Set the device state to error */
2558 object->state = WINED3DERR_DRIVERINTERNALERROR;
2560 if (object->updateStateBlock != NULL) {
2561 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2562 object->updateStateBlock = NULL;
2564 if (object->stateBlock != NULL) {
2565 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2566 object->stateBlock = NULL;
2568 if (object->render_targets[0] != NULL) {
2569 IWineD3DSurface_Release(object->render_targets[0]);
2570 object->render_targets[0] = NULL;
2572 if (object->stencilBufferTarget != NULL) {
2573 IWineD3DSurface_Release(object->stencilBufferTarget);
2574 object->stencilBufferTarget = NULL;
2576 HeapFree(GetProcessHeap(), 0, object);
2577 *ppReturnedDeviceInterface = NULL;
2578 return WINED3DERR_INVALIDCALL;
2582 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2583 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2584 IUnknown_AddRef(This->parent);
2585 *pParent = This->parent;
2586 return WINED3D_OK;
2589 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2590 IUnknown* surfaceParent;
2591 TRACE("(%p) call back\n", pSurface);
2593 /* Now, release the parent, which will take care of cleaning up the surface for us */
2594 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2595 IUnknown_Release(surfaceParent);
2596 return IUnknown_Release(surfaceParent);
2599 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2600 IUnknown* volumeParent;
2601 TRACE("(%p) call back\n", pVolume);
2603 /* Now, release the parent, which will take care of cleaning up the volume for us */
2604 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2605 IUnknown_Release(volumeParent);
2606 return IUnknown_Release(volumeParent);
2609 /**********************************************************
2610 * IWineD3D VTbl follows
2611 **********************************************************/
2613 const IWineD3DVtbl IWineD3D_Vtbl =
2615 /* IUnknown */
2616 IWineD3DImpl_QueryInterface,
2617 IWineD3DImpl_AddRef,
2618 IWineD3DImpl_Release,
2619 /* IWineD3D */
2620 IWineD3DImpl_GetParent,
2621 IWineD3DImpl_GetAdapterCount,
2622 IWineD3DImpl_RegisterSoftwareDevice,
2623 IWineD3DImpl_GetAdapterMonitor,
2624 IWineD3DImpl_GetAdapterModeCount,
2625 IWineD3DImpl_EnumAdapterModes,
2626 IWineD3DImpl_GetAdapterDisplayMode,
2627 IWineD3DImpl_GetAdapterIdentifier,
2628 IWineD3DImpl_CheckDeviceMultiSampleType,
2629 IWineD3DImpl_CheckDepthStencilMatch,
2630 IWineD3DImpl_CheckDeviceType,
2631 IWineD3DImpl_CheckDeviceFormat,
2632 IWineD3DImpl_CheckDeviceFormatConversion,
2633 IWineD3DImpl_GetDeviceCaps,
2634 IWineD3DImpl_CreateDevice