wined3d: Make the context array dynamic.
[wine/wine64.git] / dlls / wined3d / directx.c
blobe711b10c283a4042e5998f822010abc702067d88
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 NP2_NATIVE when the hardware supports it. */
796 if (wined3d_settings.nonpower2_mode == NP2_NATIVE && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
797 WARN_(d3d_caps)("GL_ARB_texture_non_power_of_two not supported, falling back to NP2_NONE NPOT mode.\n");
798 wined3d_settings.nonpower2_mode = NP2_NONE;
801 /* We can only use ORM_FBO when the hardware supports it. */
802 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
803 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
804 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
807 /* MRTs are currently only supported when FBOs are used. */
808 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
809 gl_info->max_buffers = 1;
812 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
813 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
814 * in case of the latest videocards in the number of pixel/vertex pipelines.
816 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
817 * rendering. Various games use this information to get a rough estimation of the features of the card
818 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
819 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
820 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
821 * not the PCI id.
823 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
824 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
825 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
826 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
827 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
828 * is used for rendering which is not always the case). This would work but it is not very portable. Second
829 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
830 * is limited.
832 * As said most games only use the PCI id to get an indication of the capabilities of the card.
833 * It doesn't really matter if the given id is the correct one if we return the id of a card with
834 * similar 3d features.
836 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
837 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
838 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
839 * won't pass we return a default card. This way is better than maintaining a full card database as even
840 * without a full database we can return a card with similar features. Second the size of the database
841 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
842 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
843 * to distinguishes between different models from that family.
845 switch (gl_info->gl_vendor) {
846 case VENDOR_NVIDIA:
847 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
848 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
850 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
851 if (strstr(gl_info->gl_renderer, "7800") ||
852 strstr(gl_info->gl_renderer, "7900") ||
853 strstr(gl_info->gl_renderer, "7950") ||
854 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
855 strstr(gl_info->gl_renderer, "Quadro FX 5"))
856 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
857 else if(strstr(gl_info->gl_renderer, "6800") ||
858 strstr(gl_info->gl_renderer, "7600"))
859 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
860 else if(strstr(gl_info->gl_renderer, "6600") ||
861 strstr(gl_info->gl_renderer, "6610") ||
862 strstr(gl_info->gl_renderer, "6700"))
863 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
864 else
865 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
866 } else if(WINE_D3D9_CAPABLE(gl_info)) {
867 if (strstr(gl_info->gl_renderer, "5800") ||
868 strstr(gl_info->gl_renderer, "5900") ||
869 strstr(gl_info->gl_renderer, "5950") ||
870 strstr(gl_info->gl_renderer, "Quadro FX"))
871 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
872 else if(strstr(gl_info->gl_renderer, "5600") ||
873 strstr(gl_info->gl_renderer, "5650") ||
874 strstr(gl_info->gl_renderer, "5700") ||
875 strstr(gl_info->gl_renderer, "5750"))
876 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
877 else
878 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
879 } else if(WINE_D3D8_CAPABLE(gl_info)) {
880 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
881 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
882 else
883 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
884 } else if(WINE_D3D7_CAPABLE(gl_info)) {
885 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
886 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
887 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
888 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
889 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
890 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
891 else
892 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
893 } else {
894 if (strstr(gl_info->gl_renderer, "TNT2"))
895 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
896 else
897 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
899 break;
900 case VENDOR_ATI:
901 if(WINE_D3D9_CAPABLE(gl_info)) {
902 /* Radeon R5xx */
903 if (strstr(gl_info->gl_renderer, "X1600") ||
904 strstr(gl_info->gl_renderer, "X1800") ||
905 strstr(gl_info->gl_renderer, "X1900") ||
906 strstr(gl_info->gl_renderer, "X1950"))
907 gl_info->gl_card = CARD_ATI_RADEON_X1600;
908 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
909 else if(strstr(gl_info->gl_renderer, "X700") ||
910 strstr(gl_info->gl_renderer, "X800") ||
911 strstr(gl_info->gl_renderer, "X850") ||
912 strstr(gl_info->gl_renderer, "X1300") ||
913 strstr(gl_info->gl_renderer, "X1400"))
914 gl_info->gl_card = CARD_ATI_RADEON_X700;
915 /* Radeon R3xx */
916 else
917 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
918 } else if(WINE_D3D8_CAPABLE(gl_info)) {
919 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
920 } else if(WINE_D3D7_CAPABLE(gl_info)) {
921 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
922 } else
923 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
924 break;
925 case VENDOR_INTEL:
926 if (strstr(gl_info->gl_renderer, "915GM")) {
927 gl_info->gl_card = CARD_INTEL_I915GM;
928 } else if (strstr(gl_info->gl_renderer, "915G")) {
929 gl_info->gl_card = CARD_INTEL_I915G;
930 } else if (strstr(gl_info->gl_renderer, "865G")) {
931 gl_info->gl_card = CARD_INTEL_I865G;
932 } else if (strstr(gl_info->gl_renderer, "855G")) {
933 gl_info->gl_card = CARD_INTEL_I855G;
934 } else if (strstr(gl_info->gl_renderer, "830G")) {
935 gl_info->gl_card = CARD_INTEL_I830G;
936 } else {
937 gl_info->gl_card = CARD_INTEL_I915G;
939 break;
940 case VENDOR_MESA:
941 case VENDOR_WINE:
942 default:
943 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
944 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
945 * them a good generic choice.
947 gl_info->gl_vendor = VENDOR_NVIDIA;
948 if(WINE_D3D9_CAPABLE(gl_info))
949 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
950 else if(WINE_D3D8_CAPABLE(gl_info))
951 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
952 else if(WINE_D3D7_CAPABLE(gl_info))
953 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
954 else if(WINE_D3D6_CAPABLE(gl_info))
955 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
956 else
957 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
959 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
961 /* Load all the lookup tables
962 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
963 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
964 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
966 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
967 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
970 for (i = 0; i < MAX_LOOKUPS; i++) {
971 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
974 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
975 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
976 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
977 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
978 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
979 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
980 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
981 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
982 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
983 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
985 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
986 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
987 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
988 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
989 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
992 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
993 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
994 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
995 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
996 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
997 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
998 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
999 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1000 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1001 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1002 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1003 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1004 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1006 /* TODO: config lookups */
1008 if (display != NULL) {
1009 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1010 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1012 if (NULL == GLX_Extensions) {
1013 ERR(" GLX_Extensions returns NULL\n");
1014 } else {
1015 while (*GLX_Extensions != 0x00) {
1016 const char *Start = GLX_Extensions;
1017 char ThisExtn[256];
1019 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1020 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1021 GLX_Extensions++;
1023 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1024 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1025 if (*GLX_Extensions == ' ') GLX_Extensions++;
1031 WineD3D_ReleaseFakeGLContext();
1032 return return_value;
1035 /**********************************************************
1036 * IWineD3D implementation follows
1037 **********************************************************/
1039 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1040 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1042 /* FIXME: Set to one for now to imply the display */
1043 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1044 return 1;
1047 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1048 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1049 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1050 return WINED3D_OK;
1053 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1054 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1055 POINT pt = { -1, -1 };
1057 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1058 return NULL;
1061 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1062 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1065 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1066 of the same bpp but different resolutions */
1068 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1069 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1070 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1071 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1073 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1074 return 0;
1077 if (Adapter == 0) { /* Display */
1078 int i = 0;
1079 int j = 0;
1080 #if !defined( DEBUG_SINGLE_MODE )
1081 DEVMODEW DevModeW;
1083 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1084 j++;
1085 switch (Format)
1087 case WINED3DFMT_UNKNOWN:
1088 if (DevModeW.dmBitsPerPel == 32 ||
1089 DevModeW.dmBitsPerPel == 16) i++;
1090 break;
1091 case WINED3DFMT_X8R8G8B8:
1092 if (DevModeW.dmBitsPerPel == 32) i++;
1093 break;
1094 case WINED3DFMT_R5G6B5:
1095 if (DevModeW.dmBitsPerPel == 16) i++;
1096 break;
1097 default:
1098 /* Skip other modes as they do not match the requested format */
1099 break;
1102 #else
1103 i = 1;
1104 j = 1;
1105 #endif
1106 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1107 return i;
1108 } else {
1109 FIXME_(d3d_caps)("Adapter not primary display\n");
1111 return 0;
1114 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1115 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1116 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1117 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1119 /* Validate the parameters as much as possible */
1120 if (NULL == pMode ||
1121 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1122 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1123 return WINED3DERR_INVALIDCALL;
1126 if (Adapter == 0) { /* Display */
1127 #if !defined( DEBUG_SINGLE_MODE )
1128 DEVMODEW DevModeW;
1129 int ModeIdx = 0;
1130 int i = 0;
1131 int j = 0;
1133 /* If we are filtering to a specific format (D3D9), then need to skip
1134 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1135 just count through the ones with valid bit depths */
1136 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1137 switch (Format)
1139 case WINED3DFMT_UNKNOWN:
1140 if (DevModeW.dmBitsPerPel == 32 ||
1141 DevModeW.dmBitsPerPel == 16) i++;
1142 break;
1143 case WINED3DFMT_X8R8G8B8:
1144 if (DevModeW.dmBitsPerPel == 32) i++;
1145 break;
1146 case WINED3DFMT_R5G6B5:
1147 if (DevModeW.dmBitsPerPel == 16) i++;
1148 break;
1149 default:
1150 /* Modes that don't match what we support can get an early-out */
1151 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1152 return WINED3DERR_INVALIDCALL;
1156 if (i == 0) {
1157 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1158 return WINED3DERR_INVALIDCALL;
1160 ModeIdx = j - 1;
1162 /* Now get the display mode via the calculated index */
1163 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1164 pMode->Width = DevModeW.dmPelsWidth;
1165 pMode->Height = DevModeW.dmPelsHeight;
1166 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1167 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1168 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1170 if (Format == WINED3DFMT_UNKNOWN)
1172 switch (DevModeW.dmBitsPerPel)
1174 case 16:
1175 pMode->Format = WINED3DFMT_R5G6B5;
1176 break;
1177 case 32:
1178 pMode->Format = WINED3DFMT_X8R8G8B8;
1179 break;
1180 default:
1181 pMode->Format = WINED3DFMT_UNKNOWN;
1182 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1184 } else {
1185 pMode->Format = Format;
1187 } else {
1188 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1189 return WINED3DERR_INVALIDCALL;
1192 #else
1193 /* Return one setting of the format requested */
1194 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1195 pMode->Width = 800;
1196 pMode->Height = 600;
1197 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1198 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1199 #endif
1200 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1201 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1202 DevModeW.dmBitsPerPel);
1204 } else {
1205 FIXME_(d3d_caps)("Adapter not primary display\n");
1208 return WINED3D_OK;
1211 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1212 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1213 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1215 if (NULL == pMode ||
1216 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1217 return WINED3DERR_INVALIDCALL;
1220 if (Adapter == 0) { /* Display */
1221 int bpp = 0;
1222 DEVMODEW DevModeW;
1224 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1225 pMode->Width = DevModeW.dmPelsWidth;
1226 pMode->Height = DevModeW.dmPelsHeight;
1227 bpp = DevModeW.dmBitsPerPel;
1228 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1229 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1231 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1234 switch (bpp) {
1235 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1236 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1237 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1238 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1239 default: pMode->Format = WINED3DFMT_UNKNOWN;
1242 } else {
1243 FIXME_(d3d_caps)("Adapter not primary display\n");
1246 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1247 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1248 return WINED3D_OK;
1251 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1252 Display *display;
1253 HDC device_context;
1254 /* only works with one adapter at the moment... */
1256 /* Get the display */
1257 device_context = GetDC(0);
1258 display = get_display(device_context);
1259 ReleaseDC(0, device_context);
1260 return display;
1263 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1264 and fields being inserted in the middle, a new structure is used in place */
1265 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1266 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1267 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1269 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1271 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1272 return WINED3DERR_INVALIDCALL;
1275 if (Adapter == 0) { /* Display - only device supported for now */
1277 BOOL isGLInfoValid = This->isGLInfoValid;
1279 /* FillGLCaps updates gl_info, but we only want to store and
1280 reuse the values once we have a context which is valid. Values from
1281 a temporary context may differ from the final ones */
1282 if (!isGLInfoValid) {
1283 /* If we don't know the device settings, go query them now */
1284 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1287 /* If it worked, return the information requested */
1288 if (isGLInfoValid) {
1289 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1290 strcpy(pIdentifier->Driver, "Display");
1291 strcpy(pIdentifier->Description, "Direct3D HAL");
1293 /* Note dx8 doesn't supply a DeviceName */
1294 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1295 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1296 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1297 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1298 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1299 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1300 *(pIdentifier->SubSysId) = 0;
1301 *(pIdentifier->Revision) = 0;
1303 } else {
1305 /* If it failed, return dummy values from an NVidia driver */
1306 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1307 strcpy(pIdentifier->Driver, "Display");
1308 strcpy(pIdentifier->Description, "Direct3D HAL");
1309 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1310 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1311 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1312 /* 71.74 is a current Linux Nvidia driver version */
1313 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1314 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1315 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1316 *(pIdentifier->SubSysId) = 0;
1317 *(pIdentifier->Revision) = 0;
1320 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1321 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1322 *(pIdentifier->WHQLLevel) = 0;
1323 } else {
1324 *(pIdentifier->WHQLLevel) = 1;
1327 } else {
1328 FIXME_(d3d_caps)("Adapter not primary display\n");
1331 return WINED3D_OK;
1334 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1335 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1336 int gl_test;
1337 int rb, gb, bb, ab, type, buf_sz;
1339 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1340 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1341 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1342 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1343 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1344 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1346 switch (Format) {
1347 case WINED3DFMT_X8R8G8B8:
1348 case WINED3DFMT_R8G8B8:
1349 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1350 break;
1351 case WINED3DFMT_A8R8G8B8:
1352 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1353 break;
1354 case WINED3DFMT_A2R10G10B10:
1355 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1356 break;
1357 case WINED3DFMT_X1R5G5B5:
1358 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1359 break;
1360 case WINED3DFMT_A1R5G5B5:
1361 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1362 break;
1363 case WINED3DFMT_X4R4G4B4:
1364 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1365 break;
1366 case WINED3DFMT_R5G6B5:
1367 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1368 break;
1369 case WINED3DFMT_R3G3B2:
1370 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1371 break;
1372 case WINED3DFMT_A8P8:
1373 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1374 break;
1375 case WINED3DFMT_P8:
1376 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1377 break;
1378 default:
1379 break;
1381 return FALSE;
1382 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1383 switch (Format) {
1384 case WINED3DFMT_X8R8G8B8:
1385 case WINED3DFMT_R8G8B8:
1386 case WINED3DFMT_A8R8G8B8:
1387 case WINED3DFMT_A2R10G10B10:
1388 case WINED3DFMT_X1R5G5B5:
1389 case WINED3DFMT_A1R5G5B5:
1390 case WINED3DFMT_R5G6B5:
1391 case WINED3DFMT_R3G3B2:
1392 case WINED3DFMT_A8P8:
1393 case WINED3DFMT_P8:
1394 return TRUE;
1395 default:
1396 break;
1398 return FALSE;
1399 #endif
1402 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1403 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1404 int gl_test;
1405 int db, sb;
1407 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1408 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1410 switch (Format) {
1411 case WINED3DFMT_D16:
1412 case WINED3DFMT_D16_LOCKABLE:
1413 if (16 == db) return TRUE;
1414 break;
1415 case WINED3DFMT_D32:
1416 if (32 == db) return TRUE;
1417 break;
1418 case WINED3DFMT_D15S1:
1419 if (15 == db) return TRUE;
1420 break;
1421 case WINED3DFMT_D24S8:
1422 if (24 == db && 8 == sb) return TRUE;
1423 break;
1424 case WINED3DFMT_D24FS8:
1425 if (24 == db && 8 == sb) return TRUE;
1426 break;
1427 case WINED3DFMT_D24X8:
1428 if (24 == db) return TRUE;
1429 break;
1430 case WINED3DFMT_D24X4S4:
1431 if (24 == db && 4 == sb) return TRUE;
1432 break;
1433 case WINED3DFMT_D32F_LOCKABLE:
1434 if (32 == db) return TRUE;
1435 break;
1436 default:
1437 break;
1439 return FALSE;
1440 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1441 switch (Format) {
1442 case WINED3DFMT_D16:
1443 case WINED3DFMT_D16_LOCKABLE:
1444 case WINED3DFMT_D32:
1445 case WINED3DFMT_D15S1:
1446 case WINED3DFMT_D24S8:
1447 case WINED3DFMT_D24FS8:
1448 case WINED3DFMT_D24X8:
1449 case WINED3DFMT_D24X4S4:
1450 case WINED3DFMT_D32F_LOCKABLE:
1451 return TRUE;
1452 default:
1453 break;
1455 return FALSE;
1456 #endif
1459 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1460 WINED3DFORMAT AdapterFormat,
1461 WINED3DFORMAT RenderTargetFormat,
1462 WINED3DFORMAT DepthStencilFormat) {
1463 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1464 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1465 GLXFBConfig* cfgs = NULL;
1466 int nCfgs = 0;
1467 int it;
1469 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1470 This, Adapter,
1471 DeviceType, debug_d3ddevicetype(DeviceType),
1472 AdapterFormat, debug_d3dformat(AdapterFormat),
1473 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1474 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1476 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1477 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1478 return WINED3DERR_INVALIDCALL;
1481 if(WineD3D_CreateFakeGLContext())
1482 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1484 if (cfgs) {
1485 for (it = 0; it < nCfgs; ++it) {
1486 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1487 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1488 hr = WINED3D_OK;
1489 break ;
1493 XFree(cfgs);
1494 if(hr != WINED3D_OK)
1495 ERR("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1496 } else {
1497 ERR_(d3d_caps)("returning WINED3D_OK even so CreateFakeGLContext or glXGetFBConfigs failed\n");
1498 hr = WINED3D_OK;
1501 WineD3D_ReleaseFakeGLContext();
1503 if (hr != WINED3D_OK)
1504 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1506 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1507 return hr;
1510 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1511 WINED3DFORMAT SurfaceFormat,
1512 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1514 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1515 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1516 This,
1517 Adapter,
1518 DeviceType, debug_d3ddevicetype(DeviceType),
1519 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1520 Windowed,
1521 MultiSampleType,
1522 pQualityLevels);
1524 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1525 return WINED3DERR_INVALIDCALL;
1528 if (pQualityLevels != NULL) {
1529 static int s_single_shot = 0;
1530 if (!s_single_shot) {
1531 FIXME("Quality levels unsupported at present\n");
1532 s_single_shot = 1;
1534 *pQualityLevels = 1; /* Guess at a value! */
1537 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1538 return WINED3DERR_NOTAVAILABLE;
1541 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1542 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1544 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1545 GLXFBConfig* cfgs = NULL;
1546 int nCfgs = 0;
1547 int it;
1548 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1550 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1551 This,
1552 Adapter,
1553 CheckType, debug_d3ddevicetype(CheckType),
1554 DisplayFormat, debug_d3dformat(DisplayFormat),
1555 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1556 Windowed);
1558 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1559 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1560 return WINED3DERR_INVALIDCALL;
1563 if (WineD3D_CreateFakeGLContext()) {
1564 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1565 for (it = 0; it < nCfgs; ++it) {
1566 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1567 hr = WINED3D_OK;
1568 TRACE_(d3d_caps)("OK\n");
1569 break ;
1572 if(cfgs) XFree(cfgs);
1573 if(hr != WINED3D_OK)
1574 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1575 WineD3D_ReleaseFakeGLContext();
1578 if(hr != WINED3D_OK)
1579 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1581 return hr;
1584 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1585 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1586 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1587 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1588 This,
1589 Adapter,
1590 DeviceType, debug_d3ddevicetype(DeviceType),
1591 AdapterFormat, debug_d3dformat(AdapterFormat),
1592 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1593 RType, debug_d3dresourcetype(RType),
1594 CheckFormat, debug_d3dformat(CheckFormat));
1596 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1597 return WINED3DERR_INVALIDCALL;
1600 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1601 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1602 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1603 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1604 TRACE_(d3d_caps)("[FAILED]\n");
1605 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1608 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1609 switch (CheckFormat) {
1610 case WINED3DFMT_D16_LOCKABLE:
1611 case WINED3DFMT_D32:
1612 case WINED3DFMT_D15S1:
1613 case WINED3DFMT_D24S8:
1614 case WINED3DFMT_D24X8:
1615 case WINED3DFMT_D24X4S4:
1616 case WINED3DFMT_D16:
1617 case WINED3DFMT_L16:
1618 case WINED3DFMT_D32F_LOCKABLE:
1619 case WINED3DFMT_D24FS8:
1620 TRACE_(d3d_caps)("[OK]\n");
1621 return WINED3D_OK;
1622 default:
1623 TRACE_(d3d_caps)("[FAILED]\n");
1624 return WINED3DERR_NOTAVAILABLE;
1626 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1627 switch (CheckFormat) {
1628 case WINED3DFMT_R8G8B8:
1629 case WINED3DFMT_A8R8G8B8:
1630 case WINED3DFMT_X8R8G8B8:
1631 case WINED3DFMT_R5G6B5:
1632 case WINED3DFMT_X1R5G5B5:
1633 case WINED3DFMT_A1R5G5B5:
1634 case WINED3DFMT_A4R4G4B4:
1635 case WINED3DFMT_R3G3B2:
1636 case WINED3DFMT_X4R4G4B4:
1637 case WINED3DFMT_A8B8G8R8:
1638 case WINED3DFMT_X8B8G8R8:
1639 case WINED3DFMT_P8:
1640 TRACE_(d3d_caps)("[OK]\n");
1641 return WINED3D_OK;
1642 default:
1643 TRACE_(d3d_caps)("[FAILED]\n");
1644 return WINED3DERR_NOTAVAILABLE;
1648 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1649 switch (CheckFormat) {
1650 case WINED3DFMT_DXT1:
1651 case WINED3DFMT_DXT2:
1652 case WINED3DFMT_DXT3:
1653 case WINED3DFMT_DXT4:
1654 case WINED3DFMT_DXT5:
1655 TRACE_(d3d_caps)("[OK]\n");
1656 return WINED3D_OK;
1657 default:
1658 break; /* Avoid compiler warnings */
1662 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1664 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1666 switch (CheckFormat) {
1667 case WINED3DFMT_R16F:
1668 case WINED3DFMT_A16B16G16R16F:
1669 if (!half_pixel_support) break;
1670 case WINED3DFMT_R32F:
1671 case WINED3DFMT_A32B32G32R32F:
1672 TRACE_(d3d_caps)("[OK]\n");
1673 return WINED3D_OK;
1674 default:
1675 break; /* Avoid compiler warnings */
1679 /* This format is nothing special and it is supported perfectly.
1680 * However, ati and nvidia driver on windows do not mark this format as
1681 * supported (tested with the dxCapsViewer) and pretending to
1682 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1683 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1684 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1686 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1687 TRACE_(d3d_caps)("[FAILED]\n");
1688 return WINED3DERR_NOTAVAILABLE;
1691 switch (CheckFormat) {
1693 /*****
1694 * supported: RGB(A) formats
1696 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1697 case WINED3DFMT_A8R8G8B8:
1698 case WINED3DFMT_X8R8G8B8:
1699 case WINED3DFMT_R5G6B5:
1700 case WINED3DFMT_X1R5G5B5:
1701 case WINED3DFMT_A1R5G5B5:
1702 case WINED3DFMT_A4R4G4B4:
1703 case WINED3DFMT_R3G3B2:
1704 case WINED3DFMT_A8:
1705 case WINED3DFMT_A8R3G3B2:
1706 case WINED3DFMT_X4R4G4B4:
1707 case WINED3DFMT_A8B8G8R8:
1708 case WINED3DFMT_X8B8G8R8:
1709 case WINED3DFMT_A2R10G10B10:
1710 case WINED3DFMT_A2B10G10R10:
1711 TRACE_(d3d_caps)("[OK]\n");
1712 return WINED3D_OK;
1714 /*****
1715 * supported: Palettized
1717 case WINED3DFMT_P8:
1718 TRACE_(d3d_caps)("[OK]\n");
1719 return WINED3D_OK;
1721 /*****
1722 * Supported: (Alpha)-Luminance
1724 case WINED3DFMT_L8:
1725 case WINED3DFMT_A8L8:
1726 case WINED3DFMT_A4L4:
1727 TRACE_(d3d_caps)("[OK]\n");
1728 return WINED3D_OK;
1730 /*****
1731 * Not supported for now: Bump mapping formats
1732 * Enable some because games often fail when they are not available
1733 * and are still playable even without bump mapping
1735 case WINED3DFMT_V8U8:
1736 case WINED3DFMT_V16U16:
1737 case WINED3DFMT_L6V5U5:
1738 case WINED3DFMT_X8L8V8U8:
1739 case WINED3DFMT_Q8W8V8U8:
1740 case WINED3DFMT_W11V11U10:
1741 case WINED3DFMT_A2W10V10U10:
1742 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1743 return WINED3D_OK;
1745 /*****
1746 * DXTN Formats: Handled above
1747 * WINED3DFMT_DXT1
1748 * WINED3DFMT_DXT2
1749 * WINED3DFMT_DXT3
1750 * WINED3DFMT_DXT4
1751 * WINED3DFMT_DXT5
1754 /*****
1755 * Odd formats - not supported
1757 case WINED3DFMT_VERTEXDATA:
1758 case WINED3DFMT_INDEX16:
1759 case WINED3DFMT_INDEX32:
1760 case WINED3DFMT_Q16W16V16U16:
1761 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1762 return WINED3DERR_NOTAVAILABLE;
1764 /*****
1765 * Float formats: Not supported right now
1767 case WINED3DFMT_G16R16F:
1768 case WINED3DFMT_G32R32F:
1769 case WINED3DFMT_CxV8U8:
1770 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1771 return WINED3DERR_NOTAVAILABLE;
1773 /* Not supported */
1774 case WINED3DFMT_G16R16:
1775 case WINED3DFMT_A16B16G16R16:
1776 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1777 return WINED3DERR_NOTAVAILABLE;
1779 default:
1780 break;
1783 TRACE_(d3d_caps)("[FAILED]\n");
1784 return WINED3DERR_NOTAVAILABLE;
1787 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1788 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1789 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1791 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1792 This,
1793 Adapter,
1794 DeviceType, debug_d3ddevicetype(DeviceType),
1795 SourceFormat, debug_d3dformat(SourceFormat),
1796 TargetFormat, debug_d3dformat(TargetFormat));
1797 return WINED3D_OK;
1800 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1801 subset of a D3DCAPS9 structure. However, it has to come via a void *
1802 as the d3d8 interface cannot import the d3d9 header */
1803 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1805 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1806 int vs_selected_mode;
1807 int ps_selected_mode;
1809 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1811 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1812 return WINED3DERR_INVALIDCALL;
1815 /* FIXME: GL info should be per adapter */
1817 /* If we don't know the device settings, go query them now */
1818 if (!This->isGLInfoValid) {
1819 /* use the desktop window to fill gl caps */
1820 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1822 /* We are running off a real context, save the values */
1823 if (rc) This->isGLInfoValid = TRUE;
1825 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1827 /* This function should *not* be modifying GL caps
1828 * TODO: move the functionality where it belongs */
1829 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1831 /* ------------------------------------------------
1832 The following fields apply to both d3d8 and d3d9
1833 ------------------------------------------------ */
1834 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1835 *pCaps->AdapterOrdinal = Adapter;
1837 *pCaps->Caps = 0;
1838 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1839 WINED3DCAPS2_FULLSCREENGAMMA;
1840 *pCaps->Caps3 = 0;
1841 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1843 *pCaps->CursorCaps = 0;
1846 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1847 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1848 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1849 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1850 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1851 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1852 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1853 WINED3DDEVCAPS_PUREDEVICE |
1854 WINED3DDEVCAPS_HWRASTERIZATION |
1855 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1856 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1857 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1858 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1859 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1861 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1862 D3DPMISCCAPS_CULLCCW |
1863 D3DPMISCCAPS_CULLCW |
1864 D3DPMISCCAPS_COLORWRITEENABLE |
1865 D3DPMISCCAPS_CLIPTLVERTS |
1866 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1867 D3DPMISCCAPS_MASKZ |
1868 D3DPMISCCAPS_BLENDOP;
1869 /* TODO:
1870 D3DPMISCCAPS_NULLREFERENCE
1871 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1872 D3DPMISCCAPS_FOGANDSPECULARALPHA
1873 D3DPMISCCAPS_SEPARATEALPHABLEND
1874 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1875 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1876 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1878 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1879 #if 0
1880 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1881 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1882 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1883 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1884 #endif
1886 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1887 WINED3DPRASTERCAPS_PAT |
1888 WINED3DPRASTERCAPS_WFOG |
1889 WINED3DPRASTERCAPS_ZFOG |
1890 WINED3DPRASTERCAPS_FOGVERTEX |
1891 WINED3DPRASTERCAPS_FOGTABLE |
1892 WINED3DPRASTERCAPS_FOGRANGE |
1893 WINED3DPRASTERCAPS_STIPPLE |
1894 WINED3DPRASTERCAPS_SUBPIXEL |
1895 WINED3DPRASTERCAPS_ZTEST |
1896 WINED3DPRASTERCAPS_SCISSORTEST |
1897 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1898 WINED3DPRASTERCAPS_DEPTHBIAS;
1900 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1901 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1902 WINED3DPRASTERCAPS_ZBIAS |
1903 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1905 /* FIXME Add:
1906 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1907 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1908 WINED3DPRASTERCAPS_ANTIALIASEDGES
1909 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1910 WINED3DPRASTERCAPS_WBUFFER */
1912 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1913 D3DPCMPCAPS_EQUAL |
1914 D3DPCMPCAPS_GREATER |
1915 D3DPCMPCAPS_GREATEREQUAL |
1916 D3DPCMPCAPS_LESS |
1917 D3DPCMPCAPS_LESSEQUAL |
1918 D3DPCMPCAPS_NEVER |
1919 D3DPCMPCAPS_NOTEQUAL;
1921 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1922 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1923 D3DPBLENDCAPS_BOTHSRCALPHA |
1924 D3DPBLENDCAPS_DESTALPHA |
1925 D3DPBLENDCAPS_DESTCOLOR |
1926 D3DPBLENDCAPS_INVDESTALPHA |
1927 D3DPBLENDCAPS_INVDESTCOLOR |
1928 D3DPBLENDCAPS_INVSRCALPHA |
1929 D3DPBLENDCAPS_INVSRCCOLOR |
1930 D3DPBLENDCAPS_ONE |
1931 D3DPBLENDCAPS_SRCALPHA |
1932 D3DPBLENDCAPS_SRCALPHASAT |
1933 D3DPBLENDCAPS_SRCCOLOR |
1934 D3DPBLENDCAPS_ZERO;
1936 *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1937 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1938 D3DPBLENDCAPS_BOTHSRCALPHA |
1939 D3DPBLENDCAPS_DESTALPHA |
1940 D3DPBLENDCAPS_DESTCOLOR |
1941 D3DPBLENDCAPS_INVDESTALPHA |
1942 D3DPBLENDCAPS_INVDESTCOLOR |
1943 D3DPBLENDCAPS_INVSRCALPHA |
1944 D3DPBLENDCAPS_INVSRCCOLOR |
1945 D3DPBLENDCAPS_ONE |
1946 D3DPBLENDCAPS_SRCALPHA |
1947 D3DPBLENDCAPS_SRCALPHASAT |
1948 D3DPBLENDCAPS_SRCCOLOR |
1949 D3DPBLENDCAPS_ZERO;
1951 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1952 D3DPCMPCAPS_EQUAL |
1953 D3DPCMPCAPS_GREATER |
1954 D3DPCMPCAPS_GREATEREQUAL |
1955 D3DPCMPCAPS_LESS |
1956 D3DPCMPCAPS_LESSEQUAL |
1957 D3DPCMPCAPS_NEVER |
1958 D3DPCMPCAPS_NOTEQUAL;
1960 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1961 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1962 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1963 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1964 WINED3DPSHADECAPS_COLORFLATRGB |
1965 WINED3DPSHADECAPS_FOGFLAT |
1966 WINED3DPSHADECAPS_FOGGOURAUD |
1967 WINED3DPSHADECAPS_SPECULARFLATRGB;
1969 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1970 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1971 WINED3DPTEXTURECAPS_BORDER |
1972 WINED3DPTEXTURECAPS_MIPMAP |
1973 WINED3DPTEXTURECAPS_PROJECTED |
1974 WINED3DPTEXTURECAPS_PERSPECTIVE |
1975 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1977 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1978 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1979 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1980 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1983 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1984 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1985 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1986 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1990 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1991 WINED3DPTFILTERCAPS_MAGFPOINT |
1992 WINED3DPTFILTERCAPS_MINFLINEAR |
1993 WINED3DPTFILTERCAPS_MINFPOINT |
1994 WINED3DPTFILTERCAPS_MIPFLINEAR |
1995 WINED3DPTFILTERCAPS_MIPFPOINT |
1996 WINED3DPTFILTERCAPS_LINEAR |
1997 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1998 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1999 WINED3DPTFILTERCAPS_MIPLINEAR |
2000 WINED3DPTFILTERCAPS_MIPNEAREST |
2001 WINED3DPTFILTERCAPS_NEAREST;
2003 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2004 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2005 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2008 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2009 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2010 WINED3DPTFILTERCAPS_MAGFPOINT |
2011 WINED3DPTFILTERCAPS_MINFLINEAR |
2012 WINED3DPTFILTERCAPS_MINFPOINT |
2013 WINED3DPTFILTERCAPS_MIPFLINEAR |
2014 WINED3DPTFILTERCAPS_MIPFPOINT |
2015 WINED3DPTFILTERCAPS_LINEAR |
2016 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2017 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2018 WINED3DPTFILTERCAPS_MIPLINEAR |
2019 WINED3DPTFILTERCAPS_MIPNEAREST |
2020 WINED3DPTFILTERCAPS_NEAREST;
2022 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2023 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2024 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2026 } else
2027 *pCaps->CubeTextureFilterCaps = 0;
2029 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2030 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2031 WINED3DPTFILTERCAPS_MAGFPOINT |
2032 WINED3DPTFILTERCAPS_MINFLINEAR |
2033 WINED3DPTFILTERCAPS_MINFPOINT |
2034 WINED3DPTFILTERCAPS_MIPFLINEAR |
2035 WINED3DPTFILTERCAPS_MIPFPOINT |
2036 WINED3DPTFILTERCAPS_LINEAR |
2037 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2038 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2039 WINED3DPTFILTERCAPS_MIPLINEAR |
2040 WINED3DPTFILTERCAPS_MIPNEAREST |
2041 WINED3DPTFILTERCAPS_NEAREST;
2042 } else
2043 *pCaps->VolumeTextureFilterCaps = 0;
2045 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2046 D3DPTADDRESSCAPS_CLAMP |
2047 D3DPTADDRESSCAPS_WRAP;
2049 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2050 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2052 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2053 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2055 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2056 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2059 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2060 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2061 D3DPTADDRESSCAPS_CLAMP |
2062 D3DPTADDRESSCAPS_WRAP;
2063 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2064 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2066 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2067 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2069 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2070 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2072 } else
2073 *pCaps->VolumeTextureAddressCaps = 0;
2075 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2076 D3DLINECAPS_ZTEST;
2077 /* FIXME: Add
2078 D3DLINECAPS_BLEND
2079 D3DLINECAPS_ALPHACMP
2080 D3DLINECAPS_FOG */
2082 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2083 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2085 if(GL_SUPPORT(EXT_TEXTURE3D))
2086 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2087 else
2088 *pCaps->MaxVolumeExtent = 0;
2090 *pCaps->MaxTextureRepeat = 32768;
2091 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2092 *pCaps->MaxVertexW = 1.0;
2094 *pCaps->GuardBandLeft = 0;
2095 *pCaps->GuardBandTop = 0;
2096 *pCaps->GuardBandRight = 0;
2097 *pCaps->GuardBandBottom = 0;
2099 *pCaps->ExtentsAdjust = 0;
2101 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2102 D3DSTENCILCAPS_INCRSAT |
2103 D3DSTENCILCAPS_INVERT |
2104 D3DSTENCILCAPS_KEEP |
2105 D3DSTENCILCAPS_REPLACE |
2106 D3DSTENCILCAPS_ZERO;
2107 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2108 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2109 D3DSTENCILCAPS_INCR;
2111 if ( This->dxVersion > 8 &&
2112 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2113 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2114 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2117 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2119 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2120 D3DTEXOPCAPS_ADDSIGNED |
2121 D3DTEXOPCAPS_ADDSIGNED2X |
2122 D3DTEXOPCAPS_MODULATE |
2123 D3DTEXOPCAPS_MODULATE2X |
2124 D3DTEXOPCAPS_MODULATE4X |
2125 D3DTEXOPCAPS_SELECTARG1 |
2126 D3DTEXOPCAPS_SELECTARG2 |
2127 D3DTEXOPCAPS_DISABLE;
2129 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2130 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2131 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2132 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2133 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2134 D3DTEXOPCAPS_BLENDFACTORALPHA |
2135 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2136 D3DTEXOPCAPS_LERP |
2137 D3DTEXOPCAPS_SUBTRACT;
2139 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2140 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2141 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2142 D3DTEXOPCAPS_MULTIPLYADD |
2143 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2144 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2145 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2147 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2148 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2150 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2151 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2152 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2156 #if 0
2157 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2158 /* FIXME: Add
2159 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2160 D3DTEXOPCAPS_PREMODULATE */
2161 #endif
2163 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2164 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2165 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2166 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2170 #if 0 /* TODO: Blends support in drawprim */
2171 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2172 #else
2173 *pCaps->MaxVertexBlendMatrices = 0;
2174 #endif
2175 *pCaps->MaxVertexBlendMatrixIndex = 1;
2177 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2178 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2181 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2182 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2183 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2184 WINED3DVTXPCAPS_LOCALVIEWER |
2185 WINED3DVTXPCAPS_VERTEXFOG |
2186 WINED3DVTXPCAPS_TEXGEN;
2187 /* FIXME: Add
2188 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2190 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2191 *pCaps->MaxVertexIndex = 0xFFFFF;
2192 *pCaps->MaxStreams = MAX_STREAMS;
2193 *pCaps->MaxStreamStride = 1024;
2195 if (vs_selected_mode == SHADER_GLSL) {
2196 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2197 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2198 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2199 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2200 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2201 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2202 else
2203 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2204 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2205 } else if (vs_selected_mode == SHADER_ARB) {
2206 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2207 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2208 } else if (vs_selected_mode == SHADER_SW) {
2209 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2210 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2211 } else {
2212 *pCaps->VertexShaderVersion = 0;
2213 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2216 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2218 if (ps_selected_mode == SHADER_GLSL) {
2219 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2220 in case of GeforceFX cards. */
2221 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2222 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2223 else
2224 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2225 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2226 *pCaps->PixelShader1xMaxValue = 1.0;
2227 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2228 } else if (ps_selected_mode == SHADER_ARB) {
2229 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2230 *pCaps->PixelShader1xMaxValue = 1.0;
2231 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2232 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2233 } else if (ps_selected_mode = SHADER_SW) {
2234 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2235 *pCaps->PixelShader1xMaxValue = 1.0;
2236 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2237 } else {
2238 *pCaps->PixelShaderVersion = 0;
2239 *pCaps->PixelShader1xMaxValue = 0.0;
2240 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2243 /* ------------------------------------------------
2244 The following fields apply to d3d9 only
2245 ------------------------------------------------ */
2246 if (This->dxVersion > 8) {
2247 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2248 *pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET;
2249 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2250 *pCaps->MaxNpatchTessellationLevel = 0;
2251 *pCaps->MasterAdapterOrdinal = 0;
2252 *pCaps->AdapterOrdinalInGroup = 0;
2253 *pCaps->NumberOfAdaptersInGroup = 1;
2255 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2256 /* OpenGL supports all the formats below, perhaps not always
2257 * without conversion, but it supports them.
2258 * Further GLSL doesn't seem to have an official unsigned type so
2259 * don't advertise it yet as I'm not sure how we handle it.
2260 * We might need to add some clamping in the shader engine to
2261 * support it.
2262 * TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2263 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2264 D3DDTCAPS_UBYTE4N |
2265 D3DDTCAPS_SHORT2N |
2266 D3DDTCAPS_SHORT4N |
2267 D3DDTCAPS_FLOAT16_2 |
2268 D3DDTCAPS_FLOAT16_4;
2270 } else
2271 *pCaps->DeclTypes = 0;
2273 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2276 *pCaps->StretchRectFilterCaps = 0;
2277 *pCaps->VertexTextureFilterCaps = 0;
2279 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2280 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2281 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2282 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2283 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2284 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2285 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2287 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2288 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2289 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2290 *pCaps->VS20Caps.Caps = 0;
2291 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2292 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2293 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2295 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2296 *pCaps->MaxVertexShader30InstructionSlots = 0;
2297 } else { /* VS 1.x */
2298 *pCaps->VS20Caps.Caps = 0;
2299 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2300 *pCaps->VS20Caps.NumTemps = 0;
2301 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2303 *pCaps->MaxVShaderInstructionsExecuted = 0;
2304 *pCaps->MaxVertexShader30InstructionSlots = 0;
2307 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2308 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2309 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2311 /* 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 */
2312 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2313 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2314 D3DPS20CAPS_PREDICATION |
2315 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2316 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2317 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2318 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2319 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2320 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2322 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2323 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2324 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2325 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2326 *pCaps->PS20Caps.Caps = 0;
2327 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2328 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2329 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2330 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2332 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2333 *pCaps->MaxPixelShader30InstructionSlots = 0;
2334 } else { /* PS 1.x */
2335 *pCaps->PS20Caps.Caps = 0;
2336 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2337 *pCaps->PS20Caps.NumTemps = 0;
2338 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2339 *pCaps->PS20Caps.NumInstructionSlots = 0;
2341 *pCaps->MaxPShaderInstructionsExecuted = 0;
2342 *pCaps->MaxPixelShader30InstructionSlots = 0;
2346 return WINED3D_OK;
2350 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2351 and fields being inserted in the middle, a new structure is used in place */
2352 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2353 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2354 IUnknown *parent) {
2356 IWineD3DDeviceImpl *object = NULL;
2357 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2358 HDC hDC;
2359 HRESULT temp_result;
2361 /* Validate the adapter number */
2362 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2363 return WINED3DERR_INVALIDCALL;
2366 /* Create a WineD3DDevice object */
2367 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2368 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2369 TRACE("Created WineD3DDevice object @ %p\n", object);
2370 if (NULL == object) {
2371 return WINED3DERR_OUTOFVIDEOMEMORY;
2374 /* Set up initial COM information */
2375 object->lpVtbl = &IWineD3DDevice_Vtbl;
2376 object->ref = 1;
2377 object->wineD3D = iface;
2378 IWineD3D_AddRef(object->wineD3D);
2379 object->parent = parent;
2381 /* Set the state up as invalid until the device is fully created */
2382 object->state = WINED3DERR_DRIVERINTERNALERROR;
2384 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2385 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2387 /* Save the creation parameters */
2388 object->createParms.AdapterOrdinal = Adapter;
2389 object->createParms.DeviceType = DeviceType;
2390 object->createParms.hFocusWindow = hFocusWindow;
2391 object->createParms.BehaviorFlags = BehaviourFlags;
2393 /* Initialize other useful values */
2394 object->adapterNo = Adapter;
2395 object->devType = DeviceType;
2397 TRACE("(%p) : Creating stateblock\n", This);
2398 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2399 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2400 WINED3DSBT_INIT,
2401 (IWineD3DStateBlock **)&object->stateBlock,
2402 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2403 WARN("Failed to create stateblock\n");
2404 goto create_device_error;
2406 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2407 object->updateStateBlock = object->stateBlock;
2408 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2409 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2411 /* Setup some defaults for creating the implicit swapchain */
2412 ENTER_GL();
2413 /* FIXME: GL info should be per adapter */
2414 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2415 LEAVE_GL();
2416 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2417 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2418 object->shader_backend = &glsl_shader_backend;
2419 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2420 object->shader_backend = &arb_program_shader_backend;
2421 } else {
2422 object->shader_backend = &none_shader_backend;
2425 /* This function should *not* be modifying GL caps
2426 * TODO: move the functionality where it belongs */
2427 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2429 temp_result = allocate_shader_constants(object->updateStateBlock);
2430 if (WINED3D_OK != temp_result)
2431 return temp_result;
2433 object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2435 object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
2437 /* set the state of the device to valid */
2438 object->state = WINED3D_OK;
2440 /* Get the initial screen setup for ddraw */
2441 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2442 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2443 hDC = GetDC(0);
2444 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2445 ReleaseDC(0, hDC);
2447 /* Allocate one context for now */
2448 object->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(WineD3DContext *));
2449 object->contexts[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineD3DContext));
2450 object->numContexts = 1;
2451 object->activeContext = 0;
2453 return WINED3D_OK;
2454 create_device_error:
2456 /* Set the device state to error */
2457 object->state = WINED3DERR_DRIVERINTERNALERROR;
2459 if (object->updateStateBlock != NULL) {
2460 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2461 object->updateStateBlock = NULL;
2463 if (object->stateBlock != NULL) {
2464 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2465 object->stateBlock = NULL;
2467 if (object->render_targets[0] != NULL) {
2468 IWineD3DSurface_Release(object->render_targets[0]);
2469 object->render_targets[0] = NULL;
2471 if (object->stencilBufferTarget != NULL) {
2472 IWineD3DSurface_Release(object->stencilBufferTarget);
2473 object->stencilBufferTarget = NULL;
2475 HeapFree(GetProcessHeap(), 0, object);
2476 *ppReturnedDeviceInterface = NULL;
2477 return WINED3DERR_INVALIDCALL;
2481 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2482 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2483 IUnknown_AddRef(This->parent);
2484 *pParent = This->parent;
2485 return WINED3D_OK;
2488 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2489 IUnknown* surfaceParent;
2490 TRACE("(%p) call back\n", pSurface);
2492 /* Now, release the parent, which will take care of cleaning up the surface for us */
2493 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2494 IUnknown_Release(surfaceParent);
2495 return IUnknown_Release(surfaceParent);
2498 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2499 IUnknown* volumeParent;
2500 TRACE("(%p) call back\n", pVolume);
2502 /* Now, release the parent, which will take care of cleaning up the volume for us */
2503 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2504 IUnknown_Release(volumeParent);
2505 return IUnknown_Release(volumeParent);
2508 /**********************************************************
2509 * IWineD3D VTbl follows
2510 **********************************************************/
2512 const IWineD3DVtbl IWineD3D_Vtbl =
2514 /* IUnknown */
2515 IWineD3DImpl_QueryInterface,
2516 IWineD3DImpl_AddRef,
2517 IWineD3DImpl_Release,
2518 /* IWineD3D */
2519 IWineD3DImpl_GetParent,
2520 IWineD3DImpl_GetAdapterCount,
2521 IWineD3DImpl_RegisterSoftwareDevice,
2522 IWineD3DImpl_GetAdapterMonitor,
2523 IWineD3DImpl_GetAdapterModeCount,
2524 IWineD3DImpl_EnumAdapterModes,
2525 IWineD3DImpl_GetAdapterDisplayMode,
2526 IWineD3DImpl_GetAdapterIdentifier,
2527 IWineD3DImpl_CheckDeviceMultiSampleType,
2528 IWineD3DImpl_CheckDepthStencilMatch,
2529 IWineD3DImpl_CheckDeviceType,
2530 IWineD3DImpl_CheckDeviceFormat,
2531 IWineD3DImpl_CheckDeviceFormatConversion,
2532 IWineD3DImpl_GetDeviceCaps,
2533 IWineD3DImpl_CreateDevice