wined3d: Restore blitting environment after modifying it.
[wine/testsucceed.git] / dlls / wined3d / directx.c
blob398aca0853a107d51de763efa7a2f0b3205abfae
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 /* Uncomment this to force only a single display mode to be exposed: */
27 /*#define DEBUG_SINGLE_MODE*/
30 #include "config.h"
31 #include <assert.h>
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
36 #define GLINFO_LOCATION This->gl_info
38 /**********************************************************
39 * Utility functions follow
40 **********************************************************/
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
46 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
47 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
48 X11DRV_GET_FONT, /* get current X font for a DC */
51 /* retrieve the X display to use on a given DC */
52 inline static Display *get_display( HDC hdc )
54 Display *display;
55 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
57 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
58 sizeof(display), (LPSTR)&display )) display = NULL;
59 return display;
62 /* lookup tables */
63 int minLookup[MAX_LOOKUPS];
64 int maxLookup[MAX_LOOKUPS];
65 DWORD *stateLookup[MAX_LOOKUPS];
67 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
70 /**
71 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
72 * ie there is no GL Context - Get a default rendering context to enable the
73 * function query some info from GL
76 static int wined3d_fake_gl_context_ref = 0;
77 static BOOL wined3d_fake_gl_context_foreign;
78 static BOOL wined3d_fake_gl_context_available = FALSE;
79 static Display* wined3d_fake_gl_context_display = NULL;
81 static void WineD3D_ReleaseFakeGLContext(void) {
82 GLXContext glCtx;
84 if(!wined3d_fake_gl_context_available) {
85 TRACE_(d3d_caps)("context not available\n");
86 return;
89 glCtx = glXGetCurrentContext();
91 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
92 if (0 == (--wined3d_fake_gl_context_ref) ) {
93 if(!wined3d_fake_gl_context_foreign && glCtx) {
94 TRACE_(d3d_caps)("destroying fake GL context\n");
95 glXMakeCurrent(wined3d_fake_gl_context_display, None, NULL);
96 glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
98 LEAVE_GL();
99 wined3d_fake_gl_context_available = FALSE;
101 assert(wined3d_fake_gl_context_ref >= 0);
105 static BOOL WineD3D_CreateFakeGLContext(void) {
106 XVisualInfo* visInfo;
107 GLXContext glCtx;
109 TRACE_(d3d_caps)("getting context...\n");
110 if(wined3d_fake_gl_context_ref > 0) goto ret;
111 assert(0 == wined3d_fake_gl_context_ref);
113 wined3d_fake_gl_context_foreign = TRUE;
115 if(!wined3d_fake_gl_context_display) {
116 HDC device_context = GetDC(0);
118 wined3d_fake_gl_context_display = get_display(device_context);
119 ReleaseDC(0, device_context);
122 ENTER_GL();
124 visInfo = NULL;
125 glCtx = glXGetCurrentContext();
127 if (!glCtx) {
128 Drawable drawable;
129 XVisualInfo template;
130 Visual* visual;
131 int num;
132 XWindowAttributes win_attr;
134 wined3d_fake_gl_context_foreign = FALSE;
135 drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
137 TRACE_(d3d_caps)("Creating Fake GL Context\n");
139 /* Get the X visual */
140 if (XGetWindowAttributes(wined3d_fake_gl_context_display, drawable, &win_attr)) {
141 visual = win_attr.visual;
142 } else {
143 visual = DefaultVisual(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display));
145 template.visualid = XVisualIDFromVisual(visual);
146 visInfo = XGetVisualInfo(wined3d_fake_gl_context_display, VisualIDMask, &template, &num);
147 if (!visInfo) {
148 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
149 goto fail;
152 /* Create a GL context */
153 glCtx = glXCreateContext(wined3d_fake_gl_context_display, visInfo, NULL, GL_TRUE);
154 if (!glCtx) {
155 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
156 goto fail;
159 /* Make it the current GL context */
160 if (!glXMakeCurrent(wined3d_fake_gl_context_display, drawable, glCtx)) {
161 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
162 goto fail;
165 XFree(visInfo);
169 ret:
170 TRACE_(d3d_caps)("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
171 wined3d_fake_gl_context_ref++;
172 wined3d_fake_gl_context_available = TRUE;
173 return TRUE;
174 fail:
175 if(visInfo) XFree(visInfo);
176 if(glCtx) glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
177 LEAVE_GL();
178 return FALSE;
181 /**********************************************************
182 * IUnknown parts follows
183 **********************************************************/
185 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
187 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
189 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
190 if (IsEqualGUID(riid, &IID_IUnknown)
191 || IsEqualGUID(riid, &IID_IWineD3DBase)
192 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
193 IUnknown_AddRef(iface);
194 *ppobj = This;
195 return S_OK;
197 *ppobj = NULL;
198 return E_NOINTERFACE;
201 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
202 IWineD3DImpl *This = (IWineD3DImpl *)iface;
203 ULONG refCount = InterlockedIncrement(&This->ref);
205 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
206 return refCount;
209 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
210 IWineD3DImpl *This = (IWineD3DImpl *)iface;
211 ULONG ref;
212 TRACE("(%p) : Releasing from %d\n", This, This->ref);
213 ref = InterlockedDecrement(&This->ref);
214 if (ref == 0) {
215 HeapFree(GetProcessHeap(), 0, This);
218 return ref;
221 /* Set the shader type for this device, depending on the given capabilities,
222 * the device type, and the user preferences in wined3d_settings */
224 static void select_shader_mode(
225 WineD3D_GL_Info *gl_info,
226 WINED3DDEVTYPE DeviceType,
227 int* ps_selected,
228 int* vs_selected) {
230 /* Give priority to user disable/emulation request.
231 * Then respect REF device for software.
232 * Then check capabilities for hardware, and fallback to software */
234 if (wined3d_settings.vs_mode == VS_NONE) {
235 *vs_selected = SHADER_NONE;
236 } else if (DeviceType == WINED3DDEVTYPE_REF || wined3d_settings.vs_mode == VS_SW) {
237 *vs_selected = SHADER_SW;
238 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
239 *vs_selected = SHADER_GLSL;
240 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
241 *vs_selected = SHADER_ARB;
242 } else {
243 *vs_selected = SHADER_SW;
246 /* Fallback to SHADER_NONE where software pixel shaders should be used */
247 if (wined3d_settings.ps_mode == PS_NONE) {
248 *ps_selected = SHADER_NONE;
249 } else if (DeviceType == WINED3DDEVTYPE_REF) {
250 *ps_selected = SHADER_NONE;
251 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
252 *ps_selected = SHADER_GLSL;
253 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
254 *ps_selected = SHADER_ARB;
255 } else {
256 *ps_selected = SHADER_NONE;
260 /** Select the number of report maximum shader constants based on the selected shader modes */
261 void select_shader_max_constants(
262 int ps_selected_mode,
263 int vs_selected_mode,
264 WineD3D_GL_Info *gl_info) {
266 switch (vs_selected_mode) {
267 case SHADER_GLSL:
268 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
269 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I - 1;
270 break;
271 case SHADER_ARB:
272 /* We have to subtract any other PARAMs that we might use in our shader programs.
273 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
274 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
275 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
276 break;
277 case SHADER_SW:
278 gl_info->max_vshader_constantsF = 96; /* TODO: Fixup software shaders */
279 break;
280 default:
281 gl_info->max_vshader_constantsF = 0;
282 break;
285 switch (ps_selected_mode) {
286 case SHADER_GLSL:
287 /* Subtract the other potential uniforms from the max available (bools & ints).
288 * In theory the texbem instruction may need one more shader constant too. But lets assume
289 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
290 * and lets not take away a uniform needlessly from all other shaders.
292 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
293 break;
294 case SHADER_ARB:
295 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
296 * a free constant to do that, so no need to reduce the number of available constants.
298 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
299 break;
300 case SHADER_SW:
301 gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */
302 break;
303 default:
304 gl_info->max_pshader_constantsF = 0;
305 break;
309 /**********************************************************
310 * IWineD3D parts follows
311 **********************************************************/
313 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
314 IWineD3DImpl *This = (IWineD3DImpl *)iface;
315 WineD3D_GL_Info *gl_info = &This->gl_info;
317 const char *GL_Extensions = NULL;
318 const char *GLX_Extensions = NULL;
319 const char *gl_string = NULL;
320 const char *gl_string_cursor = NULL;
321 GLint gl_max;
322 GLfloat gl_floatv[2];
323 Bool test = 0;
324 int major, minor;
325 BOOL return_value = TRUE;
326 int i;
328 /* Make sure that we've got a context */
329 /* TODO: CreateFakeGLContext should really take a display as a parameter */
330 /* Only save the values obtained when a display is provided */
331 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
332 return_value = FALSE;
334 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
336 gl_string = (const char *) glGetString(GL_RENDERER);
337 if (NULL == gl_string)
338 gl_string = "None";
339 strcpy(gl_info->gl_renderer, gl_string);
341 /* Fill in the GL info retrievable depending on the display */
342 if (NULL != display) {
343 test = glXQueryVersion(display, &major, &minor);
344 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
345 } else {
346 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
348 gl_string = (const char *) glGetString(GL_VENDOR);
350 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
351 if (gl_string != NULL) {
352 /* Fill in the GL vendor */
353 if (strstr(gl_string, "NVIDIA")) {
354 gl_info->gl_vendor = VENDOR_NVIDIA;
355 } else if (strstr(gl_string, "ATI")) {
356 gl_info->gl_vendor = VENDOR_ATI;
357 } else if (strstr(gl_string, "Intel(R)") ||
358 strstr(gl_info->gl_renderer, "Intel(R)")) {
359 gl_info->gl_vendor = VENDOR_INTEL;
360 } else if (strstr(gl_string, "Mesa")) {
361 gl_info->gl_vendor = VENDOR_MESA;
362 } else {
363 gl_info->gl_vendor = VENDOR_WINE;
365 } else {
366 gl_info->gl_vendor = VENDOR_WINE;
370 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
372 /* Parse the GL_VERSION field into major and minor information */
373 gl_string = (const char *) glGetString(GL_VERSION);
374 if (gl_string != NULL) {
376 switch (gl_info->gl_vendor) {
377 case VENDOR_NVIDIA:
378 gl_string_cursor = strstr(gl_string, "NVIDIA");
379 if (!gl_string_cursor) {
380 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
381 break;
384 gl_string_cursor = strstr(gl_string_cursor, " ");
385 if (!gl_string_cursor) {
386 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
387 break;
390 while (*gl_string_cursor == ' ') {
391 ++gl_string_cursor;
394 if (!*gl_string_cursor) {
395 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
396 break;
399 major = atoi(gl_string_cursor);
400 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
401 ++gl_string_cursor;
404 if (*gl_string_cursor++ != '.') {
405 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
406 break;
409 minor = atoi(gl_string_cursor);
410 minor = major*100+minor;
411 major = 10;
413 break;
415 case VENDOR_ATI:
416 major = minor = 0;
417 gl_string_cursor = strchr(gl_string, '-');
418 if (gl_string_cursor) {
419 int error = 0;
420 gl_string_cursor++;
422 /* Check if version number is of the form x.y.z */
423 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
424 error = 1;
425 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
426 error = 1;
427 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
428 error = 1;
429 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
430 error = 1;
432 /* Mark version number as malformed */
433 if (error)
434 gl_string_cursor = 0;
437 if (!gl_string_cursor)
438 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
439 else {
440 major = *gl_string_cursor - '0';
441 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
443 break;
445 case VENDOR_INTEL:
446 case VENDOR_MESA:
447 gl_string_cursor = strstr(gl_string, "Mesa");
448 gl_string_cursor = strstr(gl_string_cursor, " ");
449 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
450 if (*gl_string_cursor) {
451 char tmp[16];
452 int cursor = 0;
454 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
455 tmp[cursor++] = *gl_string_cursor;
456 ++gl_string_cursor;
458 tmp[cursor] = 0;
459 major = atoi(tmp);
461 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
462 ++gl_string_cursor;
464 cursor = 0;
465 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
466 tmp[cursor++] = *gl_string_cursor;
467 ++gl_string_cursor;
469 tmp[cursor] = 0;
470 minor = atoi(tmp);
472 break;
474 default:
475 major = 0;
476 minor = 9;
478 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
479 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
482 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
485 * Initialize openGL extension related variables
486 * with Default values
488 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
489 gl_info->max_buffers = 1;
490 gl_info->max_textures = 1;
491 gl_info->max_texture_stages = 1;
492 gl_info->max_samplers = 1;
493 gl_info->max_sampler_stages = 1;
494 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
495 gl_info->ps_arb_max_temps = 0;
496 gl_info->ps_arb_max_instructions = 0;
497 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
498 gl_info->vs_arb_max_temps = 0;
499 gl_info->vs_arb_max_instructions = 0;
500 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
501 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
502 gl_info->vs_glsl_constantsF = 0;
503 gl_info->ps_glsl_constantsF = 0;
504 gl_info->vs_arb_constantsF = 0;
505 gl_info->ps_arb_constantsF = 0;
507 /* Now work out what GL support this card really has */
508 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
509 GL_EXT_FUNCS_GEN;
510 GLX_EXT_FUNCS_GEN;
511 #undef USE_GL_FUNC
513 /* Retrieve opengl defaults */
514 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
515 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
516 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
518 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
519 gl_info->max_lights = gl_max;
520 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
522 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
523 gl_info->max_texture_size = gl_max;
524 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
526 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
527 gl_info->max_pointsize = gl_floatv[1];
528 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
530 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
531 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
532 TRACE_(d3d_caps)("GL_Extensions reported:\n");
534 if (NULL == GL_Extensions) {
535 ERR(" GL_Extensions returns NULL\n");
536 } else {
537 while (*GL_Extensions != 0x00) {
538 const char *Start = GL_Extensions;
539 char ThisExtn[256];
541 memset(ThisExtn, 0x00, sizeof(ThisExtn));
542 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
543 GL_Extensions++;
545 memcpy(ThisExtn, Start, (GL_Extensions - Start));
546 TRACE_(d3d_caps)("- %s\n", ThisExtn);
549 * ARB
551 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
552 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
553 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
554 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
555 gl_info->max_buffers = gl_max;
556 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
557 gl_info->ps_arb_version = PS_VERSION_11;
558 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
559 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
560 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
561 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
562 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
563 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
564 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
565 gl_info->ps_arb_constantsF = gl_max;
566 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
567 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
568 gl_info->ps_arb_max_temps = gl_max;
569 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
570 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
571 gl_info->ps_arb_max_instructions = gl_max;
572 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
573 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
574 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
575 gl_max /= 4;
576 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
577 gl_info->ps_glsl_constantsF = gl_max;
578 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
579 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
580 gl_info->supported[ARB_IMAGING] = TRUE;
581 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
582 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
583 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
584 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
585 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
586 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
587 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
588 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
589 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
590 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
591 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
592 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
593 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
594 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
595 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
596 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
597 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
598 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
599 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
600 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
601 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
602 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
603 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
604 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
605 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
606 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
607 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
608 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
609 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
610 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
611 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
612 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
613 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
614 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
615 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
616 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
617 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
618 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
619 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
620 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
621 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
622 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
623 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
624 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
625 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
626 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
627 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
628 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
629 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
630 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
631 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
632 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
633 gl_info->vs_arb_version = VS_VERSION_11;
634 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
635 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
636 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
637 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
638 gl_info->vs_arb_constantsF = gl_max;
639 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
640 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
641 gl_info->vs_arb_max_temps = gl_max;
642 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
643 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
644 gl_info->vs_arb_max_instructions = gl_max;
645 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
646 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
647 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
648 gl_max /= 4;
649 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
650 gl_info->vs_glsl_constantsF = gl_max;
651 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
652 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
653 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
654 gl_info->max_blends = gl_max;
655 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
656 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
657 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
658 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
659 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
660 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
661 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
662 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
663 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
664 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
666 * EXT
668 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
669 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
670 gl_info->supported[EXT_FOG_COORD] = TRUE;
671 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
672 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
673 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
674 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
675 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
676 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
677 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
678 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
679 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
680 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
681 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
682 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
683 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
684 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
685 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
686 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
687 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
688 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
689 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
690 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
691 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
692 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
693 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
694 gl_info->supported[EXT_TEXTURE3D] = TRUE;
695 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
696 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
697 gl_info->max_texture3d_size = gl_max;
698 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
699 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
700 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
701 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
702 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
703 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
704 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
705 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
706 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
707 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
708 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
709 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
710 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
711 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
712 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
713 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
714 gl_info->max_anisotropy = gl_max;
715 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
716 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
717 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
718 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
719 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
720 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
721 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
722 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
723 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
726 * NVIDIA
728 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
729 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
730 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
731 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
732 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
733 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
734 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
735 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
736 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
737 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
738 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
739 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
740 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
741 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
742 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
743 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
744 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
745 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
746 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
747 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
748 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
749 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
750 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
751 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
752 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
753 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
754 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
755 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
756 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
757 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
758 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
759 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
760 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
761 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
762 gl_info->vs_nv_version = VS_VERSION_30;
763 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
764 gl_info->vs_nv_version = VS_VERSION_20;
765 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
766 gl_info->vs_nv_version = VS_VERSION_11;
767 else
768 gl_info->vs_nv_version = VS_VERSION_10;
769 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
770 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
773 * ATI
775 /** TODO */
776 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
777 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
778 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
779 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
780 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
781 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
782 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
783 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
784 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
785 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
786 gl_info->vs_ati_version = VS_VERSION_11;
787 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
788 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
792 if (*GL_Extensions == ' ') GL_Extensions++;
795 checkGLcall("extension detection\n");
797 /* In some cases the number of texture stages can be larger than the number
798 * of samplers. The GF4 for example can use only 2 samplers (no fragment
799 * shaders), but 8 texture stages (register combiners). */
800 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
802 /* We can only use ORM_FBO when the hardware supports it. */
803 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
804 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
805 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
808 /* MRTs are currently only supported when FBOs are used. */
809 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
810 gl_info->max_buffers = 1;
813 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
814 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
815 * in case of the latest videocards in the number of pixel/vertex pipelines.
817 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
818 * rendering. Various games use this information to get a rough estimation of the features of the card
819 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
820 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
821 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
822 * not the PCI id.
824 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
825 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
826 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
827 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
828 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
829 * is used for rendering which is not always the case). This would work but it is not very portable. Second
830 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
831 * is limited.
833 * As said most games only use the PCI id to get an indication of the capabilities of the card.
834 * It doesn't really matter if the given id is the correct one if we return the id of a card with
835 * similar 3d features.
837 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
838 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
839 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
840 * won't pass we return a default card. This way is better than maintaining a full card database as even
841 * without a full database we can return a card with similar features. Second the size of the database
842 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
843 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
844 * to distinguishes between different models from that family.
846 switch (gl_info->gl_vendor) {
847 case VENDOR_NVIDIA:
848 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
849 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
851 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
852 if (strstr(gl_info->gl_renderer, "7800") ||
853 strstr(gl_info->gl_renderer, "7900") ||
854 strstr(gl_info->gl_renderer, "7950") ||
855 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
856 strstr(gl_info->gl_renderer, "Quadro FX 5"))
857 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
858 else if(strstr(gl_info->gl_renderer, "6800") ||
859 strstr(gl_info->gl_renderer, "7600"))
860 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
861 else if(strstr(gl_info->gl_renderer, "6600") ||
862 strstr(gl_info->gl_renderer, "6610") ||
863 strstr(gl_info->gl_renderer, "6700"))
864 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
865 else
866 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
867 } else if(WINE_D3D9_CAPABLE(gl_info)) {
868 if (strstr(gl_info->gl_renderer, "5800") ||
869 strstr(gl_info->gl_renderer, "5900") ||
870 strstr(gl_info->gl_renderer, "5950") ||
871 strstr(gl_info->gl_renderer, "Quadro FX"))
872 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
873 else if(strstr(gl_info->gl_renderer, "5600") ||
874 strstr(gl_info->gl_renderer, "5650") ||
875 strstr(gl_info->gl_renderer, "5700") ||
876 strstr(gl_info->gl_renderer, "5750"))
877 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
878 else
879 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
880 } else if(WINE_D3D8_CAPABLE(gl_info)) {
881 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
882 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
883 else
884 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
885 } else if(WINE_D3D7_CAPABLE(gl_info)) {
886 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
887 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
888 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
889 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
890 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
891 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
892 else
893 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
894 } else {
895 if (strstr(gl_info->gl_renderer, "TNT2"))
896 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
897 else
898 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
900 break;
901 case VENDOR_ATI:
902 if(WINE_D3D9_CAPABLE(gl_info)) {
903 /* Radeon R5xx */
904 if (strstr(gl_info->gl_renderer, "X1600") ||
905 strstr(gl_info->gl_renderer, "X1800") ||
906 strstr(gl_info->gl_renderer, "X1900") ||
907 strstr(gl_info->gl_renderer, "X1950"))
908 gl_info->gl_card = CARD_ATI_RADEON_X1600;
909 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
910 else if(strstr(gl_info->gl_renderer, "X700") ||
911 strstr(gl_info->gl_renderer, "X800") ||
912 strstr(gl_info->gl_renderer, "X850") ||
913 strstr(gl_info->gl_renderer, "X1300") ||
914 strstr(gl_info->gl_renderer, "X1400"))
915 gl_info->gl_card = CARD_ATI_RADEON_X700;
916 /* Radeon R3xx */
917 else
918 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
919 } else if(WINE_D3D8_CAPABLE(gl_info)) {
920 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
921 } else if(WINE_D3D7_CAPABLE(gl_info)) {
922 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
923 } else
924 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
925 break;
926 case VENDOR_INTEL:
927 if (strstr(gl_info->gl_renderer, "915GM")) {
928 gl_info->gl_card = CARD_INTEL_I915GM;
929 } else if (strstr(gl_info->gl_renderer, "915G")) {
930 gl_info->gl_card = CARD_INTEL_I915G;
931 } else if (strstr(gl_info->gl_renderer, "865G")) {
932 gl_info->gl_card = CARD_INTEL_I865G;
933 } else if (strstr(gl_info->gl_renderer, "855G")) {
934 gl_info->gl_card = CARD_INTEL_I855G;
935 } else if (strstr(gl_info->gl_renderer, "830G")) {
936 gl_info->gl_card = CARD_INTEL_I830G;
937 } else {
938 gl_info->gl_card = CARD_INTEL_I915G;
940 break;
941 case VENDOR_MESA:
942 case VENDOR_WINE:
943 default:
944 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
945 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
946 * them a good generic choice.
948 gl_info->gl_vendor = VENDOR_NVIDIA;
949 if(WINE_D3D9_CAPABLE(gl_info))
950 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
951 else if(WINE_D3D8_CAPABLE(gl_info))
952 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
953 else if(WINE_D3D7_CAPABLE(gl_info))
954 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
955 else if(WINE_D3D6_CAPABLE(gl_info))
956 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
957 else
958 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
960 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
962 /* Load all the lookup tables
963 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
964 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
965 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
967 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
968 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
971 for (i = 0; i < MAX_LOOKUPS; i++) {
972 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
975 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
976 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
977 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
978 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
979 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
980 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
981 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
982 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
983 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
984 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
986 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
987 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
988 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
989 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
990 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
993 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
994 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
995 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
996 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
997 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
998 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
999 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1000 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1001 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1002 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1003 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1004 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1005 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1007 /* TODO: config lookups */
1009 if (display != NULL) {
1010 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1011 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1013 if (NULL == GLX_Extensions) {
1014 ERR(" GLX_Extensions returns NULL\n");
1015 } else {
1016 while (*GLX_Extensions != 0x00) {
1017 const char *Start = GLX_Extensions;
1018 char ThisExtn[256];
1020 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1021 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1022 GLX_Extensions++;
1024 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1025 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1026 if (*GLX_Extensions == ' ') GLX_Extensions++;
1032 WineD3D_ReleaseFakeGLContext();
1033 return return_value;
1036 /**********************************************************
1037 * IWineD3D implementation follows
1038 **********************************************************/
1040 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1041 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1043 /* FIXME: Set to one for now to imply the display */
1044 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1045 return 1;
1048 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1049 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1050 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1051 return WINED3D_OK;
1054 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1055 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1056 POINT pt = { -1, -1 };
1058 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1059 return NULL;
1062 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1063 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1066 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1067 of the same bpp but different resolutions */
1069 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1070 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1071 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1072 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1074 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1075 return 0;
1078 if (Adapter == 0) { /* Display */
1079 int i = 0;
1080 int j = 0;
1081 #if !defined( DEBUG_SINGLE_MODE )
1082 DEVMODEW DevModeW;
1084 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1085 j++;
1086 switch (Format)
1088 case WINED3DFMT_UNKNOWN:
1089 if (DevModeW.dmBitsPerPel == 32 ||
1090 DevModeW.dmBitsPerPel == 16) i++;
1091 break;
1092 case WINED3DFMT_X8R8G8B8:
1093 if (DevModeW.dmBitsPerPel == 32) i++;
1094 break;
1095 case WINED3DFMT_R5G6B5:
1096 if (DevModeW.dmBitsPerPel == 16) i++;
1097 break;
1098 default:
1099 /* Skip other modes as they do not match the requested format */
1100 break;
1103 #else
1104 i = 1;
1105 j = 1;
1106 #endif
1107 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1108 return i;
1109 } else {
1110 FIXME_(d3d_caps)("Adapter not primary display\n");
1112 return 0;
1115 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1116 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1117 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1118 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1120 /* Validate the parameters as much as possible */
1121 if (NULL == pMode ||
1122 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1123 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1124 return WINED3DERR_INVALIDCALL;
1127 if (Adapter == 0) { /* Display */
1128 #if !defined( DEBUG_SINGLE_MODE )
1129 DEVMODEW DevModeW;
1130 int ModeIdx = 0;
1131 int i = 0;
1132 int j = 0;
1134 /* If we are filtering to a specific format (D3D9), then need to skip
1135 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1136 just count through the ones with valid bit depths */
1137 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1138 switch (Format)
1140 case WINED3DFMT_UNKNOWN:
1141 if (DevModeW.dmBitsPerPel == 32 ||
1142 DevModeW.dmBitsPerPel == 16) i++;
1143 break;
1144 case WINED3DFMT_X8R8G8B8:
1145 if (DevModeW.dmBitsPerPel == 32) i++;
1146 break;
1147 case WINED3DFMT_R5G6B5:
1148 if (DevModeW.dmBitsPerPel == 16) i++;
1149 break;
1150 default:
1151 /* Modes that don't match what we support can get an early-out */
1152 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1153 return WINED3DERR_INVALIDCALL;
1157 if (i == 0) {
1158 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1159 return WINED3DERR_INVALIDCALL;
1161 ModeIdx = j - 1;
1163 /* Now get the display mode via the calculated index */
1164 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1165 pMode->Width = DevModeW.dmPelsWidth;
1166 pMode->Height = DevModeW.dmPelsHeight;
1167 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1168 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1169 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1171 if (Format == WINED3DFMT_UNKNOWN)
1173 switch (DevModeW.dmBitsPerPel)
1175 case 16:
1176 pMode->Format = WINED3DFMT_R5G6B5;
1177 break;
1178 case 32:
1179 pMode->Format = WINED3DFMT_X8R8G8B8;
1180 break;
1181 default:
1182 pMode->Format = WINED3DFMT_UNKNOWN;
1183 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1185 } else {
1186 pMode->Format = Format;
1188 } else {
1189 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1190 return WINED3DERR_INVALIDCALL;
1193 #else
1194 /* Return one setting of the format requested */
1195 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1196 pMode->Width = 800;
1197 pMode->Height = 600;
1198 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1199 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1200 #endif
1201 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1202 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1203 DevModeW.dmBitsPerPel);
1205 } else {
1206 FIXME_(d3d_caps)("Adapter not primary display\n");
1209 return WINED3D_OK;
1212 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1213 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1214 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1216 if (NULL == pMode ||
1217 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1218 return WINED3DERR_INVALIDCALL;
1221 if (Adapter == 0) { /* Display */
1222 int bpp = 0;
1223 DEVMODEW DevModeW;
1225 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1226 pMode->Width = DevModeW.dmPelsWidth;
1227 pMode->Height = DevModeW.dmPelsHeight;
1228 bpp = DevModeW.dmBitsPerPel;
1229 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1230 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1232 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1235 switch (bpp) {
1236 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1237 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1238 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1239 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1240 default: pMode->Format = WINED3DFMT_UNKNOWN;
1243 } else {
1244 FIXME_(d3d_caps)("Adapter not primary display\n");
1247 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1248 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1249 return WINED3D_OK;
1252 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1253 Display *display;
1254 HDC device_context;
1255 /* only works with one adapter at the moment... */
1257 /* Get the display */
1258 device_context = GetDC(0);
1259 display = get_display(device_context);
1260 ReleaseDC(0, device_context);
1261 return display;
1264 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1265 and fields being inserted in the middle, a new structure is used in place */
1266 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1267 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1268 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1270 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1272 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1273 return WINED3DERR_INVALIDCALL;
1276 if (Adapter == 0) { /* Display - only device supported for now */
1278 BOOL isGLInfoValid = This->isGLInfoValid;
1280 /* FillGLCaps updates gl_info, but we only want to store and
1281 reuse the values once we have a context which is valid. Values from
1282 a temporary context may differ from the final ones */
1283 if (!isGLInfoValid) {
1284 /* If we don't know the device settings, go query them now */
1285 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1288 /* If it worked, return the information requested */
1289 if (isGLInfoValid) {
1290 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1291 strcpy(pIdentifier->Driver, "Display");
1292 strcpy(pIdentifier->Description, "Direct3D HAL");
1294 /* Note dx8 doesn't supply a DeviceName */
1295 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1296 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1297 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1298 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1299 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1300 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1301 *(pIdentifier->SubSysId) = 0;
1302 *(pIdentifier->Revision) = 0;
1304 } else {
1306 /* If it failed, return dummy values from an NVidia driver */
1307 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1308 strcpy(pIdentifier->Driver, "Display");
1309 strcpy(pIdentifier->Description, "Direct3D HAL");
1310 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1311 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1312 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1313 /* 71.74 is a current Linux Nvidia driver version */
1314 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1315 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1316 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1317 *(pIdentifier->SubSysId) = 0;
1318 *(pIdentifier->Revision) = 0;
1321 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1322 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1323 *(pIdentifier->WHQLLevel) = 0;
1324 } else {
1325 *(pIdentifier->WHQLLevel) = 1;
1328 } else {
1329 FIXME_(d3d_caps)("Adapter not primary display\n");
1332 return WINED3D_OK;
1335 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1336 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1337 int gl_test;
1338 int rb, gb, bb, ab, type, buf_sz;
1340 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1341 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1342 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1343 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1344 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1345 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1347 switch (Format) {
1348 case WINED3DFMT_X8R8G8B8:
1349 case WINED3DFMT_R8G8B8:
1350 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1351 break;
1352 case WINED3DFMT_A8R8G8B8:
1353 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1354 break;
1355 case WINED3DFMT_A2R10G10B10:
1356 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1357 break;
1358 case WINED3DFMT_X1R5G5B5:
1359 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1360 break;
1361 case WINED3DFMT_A1R5G5B5:
1362 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1363 break;
1364 case WINED3DFMT_X4R4G4B4:
1365 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1366 break;
1367 case WINED3DFMT_R5G6B5:
1368 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1369 break;
1370 case WINED3DFMT_R3G3B2:
1371 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1372 break;
1373 case WINED3DFMT_A8P8:
1374 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1375 break;
1376 case WINED3DFMT_P8:
1377 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1378 break;
1379 default:
1380 break;
1382 return FALSE;
1383 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1384 switch (Format) {
1385 case WINED3DFMT_X8R8G8B8:
1386 case WINED3DFMT_R8G8B8:
1387 case WINED3DFMT_A8R8G8B8:
1388 case WINED3DFMT_A2R10G10B10:
1389 case WINED3DFMT_X1R5G5B5:
1390 case WINED3DFMT_A1R5G5B5:
1391 case WINED3DFMT_R5G6B5:
1392 case WINED3DFMT_R3G3B2:
1393 case WINED3DFMT_A8P8:
1394 case WINED3DFMT_P8:
1395 return TRUE;
1396 default:
1397 break;
1399 return FALSE;
1400 #endif
1403 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1404 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1405 int gl_test;
1406 int db, sb;
1408 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1409 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1411 switch (Format) {
1412 case WINED3DFMT_D16:
1413 case WINED3DFMT_D16_LOCKABLE:
1414 if (16 == db) return TRUE;
1415 break;
1416 case WINED3DFMT_D32:
1417 if (32 == db) return TRUE;
1418 break;
1419 case WINED3DFMT_D15S1:
1420 if (15 == db) return TRUE;
1421 break;
1422 case WINED3DFMT_D24S8:
1423 if (24 == db && 8 == sb) return TRUE;
1424 break;
1425 case WINED3DFMT_D24FS8:
1426 if (24 == db && 8 == sb) return TRUE;
1427 break;
1428 case WINED3DFMT_D24X8:
1429 if (24 == db) return TRUE;
1430 break;
1431 case WINED3DFMT_D24X4S4:
1432 if (24 == db && 4 == sb) return TRUE;
1433 break;
1434 case WINED3DFMT_D32F_LOCKABLE:
1435 if (32 == db) return TRUE;
1436 break;
1437 default:
1438 break;
1440 return FALSE;
1441 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1442 switch (Format) {
1443 case WINED3DFMT_D16:
1444 case WINED3DFMT_D16_LOCKABLE:
1445 case WINED3DFMT_D32:
1446 case WINED3DFMT_D15S1:
1447 case WINED3DFMT_D24S8:
1448 case WINED3DFMT_D24FS8:
1449 case WINED3DFMT_D24X8:
1450 case WINED3DFMT_D24X4S4:
1451 case WINED3DFMT_D32F_LOCKABLE:
1452 return TRUE;
1453 default:
1454 break;
1456 return FALSE;
1457 #endif
1460 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1461 WINED3DFORMAT AdapterFormat,
1462 WINED3DFORMAT RenderTargetFormat,
1463 WINED3DFORMAT DepthStencilFormat) {
1464 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1465 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1466 GLXFBConfig* cfgs = NULL;
1467 int nCfgs = 0;
1468 int it;
1470 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1471 This, Adapter,
1472 DeviceType, debug_d3ddevicetype(DeviceType),
1473 AdapterFormat, debug_d3dformat(AdapterFormat),
1474 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1475 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1477 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1478 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1479 return WINED3DERR_INVALIDCALL;
1482 if(WineD3D_CreateFakeGLContext())
1483 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1485 if (cfgs) {
1486 for (it = 0; it < nCfgs; ++it) {
1487 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1488 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1489 hr = WINED3D_OK;
1490 break ;
1494 XFree(cfgs);
1495 if(hr != WINED3D_OK)
1496 ERR("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1497 } else {
1498 ERR_(d3d_caps)("returning WINED3D_OK even so CreateFakeGLContext or glXGetFBConfigs failed\n");
1499 hr = WINED3D_OK;
1502 WineD3D_ReleaseFakeGLContext();
1504 if (hr != WINED3D_OK)
1505 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1507 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1508 return hr;
1511 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1512 WINED3DFORMAT SurfaceFormat,
1513 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1515 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1516 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1517 This,
1518 Adapter,
1519 DeviceType, debug_d3ddevicetype(DeviceType),
1520 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1521 Windowed,
1522 MultiSampleType,
1523 pQualityLevels);
1525 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1526 return WINED3DERR_INVALIDCALL;
1529 if (pQualityLevels != NULL) {
1530 static int s_single_shot = 0;
1531 if (!s_single_shot) {
1532 FIXME("Quality levels unsupported at present\n");
1533 s_single_shot = 1;
1535 *pQualityLevels = 1; /* Guess at a value! */
1538 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1539 return WINED3DERR_NOTAVAILABLE;
1542 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1543 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1545 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1546 GLXFBConfig* cfgs = NULL;
1547 int nCfgs = 0;
1548 int it;
1549 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1551 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1552 This,
1553 Adapter,
1554 CheckType, debug_d3ddevicetype(CheckType),
1555 DisplayFormat, debug_d3dformat(DisplayFormat),
1556 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1557 Windowed);
1559 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1560 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1561 return WINED3DERR_INVALIDCALL;
1564 if (WineD3D_CreateFakeGLContext()) {
1565 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1566 for (it = 0; it < nCfgs; ++it) {
1567 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1568 hr = WINED3D_OK;
1569 TRACE_(d3d_caps)("OK\n");
1570 break ;
1573 if(cfgs) XFree(cfgs);
1574 if(hr != WINED3D_OK)
1575 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1576 WineD3D_ReleaseFakeGLContext();
1579 if(hr != WINED3D_OK)
1580 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1582 return hr;
1585 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1586 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1587 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1588 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1589 This,
1590 Adapter,
1591 DeviceType, debug_d3ddevicetype(DeviceType),
1592 AdapterFormat, debug_d3dformat(AdapterFormat),
1593 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1594 RType, debug_d3dresourcetype(RType),
1595 CheckFormat, debug_d3dformat(CheckFormat));
1597 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1598 return WINED3DERR_INVALIDCALL;
1601 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1602 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1603 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1604 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1605 TRACE_(d3d_caps)("[FAILED]\n");
1606 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1609 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1610 switch (CheckFormat) {
1611 case WINED3DFMT_D16_LOCKABLE:
1612 case WINED3DFMT_D32:
1613 case WINED3DFMT_D15S1:
1614 case WINED3DFMT_D24S8:
1615 case WINED3DFMT_D24X8:
1616 case WINED3DFMT_D24X4S4:
1617 case WINED3DFMT_D16:
1618 case WINED3DFMT_L16:
1619 case WINED3DFMT_D32F_LOCKABLE:
1620 case WINED3DFMT_D24FS8:
1621 TRACE_(d3d_caps)("[OK]\n");
1622 return WINED3D_OK;
1623 default:
1624 TRACE_(d3d_caps)("[FAILED]\n");
1625 return WINED3DERR_NOTAVAILABLE;
1627 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1628 switch (CheckFormat) {
1629 case WINED3DFMT_R8G8B8:
1630 case WINED3DFMT_A8R8G8B8:
1631 case WINED3DFMT_X8R8G8B8:
1632 case WINED3DFMT_R5G6B5:
1633 case WINED3DFMT_X1R5G5B5:
1634 case WINED3DFMT_A1R5G5B5:
1635 case WINED3DFMT_A4R4G4B4:
1636 case WINED3DFMT_R3G3B2:
1637 case WINED3DFMT_X4R4G4B4:
1638 case WINED3DFMT_A8B8G8R8:
1639 case WINED3DFMT_X8B8G8R8:
1640 case WINED3DFMT_P8:
1641 TRACE_(d3d_caps)("[OK]\n");
1642 return WINED3D_OK;
1643 default:
1644 TRACE_(d3d_caps)("[FAILED]\n");
1645 return WINED3DERR_NOTAVAILABLE;
1649 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1650 switch (CheckFormat) {
1651 case WINED3DFMT_DXT1:
1652 case WINED3DFMT_DXT2:
1653 case WINED3DFMT_DXT3:
1654 case WINED3DFMT_DXT4:
1655 case WINED3DFMT_DXT5:
1656 TRACE_(d3d_caps)("[OK]\n");
1657 return WINED3D_OK;
1658 default:
1659 break; /* Avoid compiler warnings */
1663 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1665 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1667 switch (CheckFormat) {
1668 case WINED3DFMT_R16F:
1669 case WINED3DFMT_A16B16G16R16F:
1670 if (!half_pixel_support) break;
1671 case WINED3DFMT_R32F:
1672 case WINED3DFMT_A32B32G32R32F:
1673 TRACE_(d3d_caps)("[OK]\n");
1674 return WINED3D_OK;
1675 default:
1676 break; /* Avoid compiler warnings */
1680 /* This format is nothing special and it is supported perfectly.
1681 * However, ati and nvidia driver on windows do not mark this format as
1682 * supported (tested with the dxCapsViewer) and pretending to
1683 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1684 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1685 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1687 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1688 TRACE_(d3d_caps)("[FAILED]\n");
1689 return WINED3DERR_NOTAVAILABLE;
1692 switch (CheckFormat) {
1694 /*****
1695 * supported: RGB(A) formats
1697 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1698 case WINED3DFMT_A8R8G8B8:
1699 case WINED3DFMT_X8R8G8B8:
1700 case WINED3DFMT_R5G6B5:
1701 case WINED3DFMT_X1R5G5B5:
1702 case WINED3DFMT_A1R5G5B5:
1703 case WINED3DFMT_A4R4G4B4:
1704 case WINED3DFMT_R3G3B2:
1705 case WINED3DFMT_A8:
1706 case WINED3DFMT_A8R3G3B2:
1707 case WINED3DFMT_X4R4G4B4:
1708 case WINED3DFMT_A8B8G8R8:
1709 case WINED3DFMT_X8B8G8R8:
1710 case WINED3DFMT_A2R10G10B10:
1711 case WINED3DFMT_A2B10G10R10:
1712 TRACE_(d3d_caps)("[OK]\n");
1713 return WINED3D_OK;
1715 /*****
1716 * supported: Palettized
1718 case WINED3DFMT_P8:
1719 TRACE_(d3d_caps)("[OK]\n");
1720 return WINED3D_OK;
1722 /*****
1723 * Supported: (Alpha)-Luminance
1725 case WINED3DFMT_L8:
1726 case WINED3DFMT_A8L8:
1727 case WINED3DFMT_A4L4:
1728 TRACE_(d3d_caps)("[OK]\n");
1729 return WINED3D_OK;
1731 /*****
1732 * Not supported for now: Bump mapping formats
1733 * Enable some because games often fail when they are not available
1734 * and are still playable even without bump mapping
1736 case WINED3DFMT_V8U8:
1737 case WINED3DFMT_V16U16:
1738 case WINED3DFMT_L6V5U5:
1739 case WINED3DFMT_X8L8V8U8:
1740 case WINED3DFMT_Q8W8V8U8:
1741 case WINED3DFMT_W11V11U10:
1742 case WINED3DFMT_A2W10V10U10:
1743 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1744 return WINED3D_OK;
1746 /*****
1747 * DXTN Formats: Handled above
1748 * WINED3DFMT_DXT1
1749 * WINED3DFMT_DXT2
1750 * WINED3DFMT_DXT3
1751 * WINED3DFMT_DXT4
1752 * WINED3DFMT_DXT5
1755 /*****
1756 * Odd formats - not supported
1758 case WINED3DFMT_VERTEXDATA:
1759 case WINED3DFMT_INDEX16:
1760 case WINED3DFMT_INDEX32:
1761 case WINED3DFMT_Q16W16V16U16:
1762 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1763 return WINED3DERR_NOTAVAILABLE;
1765 /*****
1766 * Float formats: Not supported right now
1768 case WINED3DFMT_G16R16F:
1769 case WINED3DFMT_G32R32F:
1770 case WINED3DFMT_CxV8U8:
1771 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1772 return WINED3DERR_NOTAVAILABLE;
1774 /* Not supported */
1775 case WINED3DFMT_G16R16:
1776 case WINED3DFMT_A16B16G16R16:
1777 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1778 return WINED3DERR_NOTAVAILABLE;
1780 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1781 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1782 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1783 * We can do instancing with all shader versions, but we need vertex shaders.
1785 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1786 * to enable instancing. WineD3D doesn't need that and just ignores it.
1788 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1790 case MAKEFOURCC('I','N','S','T'):
1791 TRACE("ATI Instancing check hack\n");
1792 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1793 TRACE_(d3d_caps)("[OK]\n");
1794 return WINED3D_OK;
1795 } else {
1796 TRACE_(d3d_caps)("[FAILED]\n");
1797 return WINED3DERR_NOTAVAILABLE;
1800 default:
1801 break;
1804 TRACE_(d3d_caps)("[FAILED]\n");
1805 return WINED3DERR_NOTAVAILABLE;
1808 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1809 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1810 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1812 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1813 This,
1814 Adapter,
1815 DeviceType, debug_d3ddevicetype(DeviceType),
1816 SourceFormat, debug_d3dformat(SourceFormat),
1817 TargetFormat, debug_d3dformat(TargetFormat));
1818 return WINED3D_OK;
1821 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1822 subset of a D3DCAPS9 structure. However, it has to come via a void *
1823 as the d3d8 interface cannot import the d3d9 header */
1824 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1826 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1827 int vs_selected_mode;
1828 int ps_selected_mode;
1830 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1832 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1833 return WINED3DERR_INVALIDCALL;
1836 /* FIXME: GL info should be per adapter */
1838 /* If we don't know the device settings, go query them now */
1839 if (!This->isGLInfoValid) {
1840 /* use the desktop window to fill gl caps */
1841 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1843 /* We are running off a real context, save the values */
1844 if (rc) This->isGLInfoValid = TRUE;
1846 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1848 /* This function should *not* be modifying GL caps
1849 * TODO: move the functionality where it belongs */
1850 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1852 /* ------------------------------------------------
1853 The following fields apply to both d3d8 and d3d9
1854 ------------------------------------------------ */
1855 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1856 *pCaps->AdapterOrdinal = Adapter;
1858 *pCaps->Caps = 0;
1859 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1860 WINED3DCAPS2_FULLSCREENGAMMA;
1861 *pCaps->Caps3 = 0;
1862 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1864 *pCaps->CursorCaps = 0;
1867 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1868 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1869 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1870 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1871 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1872 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1873 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1874 WINED3DDEVCAPS_PUREDEVICE |
1875 WINED3DDEVCAPS_HWRASTERIZATION |
1876 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1877 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1878 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1879 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1880 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1882 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1883 D3DPMISCCAPS_CULLCCW |
1884 D3DPMISCCAPS_CULLCW |
1885 D3DPMISCCAPS_COLORWRITEENABLE |
1886 D3DPMISCCAPS_CLIPTLVERTS |
1887 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1888 D3DPMISCCAPS_MASKZ |
1889 D3DPMISCCAPS_BLENDOP;
1890 /* TODO:
1891 D3DPMISCCAPS_NULLREFERENCE
1892 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1893 D3DPMISCCAPS_FOGANDSPECULARALPHA
1894 D3DPMISCCAPS_SEPARATEALPHABLEND
1895 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1896 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1897 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1899 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1900 #if 0
1901 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1902 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1903 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1904 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1905 #endif
1907 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1908 WINED3DPRASTERCAPS_PAT |
1909 WINED3DPRASTERCAPS_WFOG |
1910 WINED3DPRASTERCAPS_ZFOG |
1911 WINED3DPRASTERCAPS_FOGVERTEX |
1912 WINED3DPRASTERCAPS_FOGTABLE |
1913 WINED3DPRASTERCAPS_FOGRANGE |
1914 WINED3DPRASTERCAPS_STIPPLE |
1915 WINED3DPRASTERCAPS_SUBPIXEL |
1916 WINED3DPRASTERCAPS_ZTEST |
1917 WINED3DPRASTERCAPS_SCISSORTEST |
1918 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1919 WINED3DPRASTERCAPS_DEPTHBIAS;
1921 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1922 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1923 WINED3DPRASTERCAPS_ZBIAS |
1924 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1926 /* FIXME Add:
1927 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1928 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1929 WINED3DPRASTERCAPS_ANTIALIASEDGES
1930 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1931 WINED3DPRASTERCAPS_WBUFFER */
1933 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1934 D3DPCMPCAPS_EQUAL |
1935 D3DPCMPCAPS_GREATER |
1936 D3DPCMPCAPS_GREATEREQUAL |
1937 D3DPCMPCAPS_LESS |
1938 D3DPCMPCAPS_LESSEQUAL |
1939 D3DPCMPCAPS_NEVER |
1940 D3DPCMPCAPS_NOTEQUAL;
1942 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1943 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1944 D3DPBLENDCAPS_BOTHSRCALPHA |
1945 D3DPBLENDCAPS_DESTALPHA |
1946 D3DPBLENDCAPS_DESTCOLOR |
1947 D3DPBLENDCAPS_INVDESTALPHA |
1948 D3DPBLENDCAPS_INVDESTCOLOR |
1949 D3DPBLENDCAPS_INVSRCALPHA |
1950 D3DPBLENDCAPS_INVSRCCOLOR |
1951 D3DPBLENDCAPS_ONE |
1952 D3DPBLENDCAPS_SRCALPHA |
1953 D3DPBLENDCAPS_SRCALPHASAT |
1954 D3DPBLENDCAPS_SRCCOLOR |
1955 D3DPBLENDCAPS_ZERO;
1957 *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1958 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1959 D3DPBLENDCAPS_BOTHSRCALPHA |
1960 D3DPBLENDCAPS_DESTALPHA |
1961 D3DPBLENDCAPS_DESTCOLOR |
1962 D3DPBLENDCAPS_INVDESTALPHA |
1963 D3DPBLENDCAPS_INVDESTCOLOR |
1964 D3DPBLENDCAPS_INVSRCALPHA |
1965 D3DPBLENDCAPS_INVSRCCOLOR |
1966 D3DPBLENDCAPS_ONE |
1967 D3DPBLENDCAPS_SRCALPHA |
1968 D3DPBLENDCAPS_SRCALPHASAT |
1969 D3DPBLENDCAPS_SRCCOLOR |
1970 D3DPBLENDCAPS_ZERO;
1972 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1973 D3DPCMPCAPS_EQUAL |
1974 D3DPCMPCAPS_GREATER |
1975 D3DPCMPCAPS_GREATEREQUAL |
1976 D3DPCMPCAPS_LESS |
1977 D3DPCMPCAPS_LESSEQUAL |
1978 D3DPCMPCAPS_NEVER |
1979 D3DPCMPCAPS_NOTEQUAL;
1981 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1982 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1983 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1984 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1985 WINED3DPSHADECAPS_COLORFLATRGB |
1986 WINED3DPSHADECAPS_FOGFLAT |
1987 WINED3DPSHADECAPS_FOGGOURAUD |
1988 WINED3DPSHADECAPS_SPECULARFLATRGB;
1990 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1991 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1992 WINED3DPTEXTURECAPS_BORDER |
1993 WINED3DPTEXTURECAPS_MIPMAP |
1994 WINED3DPTEXTURECAPS_PROJECTED |
1995 WINED3DPTEXTURECAPS_PERSPECTIVE |
1996 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1998 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1999 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2000 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2001 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2004 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2005 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2006 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2007 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2011 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2012 WINED3DPTFILTERCAPS_MAGFPOINT |
2013 WINED3DPTFILTERCAPS_MINFLINEAR |
2014 WINED3DPTFILTERCAPS_MINFPOINT |
2015 WINED3DPTFILTERCAPS_MIPFLINEAR |
2016 WINED3DPTFILTERCAPS_MIPFPOINT |
2017 WINED3DPTFILTERCAPS_LINEAR |
2018 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2019 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2020 WINED3DPTFILTERCAPS_MIPLINEAR |
2021 WINED3DPTFILTERCAPS_MIPNEAREST |
2022 WINED3DPTFILTERCAPS_NEAREST;
2024 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2025 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2026 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2029 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2030 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2031 WINED3DPTFILTERCAPS_MAGFPOINT |
2032 WINED3DPTFILTERCAPS_MINFLINEAR |
2033 WINED3DPTFILTERCAPS_MINFPOINT |
2034 WINED3DPTFILTERCAPS_MIPFLINEAR |
2035 WINED3DPTFILTERCAPS_MIPFPOINT |
2036 WINED3DPTFILTERCAPS_LINEAR |
2037 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2038 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2039 WINED3DPTFILTERCAPS_MIPLINEAR |
2040 WINED3DPTFILTERCAPS_MIPNEAREST |
2041 WINED3DPTFILTERCAPS_NEAREST;
2043 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2044 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2045 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2047 } else
2048 *pCaps->CubeTextureFilterCaps = 0;
2050 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2051 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2052 WINED3DPTFILTERCAPS_MAGFPOINT |
2053 WINED3DPTFILTERCAPS_MINFLINEAR |
2054 WINED3DPTFILTERCAPS_MINFPOINT |
2055 WINED3DPTFILTERCAPS_MIPFLINEAR |
2056 WINED3DPTFILTERCAPS_MIPFPOINT |
2057 WINED3DPTFILTERCAPS_LINEAR |
2058 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2059 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2060 WINED3DPTFILTERCAPS_MIPLINEAR |
2061 WINED3DPTFILTERCAPS_MIPNEAREST |
2062 WINED3DPTFILTERCAPS_NEAREST;
2063 } else
2064 *pCaps->VolumeTextureFilterCaps = 0;
2066 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2067 D3DPTADDRESSCAPS_CLAMP |
2068 D3DPTADDRESSCAPS_WRAP;
2070 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2071 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2073 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2074 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2076 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2077 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2080 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2081 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2082 D3DPTADDRESSCAPS_CLAMP |
2083 D3DPTADDRESSCAPS_WRAP;
2084 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2085 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2087 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2088 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2090 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2091 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2093 } else
2094 *pCaps->VolumeTextureAddressCaps = 0;
2096 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2097 D3DLINECAPS_ZTEST;
2098 /* FIXME: Add
2099 D3DLINECAPS_BLEND
2100 D3DLINECAPS_ALPHACMP
2101 D3DLINECAPS_FOG */
2103 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2104 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2106 if(GL_SUPPORT(EXT_TEXTURE3D))
2107 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2108 else
2109 *pCaps->MaxVolumeExtent = 0;
2111 *pCaps->MaxTextureRepeat = 32768;
2112 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2113 *pCaps->MaxVertexW = 1.0;
2115 *pCaps->GuardBandLeft = 0;
2116 *pCaps->GuardBandTop = 0;
2117 *pCaps->GuardBandRight = 0;
2118 *pCaps->GuardBandBottom = 0;
2120 *pCaps->ExtentsAdjust = 0;
2122 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2123 D3DSTENCILCAPS_INCRSAT |
2124 D3DSTENCILCAPS_INVERT |
2125 D3DSTENCILCAPS_KEEP |
2126 D3DSTENCILCAPS_REPLACE |
2127 D3DSTENCILCAPS_ZERO;
2128 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2129 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2130 D3DSTENCILCAPS_INCR;
2132 if ( This->dxVersion > 8 &&
2133 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2134 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2135 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2138 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2140 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2141 D3DTEXOPCAPS_ADDSIGNED |
2142 D3DTEXOPCAPS_ADDSIGNED2X |
2143 D3DTEXOPCAPS_MODULATE |
2144 D3DTEXOPCAPS_MODULATE2X |
2145 D3DTEXOPCAPS_MODULATE4X |
2146 D3DTEXOPCAPS_SELECTARG1 |
2147 D3DTEXOPCAPS_SELECTARG2 |
2148 D3DTEXOPCAPS_DISABLE;
2150 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2151 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2152 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2153 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2154 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2155 D3DTEXOPCAPS_BLENDFACTORALPHA |
2156 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2157 D3DTEXOPCAPS_LERP |
2158 D3DTEXOPCAPS_SUBTRACT;
2160 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2161 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2162 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2163 D3DTEXOPCAPS_MULTIPLYADD |
2164 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2165 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2166 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2168 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2169 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2171 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2172 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2173 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2177 #if 0
2178 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2179 /* FIXME: Add
2180 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2181 D3DTEXOPCAPS_PREMODULATE */
2182 #endif
2184 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2185 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2186 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2187 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2191 #if 0 /* TODO: Blends support in drawprim */
2192 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2193 #else
2194 *pCaps->MaxVertexBlendMatrices = 0;
2195 #endif
2196 *pCaps->MaxVertexBlendMatrixIndex = 1;
2198 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2199 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2202 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2203 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2204 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2205 WINED3DVTXPCAPS_LOCALVIEWER |
2206 WINED3DVTXPCAPS_VERTEXFOG |
2207 WINED3DVTXPCAPS_TEXGEN;
2208 /* FIXME: Add
2209 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2211 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2212 *pCaps->MaxVertexIndex = 0xFFFFF;
2213 *pCaps->MaxStreams = MAX_STREAMS;
2214 *pCaps->MaxStreamStride = 1024;
2216 if (vs_selected_mode == SHADER_GLSL) {
2217 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2218 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2219 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2220 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2221 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2222 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2223 else
2224 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2225 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2226 } else if (vs_selected_mode == SHADER_ARB) {
2227 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2228 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2229 } else if (vs_selected_mode == SHADER_SW) {
2230 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2231 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2232 } else {
2233 *pCaps->VertexShaderVersion = 0;
2234 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2237 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2239 if (ps_selected_mode == SHADER_GLSL) {
2240 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2241 in case of GeforceFX cards. */
2242 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2243 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2244 else
2245 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2246 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2247 *pCaps->PixelShader1xMaxValue = 1.0;
2248 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2249 } else if (ps_selected_mode == SHADER_ARB) {
2250 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2251 *pCaps->PixelShader1xMaxValue = 1.0;
2252 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2253 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2254 } else if (ps_selected_mode = SHADER_SW) {
2255 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2256 *pCaps->PixelShader1xMaxValue = 1.0;
2257 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2258 } else {
2259 *pCaps->PixelShaderVersion = 0;
2260 *pCaps->PixelShader1xMaxValue = 0.0;
2261 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2264 /* ------------------------------------------------
2265 The following fields apply to d3d9 only
2266 ------------------------------------------------ */
2267 if (This->dxVersion > 8) {
2268 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2269 *pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET;
2270 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2271 *pCaps->MaxNpatchTessellationLevel = 0;
2272 *pCaps->MasterAdapterOrdinal = 0;
2273 *pCaps->AdapterOrdinalInGroup = 0;
2274 *pCaps->NumberOfAdaptersInGroup = 1;
2276 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2277 /* OpenGL supports all the formats below, perhaps not always
2278 * without conversion, but it supports them.
2279 * Further GLSL doesn't seem to have an official unsigned type so
2280 * don't advertise it yet as I'm not sure how we handle it.
2281 * We might need to add some clamping in the shader engine to
2282 * support it.
2283 * TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2284 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2285 D3DDTCAPS_UBYTE4N |
2286 D3DDTCAPS_SHORT2N |
2287 D3DDTCAPS_SHORT4N |
2288 D3DDTCAPS_FLOAT16_2 |
2289 D3DDTCAPS_FLOAT16_4;
2291 } else
2292 *pCaps->DeclTypes = 0;
2294 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2297 *pCaps->StretchRectFilterCaps = 0;
2298 *pCaps->VertexTextureFilterCaps = 0;
2300 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2301 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2302 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2303 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2304 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2305 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2306 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2308 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2309 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2310 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2311 *pCaps->VS20Caps.Caps = 0;
2312 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2313 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2314 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2316 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2317 *pCaps->MaxVertexShader30InstructionSlots = 0;
2318 } else { /* VS 1.x */
2319 *pCaps->VS20Caps.Caps = 0;
2320 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2321 *pCaps->VS20Caps.NumTemps = 0;
2322 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2324 *pCaps->MaxVShaderInstructionsExecuted = 0;
2325 *pCaps->MaxVertexShader30InstructionSlots = 0;
2328 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2329 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2330 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2332 /* 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 */
2333 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2334 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2335 D3DPS20CAPS_PREDICATION |
2336 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2337 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2338 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2339 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2340 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2341 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2343 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2344 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2345 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2346 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2347 *pCaps->PS20Caps.Caps = 0;
2348 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2349 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2350 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2351 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2353 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2354 *pCaps->MaxPixelShader30InstructionSlots = 0;
2355 } else { /* PS 1.x */
2356 *pCaps->PS20Caps.Caps = 0;
2357 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2358 *pCaps->PS20Caps.NumTemps = 0;
2359 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2360 *pCaps->PS20Caps.NumInstructionSlots = 0;
2362 *pCaps->MaxPShaderInstructionsExecuted = 0;
2363 *pCaps->MaxPixelShader30InstructionSlots = 0;
2367 return WINED3D_OK;
2371 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2372 and fields being inserted in the middle, a new structure is used in place */
2373 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2374 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2375 IUnknown *parent) {
2377 IWineD3DDeviceImpl *object = NULL;
2378 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2379 HDC hDC;
2380 HRESULT temp_result;
2382 /* Validate the adapter number */
2383 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2384 return WINED3DERR_INVALIDCALL;
2387 /* Create a WineD3DDevice object */
2388 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2389 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2390 TRACE("Created WineD3DDevice object @ %p\n", object);
2391 if (NULL == object) {
2392 return WINED3DERR_OUTOFVIDEOMEMORY;
2395 /* Set up initial COM information */
2396 object->lpVtbl = &IWineD3DDevice_Vtbl;
2397 object->ref = 1;
2398 object->wineD3D = iface;
2399 IWineD3D_AddRef(object->wineD3D);
2400 object->parent = parent;
2402 /* Set the state up as invalid until the device is fully created */
2403 object->state = WINED3DERR_DRIVERINTERNALERROR;
2405 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2406 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2408 /* Save the creation parameters */
2409 object->createParms.AdapterOrdinal = Adapter;
2410 object->createParms.DeviceType = DeviceType;
2411 object->createParms.hFocusWindow = hFocusWindow;
2412 object->createParms.BehaviorFlags = BehaviourFlags;
2414 /* Initialize other useful values */
2415 object->adapterNo = Adapter;
2416 object->devType = DeviceType;
2418 TRACE("(%p) : Creating stateblock\n", This);
2419 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2420 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2421 WINED3DSBT_INIT,
2422 (IWineD3DStateBlock **)&object->stateBlock,
2423 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2424 WARN("Failed to create stateblock\n");
2425 goto create_device_error;
2427 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2428 object->updateStateBlock = object->stateBlock;
2429 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2430 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2432 /* Setup some defaults for creating the implicit swapchain */
2433 ENTER_GL();
2434 /* FIXME: GL info should be per adapter */
2435 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2436 LEAVE_GL();
2437 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2438 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2439 object->shader_backend = &glsl_shader_backend;
2440 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2441 object->shader_backend = &arb_program_shader_backend;
2442 } else {
2443 object->shader_backend = &none_shader_backend;
2446 /* This function should *not* be modifying GL caps
2447 * TODO: move the functionality where it belongs */
2448 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2450 temp_result = allocate_shader_constants(object->updateStateBlock);
2451 if (WINED3D_OK != temp_result)
2452 return temp_result;
2454 object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2456 object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
2458 /* set the state of the device to valid */
2459 object->state = WINED3D_OK;
2461 /* Get the initial screen setup for ddraw */
2462 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2463 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2464 hDC = GetDC(0);
2465 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2466 ReleaseDC(0, hDC);
2468 return WINED3D_OK;
2469 create_device_error:
2471 /* Set the device state to error */
2472 object->state = WINED3DERR_DRIVERINTERNALERROR;
2474 if (object->updateStateBlock != NULL) {
2475 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2476 object->updateStateBlock = NULL;
2478 if (object->stateBlock != NULL) {
2479 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2480 object->stateBlock = NULL;
2482 if (object->render_targets[0] != NULL) {
2483 IWineD3DSurface_Release(object->render_targets[0]);
2484 object->render_targets[0] = NULL;
2486 if (object->stencilBufferTarget != NULL) {
2487 IWineD3DSurface_Release(object->stencilBufferTarget);
2488 object->stencilBufferTarget = NULL;
2490 HeapFree(GetProcessHeap(), 0, object);
2491 *ppReturnedDeviceInterface = NULL;
2492 return WINED3DERR_INVALIDCALL;
2496 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2497 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2498 IUnknown_AddRef(This->parent);
2499 *pParent = This->parent;
2500 return WINED3D_OK;
2503 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2504 IUnknown* surfaceParent;
2505 TRACE("(%p) call back\n", pSurface);
2507 /* Now, release the parent, which will take care of cleaning up the surface for us */
2508 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2509 IUnknown_Release(surfaceParent);
2510 return IUnknown_Release(surfaceParent);
2513 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2514 IUnknown* volumeParent;
2515 TRACE("(%p) call back\n", pVolume);
2517 /* Now, release the parent, which will take care of cleaning up the volume for us */
2518 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2519 IUnknown_Release(volumeParent);
2520 return IUnknown_Release(volumeParent);
2523 /**********************************************************
2524 * IWineD3D VTbl follows
2525 **********************************************************/
2527 const IWineD3DVtbl IWineD3D_Vtbl =
2529 /* IUnknown */
2530 IWineD3DImpl_QueryInterface,
2531 IWineD3DImpl_AddRef,
2532 IWineD3DImpl_Release,
2533 /* IWineD3D */
2534 IWineD3DImpl_GetParent,
2535 IWineD3DImpl_GetAdapterCount,
2536 IWineD3DImpl_RegisterSoftwareDevice,
2537 IWineD3DImpl_GetAdapterMonitor,
2538 IWineD3DImpl_GetAdapterModeCount,
2539 IWineD3DImpl_EnumAdapterModes,
2540 IWineD3DImpl_GetAdapterDisplayMode,
2541 IWineD3DImpl_GetAdapterIdentifier,
2542 IWineD3DImpl_CheckDeviceMultiSampleType,
2543 IWineD3DImpl_CheckDepthStencilMatch,
2544 IWineD3DImpl_CheckDeviceType,
2545 IWineD3DImpl_CheckDeviceFormat,
2546 IWineD3DImpl_CheckDeviceFormatConversion,
2547 IWineD3DImpl_GetDeviceCaps,
2548 IWineD3DImpl_CreateDevice