wined3d: Instancing emulation.
[wine/multimedia.git] / dlls / wined3d / directx.c
blob7e2fc05d0a5a58f7fe855816963933f4414cf6ef
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 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
289 break;
290 case SHADER_ARB:
291 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
292 break;
293 case SHADER_SW:
294 gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */
295 break;
296 default:
297 gl_info->max_pshader_constantsF = 0;
298 break;
302 /**********************************************************
303 * IWineD3D parts follows
304 **********************************************************/
306 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
307 IWineD3DImpl *This = (IWineD3DImpl *)iface;
308 WineD3D_GL_Info *gl_info = &This->gl_info;
310 const char *GL_Extensions = NULL;
311 const char *GLX_Extensions = NULL;
312 const char *gl_string = NULL;
313 const char *gl_string_cursor = NULL;
314 GLint gl_max;
315 GLfloat gl_floatv[2];
316 Bool test = 0;
317 int major, minor;
318 BOOL return_value = TRUE;
319 int i;
321 /* Make sure that we've got a context */
322 /* TODO: CreateFakeGLContext should really take a display as a parameter */
323 /* Only save the values obtained when a display is provided */
324 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
325 return_value = FALSE;
327 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
329 gl_string = (const char *) glGetString(GL_RENDERER);
330 if (NULL == gl_string)
331 gl_string = "None";
332 strcpy(gl_info->gl_renderer, gl_string);
334 /* Fill in the GL info retrievable depending on the display */
335 if (NULL != display) {
336 test = glXQueryVersion(display, &major, &minor);
337 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
338 } else {
339 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
341 gl_string = (const char *) glGetString(GL_VENDOR);
343 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
344 if (gl_string != NULL) {
345 /* Fill in the GL vendor */
346 if (strstr(gl_string, "NVIDIA")) {
347 gl_info->gl_vendor = VENDOR_NVIDIA;
348 } else if (strstr(gl_string, "ATI")) {
349 gl_info->gl_vendor = VENDOR_ATI;
350 } else if (strstr(gl_string, "Intel(R)") ||
351 strstr(gl_info->gl_renderer, "Intel(R)")) {
352 gl_info->gl_vendor = VENDOR_INTEL;
353 } else if (strstr(gl_string, "Mesa")) {
354 gl_info->gl_vendor = VENDOR_MESA;
355 } else {
356 gl_info->gl_vendor = VENDOR_WINE;
358 } else {
359 gl_info->gl_vendor = VENDOR_WINE;
363 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
365 /* Parse the GL_VERSION field into major and minor information */
366 gl_string = (const char *) glGetString(GL_VERSION);
367 if (gl_string != NULL) {
369 switch (gl_info->gl_vendor) {
370 case VENDOR_NVIDIA:
371 gl_string_cursor = strstr(gl_string, "NVIDIA");
372 if (!gl_string_cursor) {
373 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
374 break;
377 gl_string_cursor = strstr(gl_string_cursor, " ");
378 if (!gl_string_cursor) {
379 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
380 break;
383 while (*gl_string_cursor == ' ') {
384 ++gl_string_cursor;
387 if (!*gl_string_cursor) {
388 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
389 break;
392 major = atoi(gl_string_cursor);
393 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
394 ++gl_string_cursor;
397 if (*gl_string_cursor++ != '.') {
398 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
399 break;
402 minor = atoi(gl_string_cursor);
403 minor = major*100+minor;
404 major = 10;
406 break;
408 case VENDOR_ATI:
409 major = minor = 0;
410 gl_string_cursor = strchr(gl_string, '-');
411 if (gl_string_cursor) {
412 int error = 0;
413 gl_string_cursor++;
415 /* Check if version number is of the form x.y.z */
416 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
417 error = 1;
418 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
419 error = 1;
420 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
421 error = 1;
422 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
423 error = 1;
425 /* Mark version number as malformed */
426 if (error)
427 gl_string_cursor = 0;
430 if (!gl_string_cursor)
431 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
432 else {
433 major = *gl_string_cursor - '0';
434 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
436 break;
438 case VENDOR_INTEL:
439 case VENDOR_MESA:
440 gl_string_cursor = strstr(gl_string, "Mesa");
441 gl_string_cursor = strstr(gl_string_cursor, " ");
442 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
443 if (*gl_string_cursor) {
444 char tmp[16];
445 int cursor = 0;
447 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
448 tmp[cursor++] = *gl_string_cursor;
449 ++gl_string_cursor;
451 tmp[cursor] = 0;
452 major = atoi(tmp);
454 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
455 ++gl_string_cursor;
457 cursor = 0;
458 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
459 tmp[cursor++] = *gl_string_cursor;
460 ++gl_string_cursor;
462 tmp[cursor] = 0;
463 minor = atoi(tmp);
465 break;
467 default:
468 major = 0;
469 minor = 9;
471 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
472 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
475 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
478 * Initialize openGL extension related variables
479 * with Default values
481 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
482 gl_info->max_buffers = 1;
483 gl_info->max_textures = 1;
484 gl_info->max_texture_stages = 1;
485 gl_info->max_samplers = 1;
486 gl_info->max_sampler_stages = 1;
487 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
488 gl_info->ps_arb_max_temps = 0;
489 gl_info->ps_arb_max_instructions = 0;
490 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
491 gl_info->vs_arb_max_temps = 0;
492 gl_info->vs_arb_max_instructions = 0;
493 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
494 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
495 gl_info->vs_glsl_constantsF = 0;
496 gl_info->ps_glsl_constantsF = 0;
497 gl_info->vs_arb_constantsF = 0;
498 gl_info->ps_arb_constantsF = 0;
500 /* Now work out what GL support this card really has */
501 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
502 GL_EXT_FUNCS_GEN;
503 GLX_EXT_FUNCS_GEN;
504 #undef USE_GL_FUNC
506 /* Retrieve opengl defaults */
507 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
508 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
509 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
511 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
512 gl_info->max_lights = gl_max;
513 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
515 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
516 gl_info->max_texture_size = gl_max;
517 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
519 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
520 gl_info->max_pointsize = gl_floatv[1];
521 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
523 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
524 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
525 TRACE_(d3d_caps)("GL_Extensions reported:\n");
527 if (NULL == GL_Extensions) {
528 ERR(" GL_Extensions returns NULL\n");
529 } else {
530 while (*GL_Extensions != 0x00) {
531 const char *Start = GL_Extensions;
532 char ThisExtn[256];
534 memset(ThisExtn, 0x00, sizeof(ThisExtn));
535 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
536 GL_Extensions++;
538 memcpy(ThisExtn, Start, (GL_Extensions - Start));
539 TRACE_(d3d_caps)("- %s\n", ThisExtn);
542 * ARB
544 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
545 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
546 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
547 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
548 gl_info->max_buffers = gl_max;
549 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
550 gl_info->ps_arb_version = PS_VERSION_11;
551 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
552 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
553 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
554 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
555 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
556 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
557 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
558 gl_info->ps_arb_constantsF = gl_max;
559 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
560 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
561 gl_info->ps_arb_max_temps = gl_max;
562 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
563 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
564 gl_info->ps_arb_max_instructions = gl_max;
565 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
566 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
567 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
568 gl_max /= 4;
569 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
570 gl_info->ps_glsl_constantsF = gl_max;
571 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
572 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
573 gl_info->supported[ARB_IMAGING] = TRUE;
574 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
575 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
576 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
577 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
578 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
579 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
580 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
581 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
582 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
583 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
584 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
585 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
586 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
587 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
588 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
589 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
590 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
591 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
592 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
593 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
594 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
595 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
596 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
597 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
598 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
599 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
600 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
601 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
602 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
603 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
604 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
605 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
606 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
607 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
608 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
609 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
610 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
611 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
612 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
613 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
614 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
615 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
616 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
617 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
618 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
619 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
620 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
621 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
622 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
623 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
624 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
625 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
626 gl_info->vs_arb_version = VS_VERSION_11;
627 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
628 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
629 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
630 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
631 gl_info->vs_arb_constantsF = gl_max;
632 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
633 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
634 gl_info->vs_arb_max_temps = gl_max;
635 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
636 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
637 gl_info->vs_arb_max_instructions = gl_max;
638 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
639 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
640 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
641 gl_max /= 4;
642 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
643 gl_info->vs_glsl_constantsF = gl_max;
644 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
645 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
646 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
647 gl_info->max_blends = gl_max;
648 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
649 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
650 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
651 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
652 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
653 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
654 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
655 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
656 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
657 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
659 * EXT
661 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
662 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
663 gl_info->supported[EXT_FOG_COORD] = TRUE;
664 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
665 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
666 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
667 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
668 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
669 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
670 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
671 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
672 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
673 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
674 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
675 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
676 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
677 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
678 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
679 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
680 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
681 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
682 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
683 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
684 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
685 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
686 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
687 gl_info->supported[EXT_TEXTURE3D] = TRUE;
688 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
689 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
690 gl_info->max_texture3d_size = gl_max;
691 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
692 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
693 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
694 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
695 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
696 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
697 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
698 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
699 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
700 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
701 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
702 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
703 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
704 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
705 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
706 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
707 gl_info->max_anisotropy = gl_max;
708 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
709 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
710 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
711 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
712 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
713 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
714 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
715 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
716 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
719 * NVIDIA
721 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
722 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
723 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
724 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
725 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
726 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
727 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
728 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
729 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
730 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
731 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
732 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
733 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
734 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
735 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
736 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
737 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
738 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
739 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
740 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
741 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
742 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
743 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
744 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
745 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
746 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
747 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
748 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
749 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
750 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
751 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
752 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
753 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
754 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
755 gl_info->vs_nv_version = VS_VERSION_30;
756 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
757 gl_info->vs_nv_version = VS_VERSION_20;
758 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
759 gl_info->vs_nv_version = VS_VERSION_11;
760 else
761 gl_info->vs_nv_version = VS_VERSION_10;
762 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
763 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
766 * ATI
768 /** TODO */
769 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
770 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
771 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
772 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
773 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
774 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
775 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
776 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
777 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
778 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
779 gl_info->vs_ati_version = VS_VERSION_11;
780 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
781 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
785 if (*GL_Extensions == ' ') GL_Extensions++;
788 checkGLcall("extension detection\n");
790 /* In some cases the number of texture stages can be larger than the number
791 * of samplers. The GF4 for example can use only 2 samplers (no fragment
792 * shaders), but 8 texture stages (register combiners). */
793 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
795 /* We can only use ORM_FBO when the hardware supports it. */
796 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
797 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
798 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
801 /* MRTs are currently only supported when FBOs are used. */
802 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
803 gl_info->max_buffers = 1;
806 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
807 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
808 * in case of the latest videocards in the number of pixel/vertex pipelines.
810 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
811 * rendering. Various games use this information to get a rough estimation of the features of the card
812 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
813 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
814 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
815 * not the PCI id.
817 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
818 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
819 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
820 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
821 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
822 * is used for rendering which is not always the case). This would work but it is not very portable. Second
823 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
824 * is limited.
826 * As said most games only use the PCI id to get an indication of the capabilities of the card.
827 * It doesn't really matter if the given id is the correct one if we return the id of a card with
828 * similar 3d features.
830 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
831 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
832 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
833 * won't pass we return a default card. This way is better than maintaining a full card database as even
834 * without a full database we can return a card with similar features. Second the size of the database
835 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
836 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
837 * to distinguishes between different models from that family.
839 switch (gl_info->gl_vendor) {
840 case VENDOR_NVIDIA:
841 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
842 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
844 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
845 if (strstr(gl_info->gl_renderer, "7800") ||
846 strstr(gl_info->gl_renderer, "7900") ||
847 strstr(gl_info->gl_renderer, "7950") ||
848 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
849 strstr(gl_info->gl_renderer, "Quadro FX 5"))
850 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
851 else if(strstr(gl_info->gl_renderer, "6800") ||
852 strstr(gl_info->gl_renderer, "7600"))
853 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
854 else if(strstr(gl_info->gl_renderer, "6600") ||
855 strstr(gl_info->gl_renderer, "6610") ||
856 strstr(gl_info->gl_renderer, "6700"))
857 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
858 else
859 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
860 } else if(WINE_D3D9_CAPABLE(gl_info)) {
861 if (strstr(gl_info->gl_renderer, "5800") ||
862 strstr(gl_info->gl_renderer, "5900") ||
863 strstr(gl_info->gl_renderer, "5950") ||
864 strstr(gl_info->gl_renderer, "Quadro FX"))
865 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
866 else if(strstr(gl_info->gl_renderer, "5600") ||
867 strstr(gl_info->gl_renderer, "5650") ||
868 strstr(gl_info->gl_renderer, "5700") ||
869 strstr(gl_info->gl_renderer, "5750"))
870 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
871 else
872 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
873 } else if(WINE_D3D8_CAPABLE(gl_info)) {
874 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
875 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
876 else
877 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
878 } else if(WINE_D3D7_CAPABLE(gl_info)) {
879 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
880 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
881 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
882 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
883 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
884 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
885 else
886 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
887 } else {
888 if (strstr(gl_info->gl_renderer, "TNT2"))
889 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
890 else
891 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
893 break;
894 case VENDOR_ATI:
895 if(WINE_D3D9_CAPABLE(gl_info)) {
896 /* Radeon R5xx */
897 if (strstr(gl_info->gl_renderer, "X1600") ||
898 strstr(gl_info->gl_renderer, "X1800") ||
899 strstr(gl_info->gl_renderer, "X1900") ||
900 strstr(gl_info->gl_renderer, "X1950"))
901 gl_info->gl_card = CARD_ATI_RADEON_X1600;
902 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
903 else if(strstr(gl_info->gl_renderer, "X700") ||
904 strstr(gl_info->gl_renderer, "X800") ||
905 strstr(gl_info->gl_renderer, "X850") ||
906 strstr(gl_info->gl_renderer, "X1300") ||
907 strstr(gl_info->gl_renderer, "X1400"))
908 gl_info->gl_card = CARD_ATI_RADEON_X700;
909 /* Radeon R3xx */
910 else
911 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
912 } else if(WINE_D3D8_CAPABLE(gl_info)) {
913 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
914 } else if(WINE_D3D7_CAPABLE(gl_info)) {
915 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
916 } else
917 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
918 break;
919 case VENDOR_INTEL:
920 if (strstr(gl_info->gl_renderer, "915GM")) {
921 gl_info->gl_card = CARD_INTEL_I915GM;
922 } else if (strstr(gl_info->gl_renderer, "915G")) {
923 gl_info->gl_card = CARD_INTEL_I915G;
924 } else if (strstr(gl_info->gl_renderer, "865G")) {
925 gl_info->gl_card = CARD_INTEL_I865G;
926 } else if (strstr(gl_info->gl_renderer, "855G")) {
927 gl_info->gl_card = CARD_INTEL_I855G;
928 } else if (strstr(gl_info->gl_renderer, "830G")) {
929 gl_info->gl_card = CARD_INTEL_I830G;
930 } else {
931 gl_info->gl_card = CARD_INTEL_I915G;
933 break;
934 case VENDOR_MESA:
935 case VENDOR_WINE:
936 default:
937 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
938 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
939 * them a good generic choice.
941 gl_info->gl_vendor = VENDOR_NVIDIA;
942 if(WINE_D3D9_CAPABLE(gl_info))
943 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
944 else if(WINE_D3D8_CAPABLE(gl_info))
945 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
946 else if(WINE_D3D7_CAPABLE(gl_info))
947 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
948 else if(WINE_D3D6_CAPABLE(gl_info))
949 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
950 else
951 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
953 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
955 /* Load all the lookup tables
956 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
957 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
958 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
960 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
961 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
964 for (i = 0; i < MAX_LOOKUPS; i++) {
965 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
968 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
969 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
970 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
971 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
972 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
973 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
974 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
975 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
976 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
977 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
979 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
980 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
981 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
982 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
983 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
986 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
987 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
988 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
989 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
990 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
991 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
992 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
993 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
994 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
995 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
996 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
997 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
998 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1000 /* TODO: config lookups */
1002 if (display != NULL) {
1003 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1004 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1006 if (NULL == GLX_Extensions) {
1007 ERR(" GLX_Extensions returns NULL\n");
1008 } else {
1009 while (*GLX_Extensions != 0x00) {
1010 const char *Start = GLX_Extensions;
1011 char ThisExtn[256];
1013 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1014 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1015 GLX_Extensions++;
1017 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1018 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1019 if (*GLX_Extensions == ' ') GLX_Extensions++;
1025 WineD3D_ReleaseFakeGLContext();
1026 return return_value;
1029 /**********************************************************
1030 * IWineD3D implementation follows
1031 **********************************************************/
1033 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1034 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1036 /* FIXME: Set to one for now to imply the display */
1037 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1038 return 1;
1041 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1042 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1043 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1044 return WINED3D_OK;
1047 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1048 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1049 POINT pt = { -1, -1 };
1051 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1052 return NULL;
1055 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1056 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1059 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1060 of the same bpp but different resolutions */
1062 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1063 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1064 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1065 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1067 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1068 return 0;
1071 if (Adapter == 0) { /* Display */
1072 int i = 0;
1073 int j = 0;
1074 #if !defined( DEBUG_SINGLE_MODE )
1075 DEVMODEW DevModeW;
1077 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1078 j++;
1079 switch (Format)
1081 case WINED3DFMT_UNKNOWN:
1082 if (DevModeW.dmBitsPerPel == 32 ||
1083 DevModeW.dmBitsPerPel == 16) i++;
1084 break;
1085 case WINED3DFMT_X8R8G8B8:
1086 if (DevModeW.dmBitsPerPel == 32) i++;
1087 break;
1088 case WINED3DFMT_R5G6B5:
1089 if (DevModeW.dmBitsPerPel == 16) i++;
1090 break;
1091 default:
1092 /* Skip other modes as they do not match the requested format */
1093 break;
1096 #else
1097 i = 1;
1098 j = 1;
1099 #endif
1100 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1101 return i;
1102 } else {
1103 FIXME_(d3d_caps)("Adapter not primary display\n");
1105 return 0;
1108 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1109 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1110 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1111 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1113 /* Validate the parameters as much as possible */
1114 if (NULL == pMode ||
1115 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1116 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1117 return WINED3DERR_INVALIDCALL;
1120 if (Adapter == 0) { /* Display */
1121 #if !defined( DEBUG_SINGLE_MODE )
1122 DEVMODEW DevModeW;
1123 int ModeIdx = 0;
1124 int i = 0;
1125 int j = 0;
1127 /* If we are filtering to a specific format (D3D9), then need to skip
1128 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1129 just count through the ones with valid bit depths */
1130 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1131 switch (Format)
1133 case WINED3DFMT_UNKNOWN:
1134 if (DevModeW.dmBitsPerPel == 32 ||
1135 DevModeW.dmBitsPerPel == 16) i++;
1136 break;
1137 case WINED3DFMT_X8R8G8B8:
1138 if (DevModeW.dmBitsPerPel == 32) i++;
1139 break;
1140 case WINED3DFMT_R5G6B5:
1141 if (DevModeW.dmBitsPerPel == 16) i++;
1142 break;
1143 default:
1144 /* Modes that don't match what we support can get an early-out */
1145 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1146 return WINED3DERR_INVALIDCALL;
1150 if (i == 0) {
1151 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1152 return WINED3DERR_INVALIDCALL;
1154 ModeIdx = j - 1;
1156 /* Now get the display mode via the calculated index */
1157 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1158 pMode->Width = DevModeW.dmPelsWidth;
1159 pMode->Height = DevModeW.dmPelsHeight;
1160 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1161 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1162 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1164 if (Format == WINED3DFMT_UNKNOWN)
1166 switch (DevModeW.dmBitsPerPel)
1168 case 16:
1169 pMode->Format = WINED3DFMT_R5G6B5;
1170 break;
1171 case 32:
1172 pMode->Format = WINED3DFMT_X8R8G8B8;
1173 break;
1174 default:
1175 pMode->Format = WINED3DFMT_UNKNOWN;
1176 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1178 } else {
1179 pMode->Format = Format;
1181 } else {
1182 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1183 return WINED3DERR_INVALIDCALL;
1186 #else
1187 /* Return one setting of the format requested */
1188 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1189 pMode->Width = 800;
1190 pMode->Height = 600;
1191 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1192 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1193 #endif
1194 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1195 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1196 DevModeW.dmBitsPerPel);
1198 } else {
1199 FIXME_(d3d_caps)("Adapter not primary display\n");
1202 return WINED3D_OK;
1205 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1206 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1207 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1209 if (NULL == pMode ||
1210 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1211 return WINED3DERR_INVALIDCALL;
1214 if (Adapter == 0) { /* Display */
1215 int bpp = 0;
1216 DEVMODEW DevModeW;
1218 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1219 pMode->Width = DevModeW.dmPelsWidth;
1220 pMode->Height = DevModeW.dmPelsHeight;
1221 bpp = DevModeW.dmBitsPerPel;
1222 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1223 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1225 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1228 switch (bpp) {
1229 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1230 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1231 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1232 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1233 default: pMode->Format = WINED3DFMT_UNKNOWN;
1236 } else {
1237 FIXME_(d3d_caps)("Adapter not primary display\n");
1240 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1241 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1242 return WINED3D_OK;
1245 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1246 Display *display;
1247 HDC device_context;
1248 /* only works with one adapter at the moment... */
1250 /* Get the display */
1251 device_context = GetDC(0);
1252 display = get_display(device_context);
1253 ReleaseDC(0, device_context);
1254 return display;
1257 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1258 and fields being inserted in the middle, a new structure is used in place */
1259 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1260 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1261 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1263 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1265 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1266 return WINED3DERR_INVALIDCALL;
1269 if (Adapter == 0) { /* Display - only device supported for now */
1271 BOOL isGLInfoValid = This->isGLInfoValid;
1273 /* FillGLCaps updates gl_info, but we only want to store and
1274 reuse the values once we have a context which is valid. Values from
1275 a temporary context may differ from the final ones */
1276 if (!isGLInfoValid) {
1277 /* If we don't know the device settings, go query them now */
1278 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1281 /* If it worked, return the information requested */
1282 if (isGLInfoValid) {
1283 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1284 strcpy(pIdentifier->Driver, "Display");
1285 strcpy(pIdentifier->Description, "Direct3D HAL");
1287 /* Note dx8 doesn't supply a DeviceName */
1288 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1289 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1290 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1291 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1292 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1293 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1294 *(pIdentifier->SubSysId) = 0;
1295 *(pIdentifier->Revision) = 0;
1297 } else {
1299 /* If it failed, return dummy values from an NVidia driver */
1300 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1301 strcpy(pIdentifier->Driver, "Display");
1302 strcpy(pIdentifier->Description, "Direct3D HAL");
1303 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1304 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1305 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1306 /* 71.74 is a current Linux Nvidia driver version */
1307 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1308 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1309 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1310 *(pIdentifier->SubSysId) = 0;
1311 *(pIdentifier->Revision) = 0;
1314 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1315 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1316 *(pIdentifier->WHQLLevel) = 0;
1317 } else {
1318 *(pIdentifier->WHQLLevel) = 1;
1321 } else {
1322 FIXME_(d3d_caps)("Adapter not primary display\n");
1325 return WINED3D_OK;
1328 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1329 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1330 int gl_test;
1331 int rb, gb, bb, ab, type, buf_sz;
1333 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1334 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1335 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1336 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1337 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1338 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1340 switch (Format) {
1341 case WINED3DFMT_X8R8G8B8:
1342 case WINED3DFMT_R8G8B8:
1343 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1344 break;
1345 case WINED3DFMT_A8R8G8B8:
1346 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1347 break;
1348 case WINED3DFMT_A2R10G10B10:
1349 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1350 break;
1351 case WINED3DFMT_X1R5G5B5:
1352 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1353 break;
1354 case WINED3DFMT_A1R5G5B5:
1355 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1356 break;
1357 case WINED3DFMT_X4R4G4B4:
1358 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1359 break;
1360 case WINED3DFMT_R5G6B5:
1361 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1362 break;
1363 case WINED3DFMT_R3G3B2:
1364 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1365 break;
1366 case WINED3DFMT_A8P8:
1367 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1368 break;
1369 case WINED3DFMT_P8:
1370 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1371 break;
1372 default:
1373 break;
1375 return FALSE;
1376 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1377 switch (Format) {
1378 case WINED3DFMT_X8R8G8B8:
1379 case WINED3DFMT_R8G8B8:
1380 case WINED3DFMT_A8R8G8B8:
1381 case WINED3DFMT_A2R10G10B10:
1382 case WINED3DFMT_X1R5G5B5:
1383 case WINED3DFMT_A1R5G5B5:
1384 case WINED3DFMT_R5G6B5:
1385 case WINED3DFMT_R3G3B2:
1386 case WINED3DFMT_A8P8:
1387 case WINED3DFMT_P8:
1388 return TRUE;
1389 default:
1390 break;
1392 return FALSE;
1393 #endif
1396 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1397 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1398 int gl_test;
1399 int db, sb;
1401 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1402 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1404 switch (Format) {
1405 case WINED3DFMT_D16:
1406 case WINED3DFMT_D16_LOCKABLE:
1407 if (16 == db) return TRUE;
1408 break;
1409 case WINED3DFMT_D32:
1410 if (32 == db) return TRUE;
1411 break;
1412 case WINED3DFMT_D15S1:
1413 if (15 == db) return TRUE;
1414 break;
1415 case WINED3DFMT_D24S8:
1416 if (24 == db && 8 == sb) return TRUE;
1417 break;
1418 case WINED3DFMT_D24FS8:
1419 if (24 == db && 8 == sb) return TRUE;
1420 break;
1421 case WINED3DFMT_D24X8:
1422 if (24 == db) return TRUE;
1423 break;
1424 case WINED3DFMT_D24X4S4:
1425 if (24 == db && 4 == sb) return TRUE;
1426 break;
1427 case WINED3DFMT_D32F_LOCKABLE:
1428 if (32 == db) return TRUE;
1429 break;
1430 default:
1431 break;
1433 return FALSE;
1434 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1435 switch (Format) {
1436 case WINED3DFMT_D16:
1437 case WINED3DFMT_D16_LOCKABLE:
1438 case WINED3DFMT_D32:
1439 case WINED3DFMT_D15S1:
1440 case WINED3DFMT_D24S8:
1441 case WINED3DFMT_D24FS8:
1442 case WINED3DFMT_D24X8:
1443 case WINED3DFMT_D24X4S4:
1444 case WINED3DFMT_D32F_LOCKABLE:
1445 return TRUE;
1446 default:
1447 break;
1449 return FALSE;
1450 #endif
1453 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1454 WINED3DFORMAT AdapterFormat,
1455 WINED3DFORMAT RenderTargetFormat,
1456 WINED3DFORMAT DepthStencilFormat) {
1457 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1458 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1459 GLXFBConfig* cfgs = NULL;
1460 int nCfgs = 0;
1461 int it;
1463 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1464 This, Adapter,
1465 DeviceType, debug_d3ddevicetype(DeviceType),
1466 AdapterFormat, debug_d3dformat(AdapterFormat),
1467 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1468 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1470 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1471 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1472 return WINED3DERR_INVALIDCALL;
1475 if(WineD3D_CreateFakeGLContext())
1476 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1478 if (cfgs) {
1479 for (it = 0; it < nCfgs; ++it) {
1480 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1481 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1482 hr = WINED3D_OK;
1483 break ;
1487 XFree(cfgs);
1488 if(hr != WINED3D_OK)
1489 ERR("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1490 } else {
1491 ERR_(d3d_caps)("returning WINED3D_OK even so CreateFakeGLContext or glXGetFBConfigs failed\n");
1492 hr = WINED3D_OK;
1495 WineD3D_ReleaseFakeGLContext();
1497 if (hr != WINED3D_OK)
1498 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1500 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1501 return hr;
1504 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1505 WINED3DFORMAT SurfaceFormat,
1506 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1508 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1509 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1510 This,
1511 Adapter,
1512 DeviceType, debug_d3ddevicetype(DeviceType),
1513 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1514 Windowed,
1515 MultiSampleType,
1516 pQualityLevels);
1518 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1519 return WINED3DERR_INVALIDCALL;
1522 if (pQualityLevels != NULL) {
1523 static int s_single_shot = 0;
1524 if (!s_single_shot) {
1525 FIXME("Quality levels unsupported at present\n");
1526 s_single_shot = 1;
1528 *pQualityLevels = 1; /* Guess at a value! */
1531 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1532 return WINED3DERR_NOTAVAILABLE;
1535 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1536 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1538 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1539 GLXFBConfig* cfgs = NULL;
1540 int nCfgs = 0;
1541 int it;
1542 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1544 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1545 This,
1546 Adapter,
1547 CheckType, debug_d3ddevicetype(CheckType),
1548 DisplayFormat, debug_d3dformat(DisplayFormat),
1549 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1550 Windowed);
1552 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1553 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1554 return WINED3DERR_INVALIDCALL;
1557 if (WineD3D_CreateFakeGLContext()) {
1558 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1559 for (it = 0; it < nCfgs; ++it) {
1560 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1561 hr = WINED3D_OK;
1562 TRACE_(d3d_caps)("OK\n");
1563 break ;
1566 if(cfgs) XFree(cfgs);
1567 if(hr != WINED3D_OK)
1568 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1569 WineD3D_ReleaseFakeGLContext();
1572 if(hr != WINED3D_OK)
1573 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1575 return hr;
1578 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1579 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1580 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1581 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1582 This,
1583 Adapter,
1584 DeviceType, debug_d3ddevicetype(DeviceType),
1585 AdapterFormat, debug_d3dformat(AdapterFormat),
1586 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1587 RType, debug_d3dresourcetype(RType),
1588 CheckFormat, debug_d3dformat(CheckFormat));
1590 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1591 return WINED3DERR_INVALIDCALL;
1594 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1595 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1596 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1597 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1598 TRACE_(d3d_caps)("[FAILED]\n");
1599 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1602 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1603 switch (CheckFormat) {
1604 case WINED3DFMT_D16_LOCKABLE:
1605 case WINED3DFMT_D32:
1606 case WINED3DFMT_D15S1:
1607 case WINED3DFMT_D24S8:
1608 case WINED3DFMT_D24X8:
1609 case WINED3DFMT_D24X4S4:
1610 case WINED3DFMT_D16:
1611 case WINED3DFMT_L16:
1612 case WINED3DFMT_D32F_LOCKABLE:
1613 case WINED3DFMT_D24FS8:
1614 TRACE_(d3d_caps)("[OK]\n");
1615 return WINED3D_OK;
1616 default:
1617 TRACE_(d3d_caps)("[FAILED]\n");
1618 return WINED3DERR_NOTAVAILABLE;
1620 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1621 switch (CheckFormat) {
1622 case WINED3DFMT_R8G8B8:
1623 case WINED3DFMT_A8R8G8B8:
1624 case WINED3DFMT_X8R8G8B8:
1625 case WINED3DFMT_R5G6B5:
1626 case WINED3DFMT_X1R5G5B5:
1627 case WINED3DFMT_A1R5G5B5:
1628 case WINED3DFMT_A4R4G4B4:
1629 case WINED3DFMT_R3G3B2:
1630 case WINED3DFMT_X4R4G4B4:
1631 case WINED3DFMT_A8B8G8R8:
1632 case WINED3DFMT_X8B8G8R8:
1633 case WINED3DFMT_P8:
1634 TRACE_(d3d_caps)("[OK]\n");
1635 return WINED3D_OK;
1636 default:
1637 TRACE_(d3d_caps)("[FAILED]\n");
1638 return WINED3DERR_NOTAVAILABLE;
1642 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1643 switch (CheckFormat) {
1644 case WINED3DFMT_DXT1:
1645 case WINED3DFMT_DXT2:
1646 case WINED3DFMT_DXT3:
1647 case WINED3DFMT_DXT4:
1648 case WINED3DFMT_DXT5:
1649 TRACE_(d3d_caps)("[OK]\n");
1650 return WINED3D_OK;
1651 default:
1652 break; /* Avoid compiler warnings */
1656 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1658 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1660 switch (CheckFormat) {
1661 case WINED3DFMT_R16F:
1662 case WINED3DFMT_A16B16G16R16F:
1663 if (!half_pixel_support) break;
1664 case WINED3DFMT_R32F:
1665 case WINED3DFMT_A32B32G32R32F:
1666 TRACE_(d3d_caps)("[OK]\n");
1667 return WINED3D_OK;
1668 default:
1669 break; /* Avoid compiler warnings */
1673 /* This format is nothing special and it is supported perfectly.
1674 * However, ati and nvidia driver on windows do not mark this format as
1675 * supported (tested with the dxCapsViewer) and pretending to
1676 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1677 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1678 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1680 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1681 TRACE_(d3d_caps)("[FAILED]\n");
1682 return WINED3DERR_NOTAVAILABLE;
1685 switch (CheckFormat) {
1687 /*****
1688 * supported: RGB(A) formats
1690 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1691 case WINED3DFMT_A8R8G8B8:
1692 case WINED3DFMT_X8R8G8B8:
1693 case WINED3DFMT_R5G6B5:
1694 case WINED3DFMT_X1R5G5B5:
1695 case WINED3DFMT_A1R5G5B5:
1696 case WINED3DFMT_A4R4G4B4:
1697 case WINED3DFMT_R3G3B2:
1698 case WINED3DFMT_A8:
1699 case WINED3DFMT_A8R3G3B2:
1700 case WINED3DFMT_X4R4G4B4:
1701 case WINED3DFMT_A8B8G8R8:
1702 case WINED3DFMT_X8B8G8R8:
1703 case WINED3DFMT_A2R10G10B10:
1704 case WINED3DFMT_A2B10G10R10:
1705 TRACE_(d3d_caps)("[OK]\n");
1706 return WINED3D_OK;
1708 /*****
1709 * supported: Palettized
1711 case WINED3DFMT_P8:
1712 TRACE_(d3d_caps)("[OK]\n");
1713 return WINED3D_OK;
1715 /*****
1716 * Supported: (Alpha)-Luminance
1718 case WINED3DFMT_L8:
1719 case WINED3DFMT_A8L8:
1720 case WINED3DFMT_A4L4:
1721 TRACE_(d3d_caps)("[OK]\n");
1722 return WINED3D_OK;
1724 /*****
1725 * Not supported for now: Bump mapping formats
1726 * Enable some because games often fail when they are not available
1727 * and are still playable even without bump mapping
1729 case WINED3DFMT_V8U8:
1730 case WINED3DFMT_V16U16:
1731 case WINED3DFMT_L6V5U5:
1732 case WINED3DFMT_X8L8V8U8:
1733 case WINED3DFMT_Q8W8V8U8:
1734 case WINED3DFMT_W11V11U10:
1735 case WINED3DFMT_A2W10V10U10:
1736 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1737 return WINED3D_OK;
1739 /*****
1740 * DXTN Formats: Handled above
1741 * WINED3DFMT_DXT1
1742 * WINED3DFMT_DXT2
1743 * WINED3DFMT_DXT3
1744 * WINED3DFMT_DXT4
1745 * WINED3DFMT_DXT5
1748 /*****
1749 * Odd formats - not supported
1751 case WINED3DFMT_VERTEXDATA:
1752 case WINED3DFMT_INDEX16:
1753 case WINED3DFMT_INDEX32:
1754 case WINED3DFMT_Q16W16V16U16:
1755 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1756 return WINED3DERR_NOTAVAILABLE;
1758 /*****
1759 * Float formats: Not supported right now
1761 case WINED3DFMT_G16R16F:
1762 case WINED3DFMT_G32R32F:
1763 case WINED3DFMT_CxV8U8:
1764 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1765 return WINED3DERR_NOTAVAILABLE;
1767 /* Not supported */
1768 case WINED3DFMT_G16R16:
1769 case WINED3DFMT_A16B16G16R16:
1770 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1771 return WINED3DERR_NOTAVAILABLE;
1773 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1774 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1775 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1776 * We can do instancing with all shader versions, but we need vertex shaders.
1778 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1779 * to enable instancing. WineD3D doesn't need that and just ignores it.
1781 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1783 case MAKEFOURCC('I','N','S','T'):
1784 TRACE("ATI Instancing check hack\n");
1785 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1786 TRACE_(d3d_caps)("[OK]\n");
1787 return WINED3D_OK;
1788 } else {
1789 TRACE_(d3d_caps)("[FAILED]\n");
1790 return WINED3DERR_NOTAVAILABLE;
1793 default:
1794 break;
1797 TRACE_(d3d_caps)("[FAILED]\n");
1798 return WINED3DERR_NOTAVAILABLE;
1801 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1802 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1803 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1805 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1806 This,
1807 Adapter,
1808 DeviceType, debug_d3ddevicetype(DeviceType),
1809 SourceFormat, debug_d3dformat(SourceFormat),
1810 TargetFormat, debug_d3dformat(TargetFormat));
1811 return WINED3D_OK;
1814 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1815 subset of a D3DCAPS9 structure. However, it has to come via a void *
1816 as the d3d8 interface cannot import the d3d9 header */
1817 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1819 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1820 int vs_selected_mode;
1821 int ps_selected_mode;
1823 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1825 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1826 return WINED3DERR_INVALIDCALL;
1829 /* FIXME: GL info should be per adapter */
1831 /* If we don't know the device settings, go query them now */
1832 if (!This->isGLInfoValid) {
1833 /* use the desktop window to fill gl caps */
1834 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1836 /* We are running off a real context, save the values */
1837 if (rc) This->isGLInfoValid = TRUE;
1839 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1841 /* This function should *not* be modifying GL caps
1842 * TODO: move the functionality where it belongs */
1843 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1845 /* ------------------------------------------------
1846 The following fields apply to both d3d8 and d3d9
1847 ------------------------------------------------ */
1848 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1849 *pCaps->AdapterOrdinal = Adapter;
1851 *pCaps->Caps = 0;
1852 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1853 WINED3DCAPS2_FULLSCREENGAMMA;
1854 *pCaps->Caps3 = 0;
1855 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1857 *pCaps->CursorCaps = 0;
1860 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1861 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1862 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1863 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1864 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1865 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1866 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1867 WINED3DDEVCAPS_PUREDEVICE |
1868 WINED3DDEVCAPS_HWRASTERIZATION |
1869 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1870 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1871 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1872 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1873 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1875 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1876 D3DPMISCCAPS_CULLCCW |
1877 D3DPMISCCAPS_CULLCW |
1878 D3DPMISCCAPS_COLORWRITEENABLE |
1879 D3DPMISCCAPS_CLIPTLVERTS |
1880 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1881 D3DPMISCCAPS_MASKZ |
1882 D3DPMISCCAPS_BLENDOP;
1883 /* TODO:
1884 D3DPMISCCAPS_NULLREFERENCE
1885 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1886 D3DPMISCCAPS_FOGANDSPECULARALPHA
1887 D3DPMISCCAPS_SEPARATEALPHABLEND
1888 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1889 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1890 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1892 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1893 #if 0
1894 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1895 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1896 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1897 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1898 #endif
1900 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1901 WINED3DPRASTERCAPS_PAT |
1902 WINED3DPRASTERCAPS_WFOG |
1903 WINED3DPRASTERCAPS_ZFOG |
1904 WINED3DPRASTERCAPS_FOGVERTEX |
1905 WINED3DPRASTERCAPS_FOGTABLE |
1906 WINED3DPRASTERCAPS_FOGRANGE |
1907 WINED3DPRASTERCAPS_STIPPLE |
1908 WINED3DPRASTERCAPS_SUBPIXEL |
1909 WINED3DPRASTERCAPS_ZTEST |
1910 WINED3DPRASTERCAPS_SCISSORTEST |
1911 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1912 WINED3DPRASTERCAPS_DEPTHBIAS;
1914 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1915 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1916 WINED3DPRASTERCAPS_ZBIAS |
1917 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1919 /* FIXME Add:
1920 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1921 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1922 WINED3DPRASTERCAPS_ANTIALIASEDGES
1923 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1924 WINED3DPRASTERCAPS_WBUFFER */
1926 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1927 D3DPCMPCAPS_EQUAL |
1928 D3DPCMPCAPS_GREATER |
1929 D3DPCMPCAPS_GREATEREQUAL |
1930 D3DPCMPCAPS_LESS |
1931 D3DPCMPCAPS_LESSEQUAL |
1932 D3DPCMPCAPS_NEVER |
1933 D3DPCMPCAPS_NOTEQUAL;
1935 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1936 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1937 D3DPBLENDCAPS_BOTHSRCALPHA |
1938 D3DPBLENDCAPS_DESTALPHA |
1939 D3DPBLENDCAPS_DESTCOLOR |
1940 D3DPBLENDCAPS_INVDESTALPHA |
1941 D3DPBLENDCAPS_INVDESTCOLOR |
1942 D3DPBLENDCAPS_INVSRCALPHA |
1943 D3DPBLENDCAPS_INVSRCCOLOR |
1944 D3DPBLENDCAPS_ONE |
1945 D3DPBLENDCAPS_SRCALPHA |
1946 D3DPBLENDCAPS_SRCALPHASAT |
1947 D3DPBLENDCAPS_SRCCOLOR |
1948 D3DPBLENDCAPS_ZERO;
1950 *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1951 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1952 D3DPBLENDCAPS_BOTHSRCALPHA |
1953 D3DPBLENDCAPS_DESTALPHA |
1954 D3DPBLENDCAPS_DESTCOLOR |
1955 D3DPBLENDCAPS_INVDESTALPHA |
1956 D3DPBLENDCAPS_INVDESTCOLOR |
1957 D3DPBLENDCAPS_INVSRCALPHA |
1958 D3DPBLENDCAPS_INVSRCCOLOR |
1959 D3DPBLENDCAPS_ONE |
1960 D3DPBLENDCAPS_SRCALPHA |
1961 D3DPBLENDCAPS_SRCALPHASAT |
1962 D3DPBLENDCAPS_SRCCOLOR |
1963 D3DPBLENDCAPS_ZERO;
1965 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1966 D3DPCMPCAPS_EQUAL |
1967 D3DPCMPCAPS_GREATER |
1968 D3DPCMPCAPS_GREATEREQUAL |
1969 D3DPCMPCAPS_LESS |
1970 D3DPCMPCAPS_LESSEQUAL |
1971 D3DPCMPCAPS_NEVER |
1972 D3DPCMPCAPS_NOTEQUAL;
1974 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1975 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1976 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1977 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1978 WINED3DPSHADECAPS_COLORFLATRGB |
1979 WINED3DPSHADECAPS_FOGFLAT |
1980 WINED3DPSHADECAPS_FOGGOURAUD |
1981 WINED3DPSHADECAPS_SPECULARFLATRGB;
1983 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1984 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1985 WINED3DPTEXTURECAPS_BORDER |
1986 WINED3DPTEXTURECAPS_MIPMAP |
1987 WINED3DPTEXTURECAPS_PROJECTED |
1988 WINED3DPTEXTURECAPS_PERSPECTIVE |
1989 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1991 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1992 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1993 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1994 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1997 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1998 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1999 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2000 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2004 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2005 WINED3DPTFILTERCAPS_MAGFPOINT |
2006 WINED3DPTFILTERCAPS_MINFLINEAR |
2007 WINED3DPTFILTERCAPS_MINFPOINT |
2008 WINED3DPTFILTERCAPS_MIPFLINEAR |
2009 WINED3DPTFILTERCAPS_MIPFPOINT |
2010 WINED3DPTFILTERCAPS_LINEAR |
2011 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2012 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2013 WINED3DPTFILTERCAPS_MIPLINEAR |
2014 WINED3DPTFILTERCAPS_MIPNEAREST |
2015 WINED3DPTFILTERCAPS_NEAREST;
2017 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2018 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2019 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2022 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2023 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2024 WINED3DPTFILTERCAPS_MAGFPOINT |
2025 WINED3DPTFILTERCAPS_MINFLINEAR |
2026 WINED3DPTFILTERCAPS_MINFPOINT |
2027 WINED3DPTFILTERCAPS_MIPFLINEAR |
2028 WINED3DPTFILTERCAPS_MIPFPOINT |
2029 WINED3DPTFILTERCAPS_LINEAR |
2030 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2031 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2032 WINED3DPTFILTERCAPS_MIPLINEAR |
2033 WINED3DPTFILTERCAPS_MIPNEAREST |
2034 WINED3DPTFILTERCAPS_NEAREST;
2036 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2037 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2038 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2040 } else
2041 *pCaps->CubeTextureFilterCaps = 0;
2043 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2044 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2045 WINED3DPTFILTERCAPS_MAGFPOINT |
2046 WINED3DPTFILTERCAPS_MINFLINEAR |
2047 WINED3DPTFILTERCAPS_MINFPOINT |
2048 WINED3DPTFILTERCAPS_MIPFLINEAR |
2049 WINED3DPTFILTERCAPS_MIPFPOINT |
2050 WINED3DPTFILTERCAPS_LINEAR |
2051 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2052 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2053 WINED3DPTFILTERCAPS_MIPLINEAR |
2054 WINED3DPTFILTERCAPS_MIPNEAREST |
2055 WINED3DPTFILTERCAPS_NEAREST;
2056 } else
2057 *pCaps->VolumeTextureFilterCaps = 0;
2059 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2060 D3DPTADDRESSCAPS_CLAMP |
2061 D3DPTADDRESSCAPS_WRAP;
2063 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2064 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2066 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2067 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2069 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2070 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2073 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2074 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2075 D3DPTADDRESSCAPS_CLAMP |
2076 D3DPTADDRESSCAPS_WRAP;
2077 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2078 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2080 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2081 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2083 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2084 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2086 } else
2087 *pCaps->VolumeTextureAddressCaps = 0;
2089 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2090 D3DLINECAPS_ZTEST;
2091 /* FIXME: Add
2092 D3DLINECAPS_BLEND
2093 D3DLINECAPS_ALPHACMP
2094 D3DLINECAPS_FOG */
2096 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2097 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2099 if(GL_SUPPORT(EXT_TEXTURE3D))
2100 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2101 else
2102 *pCaps->MaxVolumeExtent = 0;
2104 *pCaps->MaxTextureRepeat = 32768;
2105 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2106 *pCaps->MaxVertexW = 1.0;
2108 *pCaps->GuardBandLeft = 0;
2109 *pCaps->GuardBandTop = 0;
2110 *pCaps->GuardBandRight = 0;
2111 *pCaps->GuardBandBottom = 0;
2113 *pCaps->ExtentsAdjust = 0;
2115 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2116 D3DSTENCILCAPS_INCRSAT |
2117 D3DSTENCILCAPS_INVERT |
2118 D3DSTENCILCAPS_KEEP |
2119 D3DSTENCILCAPS_REPLACE |
2120 D3DSTENCILCAPS_ZERO;
2121 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2122 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2123 D3DSTENCILCAPS_INCR;
2125 if ( This->dxVersion > 8 &&
2126 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2127 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2128 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2131 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2133 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2134 D3DTEXOPCAPS_ADDSIGNED |
2135 D3DTEXOPCAPS_ADDSIGNED2X |
2136 D3DTEXOPCAPS_MODULATE |
2137 D3DTEXOPCAPS_MODULATE2X |
2138 D3DTEXOPCAPS_MODULATE4X |
2139 D3DTEXOPCAPS_SELECTARG1 |
2140 D3DTEXOPCAPS_SELECTARG2 |
2141 D3DTEXOPCAPS_DISABLE;
2143 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2144 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2145 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2146 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2147 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2148 D3DTEXOPCAPS_BLENDFACTORALPHA |
2149 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2150 D3DTEXOPCAPS_LERP |
2151 D3DTEXOPCAPS_SUBTRACT;
2153 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2154 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2155 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2156 D3DTEXOPCAPS_MULTIPLYADD |
2157 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2158 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2159 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2161 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2162 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2164 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2165 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2166 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2170 #if 0
2171 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2172 /* FIXME: Add
2173 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2174 D3DTEXOPCAPS_PREMODULATE */
2175 #endif
2177 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2178 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2179 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2180 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2184 #if 0 /* TODO: Blends support in drawprim */
2185 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2186 #else
2187 *pCaps->MaxVertexBlendMatrices = 0;
2188 #endif
2189 *pCaps->MaxVertexBlendMatrixIndex = 1;
2191 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2192 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2195 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2196 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2197 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2198 WINED3DVTXPCAPS_LOCALVIEWER |
2199 WINED3DVTXPCAPS_VERTEXFOG |
2200 WINED3DVTXPCAPS_TEXGEN;
2201 /* FIXME: Add
2202 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2204 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2205 *pCaps->MaxVertexIndex = 0xFFFFF;
2206 *pCaps->MaxStreams = MAX_STREAMS;
2207 *pCaps->MaxStreamStride = 1024;
2209 if (vs_selected_mode == SHADER_GLSL) {
2210 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2211 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2212 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2213 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2214 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2215 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2216 else
2217 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2218 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2219 } else if (vs_selected_mode == SHADER_ARB) {
2220 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2221 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2222 } else if (vs_selected_mode == SHADER_SW) {
2223 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2224 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2225 } else {
2226 *pCaps->VertexShaderVersion = 0;
2227 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2230 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2232 if (ps_selected_mode == SHADER_GLSL) {
2233 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2234 in case of GeforceFX cards. */
2235 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2236 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2237 else
2238 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2239 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2240 *pCaps->PixelShader1xMaxValue = 1.0;
2241 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2242 } else if (ps_selected_mode == SHADER_ARB) {
2243 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2244 *pCaps->PixelShader1xMaxValue = 1.0;
2245 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2246 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2247 } else if (ps_selected_mode = SHADER_SW) {
2248 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2249 *pCaps->PixelShader1xMaxValue = 1.0;
2250 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2251 } else {
2252 *pCaps->PixelShaderVersion = 0;
2253 *pCaps->PixelShader1xMaxValue = 0.0;
2254 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2257 /* ------------------------------------------------
2258 The following fields apply to d3d9 only
2259 ------------------------------------------------ */
2260 if (This->dxVersion > 8) {
2261 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2262 *pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET;
2263 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2264 *pCaps->MaxNpatchTessellationLevel = 0;
2265 *pCaps->MasterAdapterOrdinal = 0;
2266 *pCaps->AdapterOrdinalInGroup = 0;
2267 *pCaps->NumberOfAdaptersInGroup = 1;
2269 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2270 /* OpenGL supports all the formats below, perhaps not always
2271 * without conversion, but it supports them.
2272 * Further GLSL doesn't seem to have an official unsigned type so
2273 * don't advertise it yet as I'm not sure how we handle it.
2274 * We might need to add some clamping in the shader engine to
2275 * support it.
2276 * TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2277 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2278 D3DDTCAPS_UBYTE4N |
2279 D3DDTCAPS_SHORT2N |
2280 D3DDTCAPS_SHORT4N |
2281 D3DDTCAPS_FLOAT16_2 |
2282 D3DDTCAPS_FLOAT16_4;
2284 } else
2285 *pCaps->DeclTypes = 0;
2287 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2290 *pCaps->StretchRectFilterCaps = 0;
2291 *pCaps->VertexTextureFilterCaps = 0;
2293 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2294 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2295 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2296 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2297 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2298 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2299 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2301 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2302 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2303 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2304 *pCaps->VS20Caps.Caps = 0;
2305 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2306 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2307 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2309 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2310 *pCaps->MaxVertexShader30InstructionSlots = 0;
2311 } else { /* VS 1.x */
2312 *pCaps->VS20Caps.Caps = 0;
2313 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2314 *pCaps->VS20Caps.NumTemps = 0;
2315 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2317 *pCaps->MaxVShaderInstructionsExecuted = 0;
2318 *pCaps->MaxVertexShader30InstructionSlots = 0;
2321 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2322 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2323 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2325 /* 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 */
2326 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2327 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2328 D3DPS20CAPS_PREDICATION |
2329 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2330 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2331 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2332 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2333 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2334 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2336 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2337 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2338 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2339 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2340 *pCaps->PS20Caps.Caps = 0;
2341 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2342 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2343 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2344 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2346 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2347 *pCaps->MaxPixelShader30InstructionSlots = 0;
2348 } else { /* PS 1.x */
2349 *pCaps->PS20Caps.Caps = 0;
2350 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2351 *pCaps->PS20Caps.NumTemps = 0;
2352 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2353 *pCaps->PS20Caps.NumInstructionSlots = 0;
2355 *pCaps->MaxPShaderInstructionsExecuted = 0;
2356 *pCaps->MaxPixelShader30InstructionSlots = 0;
2360 return WINED3D_OK;
2364 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2365 and fields being inserted in the middle, a new structure is used in place */
2366 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2367 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2368 IUnknown *parent) {
2370 IWineD3DDeviceImpl *object = NULL;
2371 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2372 HDC hDC;
2373 HRESULT temp_result;
2375 /* Validate the adapter number */
2376 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2377 return WINED3DERR_INVALIDCALL;
2380 /* Create a WineD3DDevice object */
2381 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2382 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2383 TRACE("Created WineD3DDevice object @ %p\n", object);
2384 if (NULL == object) {
2385 return WINED3DERR_OUTOFVIDEOMEMORY;
2388 /* Set up initial COM information */
2389 object->lpVtbl = &IWineD3DDevice_Vtbl;
2390 object->ref = 1;
2391 object->wineD3D = iface;
2392 IWineD3D_AddRef(object->wineD3D);
2393 object->parent = parent;
2395 /* Set the state up as invalid until the device is fully created */
2396 object->state = WINED3DERR_DRIVERINTERNALERROR;
2398 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2399 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2401 /* Save the creation parameters */
2402 object->createParms.AdapterOrdinal = Adapter;
2403 object->createParms.DeviceType = DeviceType;
2404 object->createParms.hFocusWindow = hFocusWindow;
2405 object->createParms.BehaviorFlags = BehaviourFlags;
2407 /* Initialize other useful values */
2408 object->adapterNo = Adapter;
2409 object->devType = DeviceType;
2411 TRACE("(%p) : Creating stateblock\n", This);
2412 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2413 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2414 WINED3DSBT_INIT,
2415 (IWineD3DStateBlock **)&object->stateBlock,
2416 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2417 WARN("Failed to create stateblock\n");
2418 goto create_device_error;
2420 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2421 object->updateStateBlock = object->stateBlock;
2422 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2423 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2425 /* Setup some defaults for creating the implicit swapchain */
2426 ENTER_GL();
2427 /* FIXME: GL info should be per adapter */
2428 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2429 LEAVE_GL();
2430 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2431 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2432 object->shader_backend = &glsl_shader_backend;
2433 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2434 object->shader_backend = &arb_program_shader_backend;
2435 } else {
2436 object->shader_backend = &none_shader_backend;
2439 /* This function should *not* be modifying GL caps
2440 * TODO: move the functionality where it belongs */
2441 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2443 temp_result = allocate_shader_constants(object->updateStateBlock);
2444 if (WINED3D_OK != temp_result)
2445 return temp_result;
2447 object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2449 object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
2451 /* set the state of the device to valid */
2452 object->state = WINED3D_OK;
2454 /* Get the initial screen setup for ddraw */
2455 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2456 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2457 hDC = GetDC(0);
2458 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2459 ReleaseDC(0, hDC);
2461 return WINED3D_OK;
2462 create_device_error:
2464 /* Set the device state to error */
2465 object->state = WINED3DERR_DRIVERINTERNALERROR;
2467 if (object->updateStateBlock != NULL) {
2468 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2469 object->updateStateBlock = NULL;
2471 if (object->stateBlock != NULL) {
2472 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2473 object->stateBlock = NULL;
2475 if (object->render_targets[0] != NULL) {
2476 IWineD3DSurface_Release(object->render_targets[0]);
2477 object->render_targets[0] = NULL;
2479 if (object->stencilBufferTarget != NULL) {
2480 IWineD3DSurface_Release(object->stencilBufferTarget);
2481 object->stencilBufferTarget = NULL;
2483 HeapFree(GetProcessHeap(), 0, object);
2484 *ppReturnedDeviceInterface = NULL;
2485 return WINED3DERR_INVALIDCALL;
2489 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2490 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2491 IUnknown_AddRef(This->parent);
2492 *pParent = This->parent;
2493 return WINED3D_OK;
2496 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2497 IUnknown* surfaceParent;
2498 TRACE("(%p) call back\n", pSurface);
2500 /* Now, release the parent, which will take care of cleaning up the surface for us */
2501 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2502 IUnknown_Release(surfaceParent);
2503 return IUnknown_Release(surfaceParent);
2506 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2507 IUnknown* volumeParent;
2508 TRACE("(%p) call back\n", pVolume);
2510 /* Now, release the parent, which will take care of cleaning up the volume for us */
2511 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2512 IUnknown_Release(volumeParent);
2513 return IUnknown_Release(volumeParent);
2516 /**********************************************************
2517 * IWineD3D VTbl follows
2518 **********************************************************/
2520 const IWineD3DVtbl IWineD3D_Vtbl =
2522 /* IUnknown */
2523 IWineD3DImpl_QueryInterface,
2524 IWineD3DImpl_AddRef,
2525 IWineD3DImpl_Release,
2526 /* IWineD3D */
2527 IWineD3DImpl_GetParent,
2528 IWineD3DImpl_GetAdapterCount,
2529 IWineD3DImpl_RegisterSoftwareDevice,
2530 IWineD3DImpl_GetAdapterMonitor,
2531 IWineD3DImpl_GetAdapterModeCount,
2532 IWineD3DImpl_EnumAdapterModes,
2533 IWineD3DImpl_GetAdapterDisplayMode,
2534 IWineD3DImpl_GetAdapterIdentifier,
2535 IWineD3DImpl_CheckDeviceMultiSampleType,
2536 IWineD3DImpl_CheckDepthStencilMatch,
2537 IWineD3DImpl_CheckDeviceType,
2538 IWineD3DImpl_CheckDeviceFormat,
2539 IWineD3DImpl_CheckDeviceFormatConversion,
2540 IWineD3DImpl_GetDeviceCaps,
2541 IWineD3DImpl_CreateDevice