oledlg: Call the hook proc if present.
[wine/hacks.git] / dlls / wined3d / directx.c
blob25839b53e4fc051c904429b24111d0b34573a6d6
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 "wined3d_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
34 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
35 #define GLINFO_LOCATION This->gl_info
37 /**********************************************************
38 * Utility functions follow
39 **********************************************************/
41 /* x11drv GDI escapes */
42 #define X11DRV_ESCAPE 6789
43 enum x11drv_escape_codes
45 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
46 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
47 X11DRV_GET_FONT, /* get current X font for a DC */
50 /* retrieve the X display to use on a given DC */
51 inline static Display *get_display( HDC hdc )
53 Display *display;
54 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
56 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
57 sizeof(display), (LPSTR)&display )) display = NULL;
58 return display;
61 /* lookup tables */
62 int minLookup[MAX_LOOKUPS];
63 int maxLookup[MAX_LOOKUPS];
64 DWORD *stateLookup[MAX_LOOKUPS];
66 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
75 static WineD3D_Context* WineD3D_CreateFakeGLContext(void) {
76 static WineD3D_Context ctx = { NULL, NULL, NULL, 0, 0 };
77 WineD3D_Context* ret = NULL;
79 if (glXGetCurrentContext() == NULL) {
80 BOOL gotContext = FALSE;
81 BOOL created = FALSE;
82 XVisualInfo template;
83 HDC device_context;
84 Visual* visual;
85 BOOL failed = FALSE;
86 int num;
87 XWindowAttributes win_attr;
88 TRACE_(d3d_caps)("Creating Fake GL Context\n");
90 ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
92 /* Get the display */
93 device_context = GetDC(0);
94 ctx.display = get_display(device_context);
95 ReleaseDC(0, device_context);
97 /* Get the X visual */
98 ENTER_GL();
99 if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
100 visual = win_attr.visual;
101 } else {
102 visual = DefaultVisual(ctx.display, DefaultScreen(ctx.display));
104 template.visualid = XVisualIDFromVisual(visual);
105 ctx.visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
106 if (ctx.visInfo == NULL) {
107 LEAVE_GL();
108 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
109 failed = TRUE;
112 /* Create a GL context */
113 if (!failed) {
114 ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
116 if (ctx.glCtx == NULL) {
117 LEAVE_GL();
118 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
119 failed = TRUE;
123 /* Make it the current GL context */
124 if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
125 glXDestroyContext(ctx.display, ctx.glCtx);
126 LEAVE_GL();
127 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
128 failed = TRUE;
131 /* It worked! Wow... */
132 if (!failed) {
133 gotContext = TRUE;
134 created = TRUE;
135 ret = &ctx;
136 } else {
137 ret = NULL;
140 } else {
141 if (ctx.ref > 0) ret = &ctx;
144 if (NULL != ret) InterlockedIncrement(&ret->ref);
145 return ret;
148 static void WineD3D_ReleaseFakeGLContext(WineD3D_Context* ctx) {
149 /* If we created a dummy context, throw it away */
150 if (NULL != ctx) {
151 if (0 == InterlockedDecrement(&ctx->ref)) {
152 glXMakeCurrent(ctx->display, None, NULL);
153 glXDestroyContext(ctx->display, ctx->glCtx);
154 ctx->display = NULL;
155 ctx->glCtx = NULL;
156 LEAVE_GL();
161 /**********************************************************
162 * IUnknown parts follows
163 **********************************************************/
165 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
169 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
170 if (IsEqualGUID(riid, &IID_IUnknown)
171 || IsEqualGUID(riid, &IID_IWineD3DBase)
172 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
173 IUnknown_AddRef(iface);
174 *ppobj = This;
175 return S_OK;
177 *ppobj = NULL;
178 return E_NOINTERFACE;
181 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
182 IWineD3DImpl *This = (IWineD3DImpl *)iface;
183 ULONG refCount = InterlockedIncrement(&This->ref);
185 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
186 return refCount;
189 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
190 IWineD3DImpl *This = (IWineD3DImpl *)iface;
191 ULONG ref;
192 TRACE("(%p) : Releasing from %d\n", This, This->ref);
193 ref = InterlockedDecrement(&This->ref);
194 if (ref == 0) {
195 HeapFree(GetProcessHeap(), 0, This);
198 return ref;
201 /* Set the shader type for this device, depending on the given capabilities,
202 * the device type, and the user preferences in wined3d_settings */
204 static void select_shader_mode(
205 WineD3D_GL_Info *gl_info,
206 WINED3DDEVTYPE DeviceType,
207 int* ps_selected,
208 int* vs_selected) {
210 /* Give priority to user disable/emulation request.
211 * Then respect REF device for software.
212 * Then check capabilities for hardware, and fallback to software */
214 if (wined3d_settings.vs_mode == VS_NONE) {
215 *vs_selected = SHADER_NONE;
216 } else if (DeviceType == WINED3DDEVTYPE_REF || wined3d_settings.vs_mode == VS_SW) {
217 *vs_selected = SHADER_SW;
218 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
219 *vs_selected = SHADER_GLSL;
220 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
221 *vs_selected = SHADER_ARB;
222 } else {
223 *vs_selected = SHADER_SW;
226 /* Fallback to SHADER_NONE where software pixel shaders should be used */
227 if (wined3d_settings.ps_mode == PS_NONE) {
228 *ps_selected = SHADER_NONE;
229 } else if (DeviceType == WINED3DDEVTYPE_REF) {
230 *ps_selected = SHADER_NONE;
231 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
232 *ps_selected = SHADER_GLSL;
233 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
234 *ps_selected = SHADER_ARB;
235 } else {
236 *ps_selected = SHADER_NONE;
240 /** Select the number of report maximum shader constants based on the selected shader modes */
241 void select_shader_max_constants(
242 int ps_selected_mode,
243 int vs_selected_mode,
244 WineD3D_GL_Info *gl_info) {
246 switch (vs_selected_mode) {
247 case SHADER_GLSL:
248 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
249 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I - 1;
250 break;
251 case SHADER_ARB:
252 /* We have to subtract any other PARAMs that we might use in our shader programs.
253 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
254 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
255 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
256 break;
257 case SHADER_SW:
258 gl_info->max_vshader_constantsF = 96; /* TODO: Fixup software shaders */
259 break;
260 default:
261 gl_info->max_vshader_constantsF = 0;
262 break;
265 switch (ps_selected_mode) {
266 case SHADER_GLSL:
267 /* Subtract the other potential uniforms from the max available (bools & ints) */
268 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
269 break;
270 case SHADER_ARB:
271 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
272 break;
273 case SHADER_SW:
274 gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */
275 break;
276 default:
277 gl_info->max_pshader_constantsF = 0;
278 break;
282 /**********************************************************
283 * IWineD3D parts follows
284 **********************************************************/
286 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
287 IWineD3DImpl *This = (IWineD3DImpl *)iface;
288 WineD3D_GL_Info *gl_info = &This->gl_info;
290 const char *GL_Extensions = NULL;
291 const char *GLX_Extensions = NULL;
292 const char *gl_string = NULL;
293 const char *gl_string_cursor = NULL;
294 GLint gl_max;
295 GLfloat gl_floatv[2];
296 Bool test = 0;
297 int major, minor;
298 WineD3D_Context *fake_ctx = NULL;
299 BOOL gotContext = FALSE;
300 int i;
302 /* Make sure that we've got a context */
303 if (glXGetCurrentContext() == NULL) {
304 /* TODO: CreateFakeGLContext should really take a display as a parameter */
305 fake_ctx = WineD3D_CreateFakeGLContext();
306 if (NULL != fake_ctx) gotContext = TRUE;
307 } else {
308 gotContext = TRUE;
311 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
313 gl_string = (const char *) glGetString(GL_RENDERER);
314 if (NULL == gl_string)
315 gl_string = "None";
316 strcpy(gl_info->gl_renderer, gl_string);
318 /* Fill in the GL info retrievable depending on the display */
319 if (NULL != display) {
320 test = glXQueryVersion(display, &major, &minor);
321 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
322 } else {
323 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
325 gl_string = (const char *) glGetString(GL_VENDOR);
327 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
328 if (gl_string != NULL) {
329 /* Fill in the GL vendor */
330 if (strstr(gl_string, "NVIDIA")) {
331 gl_info->gl_vendor = VENDOR_NVIDIA;
332 } else if (strstr(gl_string, "ATI")) {
333 gl_info->gl_vendor = VENDOR_ATI;
334 } else if (strstr(gl_string, "Intel(R)") ||
335 strstr(gl_info->gl_renderer, "Intel(R)")) {
336 gl_info->gl_vendor = VENDOR_INTEL;
337 } else if (strstr(gl_string, "Mesa")) {
338 gl_info->gl_vendor = VENDOR_MESA;
339 } else {
340 gl_info->gl_vendor = VENDOR_WINE;
342 } else {
343 gl_info->gl_vendor = VENDOR_WINE;
347 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
349 /* Parse the GL_VERSION field into major and minor information */
350 gl_string = (const char *) glGetString(GL_VERSION);
351 if (gl_string != NULL) {
353 switch (gl_info->gl_vendor) {
354 case VENDOR_NVIDIA:
355 gl_string_cursor = strstr(gl_string, "NVIDIA");
356 if (!gl_string_cursor) {
357 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
358 break;
361 gl_string_cursor = strstr(gl_string_cursor, " ");
362 if (!gl_string_cursor) {
363 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
364 break;
367 while (*gl_string_cursor == ' ') {
368 ++gl_string_cursor;
371 if (!*gl_string_cursor) {
372 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
373 break;
376 major = atoi(gl_string_cursor);
377 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
378 ++gl_string_cursor;
381 if (*gl_string_cursor++ != '.') {
382 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
383 break;
386 minor = atoi(gl_string_cursor);
387 minor = major*100+minor;
388 major = 10;
390 break;
392 case VENDOR_ATI:
393 major = minor = 0;
394 gl_string_cursor = strchr(gl_string, '-');
395 if (gl_string_cursor) {
396 int error = 0;
397 gl_string_cursor++;
399 /* Check if version number is of the form x.y.z */
400 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
401 error = 1;
402 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
403 error = 1;
404 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
405 error = 1;
406 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
407 error = 1;
409 /* Mark version number as malformed */
410 if (error)
411 gl_string_cursor = 0;
414 if (!gl_string_cursor)
415 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
416 else {
417 major = *gl_string_cursor - '0';
418 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
420 break;
422 case VENDOR_INTEL:
423 case VENDOR_MESA:
424 gl_string_cursor = strstr(gl_string, "Mesa");
425 gl_string_cursor = strstr(gl_string_cursor, " ");
426 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
427 if (*gl_string_cursor) {
428 char tmp[16];
429 int cursor = 0;
431 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
432 tmp[cursor++] = *gl_string_cursor;
433 ++gl_string_cursor;
435 tmp[cursor] = 0;
436 major = atoi(tmp);
438 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
439 ++gl_string_cursor;
441 cursor = 0;
442 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
443 tmp[cursor++] = *gl_string_cursor;
444 ++gl_string_cursor;
446 tmp[cursor] = 0;
447 minor = atoi(tmp);
449 break;
451 default:
452 major = 0;
453 minor = 9;
455 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
456 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
459 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
462 * Initialize openGL extension related variables
463 * with Default values
465 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
466 gl_info->max_buffers = 1;
467 gl_info->max_textures = 1;
468 gl_info->max_texture_stages = 1;
469 gl_info->max_samplers = 1;
470 gl_info->max_sampler_stages = 1;
471 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
472 gl_info->ps_arb_max_temps = 0;
473 gl_info->ps_arb_max_instructions = 0;
474 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
475 gl_info->vs_arb_max_temps = 0;
476 gl_info->vs_arb_max_instructions = 0;
477 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
478 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
479 gl_info->vs_glsl_constantsF = 0;
480 gl_info->ps_glsl_constantsF = 0;
481 gl_info->vs_arb_constantsF = 0;
482 gl_info->ps_arb_constantsF = 0;
484 /* Now work out what GL support this card really has */
485 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
486 GL_EXT_FUNCS_GEN;
487 GLX_EXT_FUNCS_GEN;
488 #undef USE_GL_FUNC
490 /* Retrieve opengl defaults */
491 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
492 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
493 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
495 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
496 gl_info->max_lights = gl_max;
497 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
499 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
500 gl_info->max_texture_size = gl_max;
501 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
503 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
504 gl_info->max_pointsize = gl_floatv[1];
505 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
507 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
508 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
509 TRACE_(d3d_caps)("GL_Extensions reported:\n");
511 if (NULL == GL_Extensions) {
512 ERR(" GL_Extensions returns NULL\n");
513 } else {
514 while (*GL_Extensions != 0x00) {
515 const char *Start = GL_Extensions;
516 char ThisExtn[256];
518 memset(ThisExtn, 0x00, sizeof(ThisExtn));
519 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
520 GL_Extensions++;
522 memcpy(ThisExtn, Start, (GL_Extensions - Start));
523 TRACE_(d3d_caps)("- %s\n", ThisExtn);
526 * ARB
528 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
529 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
530 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
531 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
532 gl_info->max_buffers = gl_max;
533 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
534 gl_info->ps_arb_version = PS_VERSION_11;
535 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
536 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
537 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
538 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
539 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
540 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
541 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
542 gl_info->ps_arb_constantsF = gl_max;
543 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
544 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
545 gl_info->ps_arb_max_temps = gl_max;
546 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
547 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
548 gl_info->ps_arb_max_instructions = gl_max;
549 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
550 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
551 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
552 gl_max /= 4;
553 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
554 gl_info->ps_glsl_constantsF = gl_max;
555 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
556 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
557 gl_info->supported[ARB_IMAGING] = TRUE;
558 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
559 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
560 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
561 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
562 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
563 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
564 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
565 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
566 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
567 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
568 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
569 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
570 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
571 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
572 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
573 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
574 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
575 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
576 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
577 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
578 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
579 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
580 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
581 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
582 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
583 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
584 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
585 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
586 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
587 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
588 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
589 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
590 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
591 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
592 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
593 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
594 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
595 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
596 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
597 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
598 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
599 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
600 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
601 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
602 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
603 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
604 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
605 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
606 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
607 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
608 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
609 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
610 gl_info->vs_arb_version = VS_VERSION_11;
611 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
612 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
613 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
614 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
615 gl_info->vs_arb_constantsF = gl_max;
616 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
617 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
618 gl_info->vs_arb_max_temps = gl_max;
619 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
620 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
621 gl_info->vs_arb_max_instructions = gl_max;
622 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
623 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
624 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
625 gl_max /= 4;
626 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
627 gl_info->vs_glsl_constantsF = gl_max;
628 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
629 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
630 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
631 gl_info->max_blends = gl_max;
632 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
633 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
634 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
635 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
636 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
637 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
638 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
639 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
640 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
641 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
643 * EXT
645 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
646 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
647 gl_info->supported[EXT_FOG_COORD] = TRUE;
648 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
649 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
650 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
651 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
652 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
653 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
654 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
655 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
656 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
657 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
658 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
659 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
660 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
661 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
662 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
663 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
664 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
665 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
666 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
667 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
668 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
669 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
670 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
671 gl_info->supported[EXT_TEXTURE3D] = TRUE;
672 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
673 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
674 gl_info->max_texture3d_size = gl_max;
675 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
676 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
677 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
678 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
679 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
680 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
681 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
682 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
683 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
684 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
685 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
686 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
687 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
688 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
689 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
690 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
691 gl_info->max_anisotropy = gl_max;
692 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
693 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
694 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
695 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
696 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
697 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
698 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
699 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
700 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
703 * NVIDIA
705 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
706 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
707 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
708 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
709 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
710 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
711 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
712 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
713 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
714 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
715 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
716 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
717 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
718 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
719 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
720 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
721 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
722 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
723 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
724 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
725 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
726 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
727 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
728 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
729 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
730 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
731 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
732 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
733 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
734 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
735 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
736 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
737 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
738 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
739 gl_info->vs_nv_version = VS_VERSION_30;
740 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
741 gl_info->vs_nv_version = VS_VERSION_20;
742 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
743 gl_info->vs_nv_version = VS_VERSION_11;
744 else
745 gl_info->vs_nv_version = VS_VERSION_10;
746 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
747 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
750 * ATI
752 /** TODO */
753 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
754 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
755 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
756 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
757 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
758 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
759 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
760 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
761 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
762 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
763 gl_info->vs_ati_version = VS_VERSION_11;
764 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
765 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
769 if (*GL_Extensions == ' ') GL_Extensions++;
772 checkGLcall("extension detection\n");
774 /* In some cases the number of texture stages can be larger than the number
775 * of samplers. The GF4 for example can use only 2 samplers (no fragment
776 * shaders), but 8 texture stages (register combiners). */
777 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
779 /* We can only use NP2_NATIVE when the hardware supports it. */
780 if (wined3d_settings.nonpower2_mode == NP2_NATIVE && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
781 WARN_(d3d_caps)("GL_ARB_texture_non_power_of_two not supported, falling back to NP2_NONE NPOT mode.\n");
782 wined3d_settings.nonpower2_mode = NP2_NONE;
785 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
786 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
787 * in case of the latest videocards in the number of pixel/vertex pipelines.
789 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
790 * rendering. Various games use this information to get a rough estimation of the features of the card
791 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
792 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
793 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
794 * not the PCI id.
796 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
797 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
798 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
799 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
800 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
801 * is used for rendering which is not always the case). This would work but it is not very portable. Second
802 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
803 * is limited.
805 * As said most games only use the PCI id to get an indication of the capabilities of the card.
806 * It doesn't really matter if the given id is the correct one if we return the id of a card with
807 * similar 3d features.
809 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
810 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
811 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
812 * won't pass we return a default card. This way is better than maintaining a full card database as even
813 * without a full database we can return a card with similar features. Second the size of the database
814 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
815 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
816 * to distinguishes between different models from that family.
818 switch (gl_info->gl_vendor) {
819 case VENDOR_NVIDIA:
820 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
821 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
823 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
824 if (strstr(gl_info->gl_renderer, "7800") ||
825 strstr(gl_info->gl_renderer, "7900") ||
826 strstr(gl_info->gl_renderer, "7950") ||
827 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
828 strstr(gl_info->gl_renderer, "Quadro FX 5"))
829 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
830 else if(strstr(gl_info->gl_renderer, "6800") ||
831 strstr(gl_info->gl_renderer, "7600"))
832 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
833 else if(strstr(gl_info->gl_renderer, "6600") ||
834 strstr(gl_info->gl_renderer, "6610") ||
835 strstr(gl_info->gl_renderer, "6700"))
836 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
837 else
838 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
839 } else if(WINE_D3D9_CAPABLE(gl_info)) {
840 if (strstr(gl_info->gl_renderer, "5800") ||
841 strstr(gl_info->gl_renderer, "5900") ||
842 strstr(gl_info->gl_renderer, "5950") ||
843 strstr(gl_info->gl_renderer, "Quadro FX"))
844 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
845 else if(strstr(gl_info->gl_renderer, "5600") ||
846 strstr(gl_info->gl_renderer, "5650") ||
847 strstr(gl_info->gl_renderer, "5700") ||
848 strstr(gl_info->gl_renderer, "5750"))
849 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
850 else
851 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
852 } else if(WINE_D3D8_CAPABLE(gl_info)) {
853 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
854 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
855 else
856 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
857 } else if(WINE_D3D7_CAPABLE(gl_info)) {
858 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
859 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
860 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
861 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
862 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
863 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
864 else
865 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
866 } else {
867 if (strstr(gl_info->gl_renderer, "TNT2"))
868 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
869 else
870 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
872 break;
873 case VENDOR_ATI:
874 if(WINE_D3D9_CAPABLE(gl_info)) {
875 /* Radeon R5xx */
876 if (strstr(gl_info->gl_renderer, "X1600") ||
877 strstr(gl_info->gl_renderer, "X1800") ||
878 strstr(gl_info->gl_renderer, "X1900") ||
879 strstr(gl_info->gl_renderer, "X1950"))
880 gl_info->gl_card = CARD_ATI_RADEON_X1600;
881 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
882 else if(strstr(gl_info->gl_renderer, "X700") ||
883 strstr(gl_info->gl_renderer, "X800") ||
884 strstr(gl_info->gl_renderer, "X850") ||
885 strstr(gl_info->gl_renderer, "X1300") ||
886 strstr(gl_info->gl_renderer, "X1400"))
887 gl_info->gl_card = CARD_ATI_RADEON_X700;
888 /* Radeon R3xx */
889 else
890 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
891 } else if(WINE_D3D8_CAPABLE(gl_info)) {
892 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
893 } else if(WINE_D3D7_CAPABLE(gl_info)) {
894 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
895 } else
896 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
897 break;
898 case VENDOR_INTEL:
899 if (strstr(gl_info->gl_renderer, "915GM")) {
900 gl_info->gl_card = CARD_INTEL_I915GM;
901 } else if (strstr(gl_info->gl_renderer, "915G")) {
902 gl_info->gl_card = CARD_INTEL_I915G;
903 } else if (strstr(gl_info->gl_renderer, "865G")) {
904 gl_info->gl_card = CARD_INTEL_I865G;
905 } else if (strstr(gl_info->gl_renderer, "855G")) {
906 gl_info->gl_card = CARD_INTEL_I855G;
907 } else if (strstr(gl_info->gl_renderer, "830G")) {
908 gl_info->gl_card = CARD_INTEL_I830G;
909 } else {
910 gl_info->gl_card = CARD_INTEL_I915G;
912 break;
913 case VENDOR_MESA:
914 case VENDOR_WINE:
915 default:
916 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
917 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
918 * them a good generic choice.
920 gl_info->gl_vendor = VENDOR_NVIDIA;
921 if(WINE_D3D9_CAPABLE(gl_info))
922 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
923 else if(WINE_D3D8_CAPABLE(gl_info))
924 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
925 else if(WINE_D3D7_CAPABLE(gl_info))
926 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
927 else if(WINE_D3D6_CAPABLE(gl_info))
928 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
929 else
930 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
932 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
934 /* Load all the lookup tables
935 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
936 minLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_WRAP;
937 maxLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_MIRRORONCE;
939 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
940 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
943 for (i = 0; i < MAX_LOOKUPS; i++) {
944 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
947 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
948 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
949 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
950 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
951 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
952 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
953 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
954 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
955 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
956 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
958 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
959 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
960 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
961 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
962 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
965 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
966 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
967 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
968 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
969 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
970 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
971 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
972 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
973 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
974 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
975 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
976 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
977 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
979 /* TODO: config lookups */
981 if (display != NULL) {
982 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
983 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
985 if (NULL == GLX_Extensions) {
986 ERR(" GLX_Extensions returns NULL\n");
987 } else {
988 while (*GLX_Extensions != 0x00) {
989 const char *Start = GLX_Extensions;
990 char ThisExtn[256];
992 memset(ThisExtn, 0x00, sizeof(ThisExtn));
993 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
994 GLX_Extensions++;
996 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
997 TRACE_(d3d_caps)("- %s\n", ThisExtn);
998 if (*GLX_Extensions == ' ') GLX_Extensions++;
1003 /* If we created a dummy context, throw it away */
1004 if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
1006 /* Only save the values obtained when a display is provided */
1007 if (fake_ctx == NULL) {
1008 return TRUE;
1009 } else {
1010 return FALSE;
1014 /**********************************************************
1015 * IWineD3D implementation follows
1016 **********************************************************/
1018 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1019 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1021 /* FIXME: Set to one for now to imply the display */
1022 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1023 return 1;
1026 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1027 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1028 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1029 return WINED3D_OK;
1032 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1033 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1034 POINT pt = { -1, -1 };
1036 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1037 return NULL;
1040 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1041 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1044 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1045 of the same bpp but different resolutions */
1047 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1048 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1049 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1050 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1052 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1053 return 0;
1056 if (Adapter == 0) { /* Display */
1057 int i = 0;
1058 int j = 0;
1059 #if !defined( DEBUG_SINGLE_MODE )
1060 DEVMODEW DevModeW;
1062 /* Work out the current screen bpp */
1063 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1064 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1065 DeleteDC(hdc);
1067 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1068 j++;
1069 switch (Format)
1071 case WINED3DFMT_UNKNOWN:
1072 i++;
1073 break;
1074 case WINED3DFMT_X8R8G8B8:
1075 case WINED3DFMT_A8R8G8B8:
1076 if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
1077 if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
1078 break;
1079 case WINED3DFMT_X1R5G5B5:
1080 case WINED3DFMT_A1R5G5B5:
1081 case WINED3DFMT_R5G6B5:
1082 if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
1083 break;
1084 default:
1085 /* Skip other modes as they do not match the requested format */
1086 break;
1089 #else
1090 i = 1;
1091 j = 1;
1092 #endif
1093 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1094 return i;
1095 } else {
1096 FIXME_(d3d_caps)("Adapter not primary display\n");
1098 return 0;
1101 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1102 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1103 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1104 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1106 /* Validate the parameters as much as possible */
1107 if (NULL == pMode ||
1108 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1109 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1110 return WINED3DERR_INVALIDCALL;
1113 if (Adapter == 0) { /* Display */
1114 int bpp;
1115 #if !defined( DEBUG_SINGLE_MODE )
1116 DEVMODEW DevModeW;
1117 int ModeIdx = 0;
1119 /* Work out the current screen bpp */
1120 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1121 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1122 DeleteDC(hdc);
1124 /* If we are filtering to a specific format, then need to skip all unrelated
1125 modes, but if mode is irrelevant, then we can use the index directly */
1126 if (Format == WINED3DFMT_UNKNOWN)
1128 ModeIdx = Mode;
1129 } else {
1130 int i = 0;
1131 int j = 0;
1132 DEVMODEW DevModeWtmp;
1135 while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
1136 j++;
1137 switch (Format)
1139 case WINED3DFMT_UNKNOWN:
1140 i++;
1141 break;
1142 case WINED3DFMT_X8R8G8B8:
1143 case WINED3DFMT_A8R8G8B8:
1144 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
1145 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
1146 break;
1147 case WINED3DFMT_X1R5G5B5:
1148 case WINED3DFMT_A1R5G5B5:
1149 case WINED3DFMT_R5G6B5:
1150 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
1151 break;
1152 default:
1153 /* Skip other modes as they do not match requested format */
1154 break;
1157 ModeIdx = j;
1160 /* Now get the display mode via the calculated index */
1161 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
1163 pMode->Width = DevModeW.dmPelsWidth;
1164 pMode->Height = DevModeW.dmPelsHeight;
1165 bpp = min(DevModeW.dmBitsPerPel, bpp);
1166 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1167 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1169 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1172 if (Format == WINED3DFMT_UNKNOWN)
1174 switch (bpp) {
1175 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1176 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1177 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
1178 case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break;
1179 default: pMode->Format = WINED3DFMT_UNKNOWN;
1181 } else {
1182 pMode->Format = Format;
1185 else
1187 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1188 return WINED3DERR_INVALIDCALL;
1191 #else
1192 /* Return one setting of the format requested */
1193 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1194 pMode->Width = 800;
1195 pMode->Height = 600;
1196 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1197 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_A8R8G8B8 : Format;
1198 bpp = 32;
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), bpp);
1203 } else {
1204 FIXME_(d3d_caps)("Adapter not primary display\n");
1207 return WINED3D_OK;
1210 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1211 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1212 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1214 if (NULL == pMode ||
1215 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1216 return WINED3DERR_INVALIDCALL;
1219 if (Adapter == 0) { /* Display */
1220 int bpp = 0;
1221 DEVMODEW DevModeW;
1223 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1224 pMode->Width = DevModeW.dmPelsWidth;
1225 pMode->Height = DevModeW.dmPelsHeight;
1226 bpp = DevModeW.dmBitsPerPel;
1227 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1228 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1230 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1233 switch (bpp) {
1234 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1235 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1236 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1237 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1238 default: pMode->Format = WINED3DFMT_UNKNOWN;
1241 } else {
1242 FIXME_(d3d_caps)("Adapter not primary display\n");
1245 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1246 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1247 return WINED3D_OK;
1250 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1251 Display *display;
1252 HDC device_context;
1253 /* only works with one adapter at the moment... */
1255 /* Get the display */
1256 device_context = GetDC(0);
1257 display = get_display(device_context);
1258 ReleaseDC(0, device_context);
1259 return display;
1262 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1263 and fields being inserted in the middle, a new structure is used in place */
1264 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1265 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1266 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1268 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1270 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1271 return WINED3DERR_INVALIDCALL;
1274 if (Adapter == 0) { /* Display - only device supported for now */
1276 BOOL isGLInfoValid = This->isGLInfoValid;
1278 /* FillGLCaps updates gl_info, but we only want to store and
1279 reuse the values once we have a context which is valid. Values from
1280 a temporary context may differ from the final ones */
1281 if (!isGLInfoValid) {
1282 WineD3D_Context *fake_ctx = NULL;
1283 if (glXGetCurrentContext() == NULL) fake_ctx = WineD3D_CreateFakeGLContext();
1284 /* If we don't know the device settings, go query them now */
1285 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1286 if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
1289 /* If it worked, return the information requested */
1290 if (isGLInfoValid) {
1291 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1292 strcpy(pIdentifier->Driver, "Display");
1293 strcpy(pIdentifier->Description, "Direct3D HAL");
1295 /* Note dx8 doesn't supply a DeviceName */
1296 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1297 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1298 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1299 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1300 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1301 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1302 *(pIdentifier->SubSysId) = 0;
1303 *(pIdentifier->Revision) = 0;
1305 } else {
1307 /* If it failed, return dummy values from an NVidia driver */
1308 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1309 strcpy(pIdentifier->Driver, "Display");
1310 strcpy(pIdentifier->Description, "Direct3D HAL");
1311 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1312 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1313 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1314 /* 71.74 is a current Linux Nvidia driver version */
1315 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1316 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1317 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1318 *(pIdentifier->SubSysId) = 0;
1319 *(pIdentifier->Revision) = 0;
1322 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1323 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1324 *(pIdentifier->WHQLLevel) = 0;
1325 } else {
1326 *(pIdentifier->WHQLLevel) = 1;
1329 } else {
1330 FIXME_(d3d_caps)("Adapter not primary display\n");
1333 return WINED3D_OK;
1336 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1337 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1338 int gl_test;
1339 int rb, gb, bb, ab, type, buf_sz;
1341 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE, &rb);
1342 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
1343 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE, &bb);
1344 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
1345 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
1346 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1348 switch (Format) {
1349 case WINED3DFMT_X8R8G8B8:
1350 case WINED3DFMT_R8G8B8:
1351 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1352 break;
1353 case WINED3DFMT_A8R8G8B8:
1354 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1355 break;
1356 case WINED3DFMT_A2R10G10B10:
1357 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1358 break;
1359 case WINED3DFMT_X1R5G5B5:
1360 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1361 break;
1362 case WINED3DFMT_A1R5G5B5:
1363 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1364 break;
1365 case WINED3DFMT_X4R4G4B4:
1366 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1367 break;
1368 case WINED3DFMT_R5G6B5:
1369 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1370 break;
1371 case WINED3DFMT_R3G3B2:
1372 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1373 break;
1374 case WINED3DFMT_A8P8:
1375 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1376 break;
1377 case WINED3DFMT_P8:
1378 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1379 break;
1380 default:
1381 ERR("unsupported format %s\n", debug_d3dformat(Format));
1382 break;
1384 return FALSE;
1385 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1386 switch (Format) {
1387 case WINED3DFMT_X8R8G8B8:
1388 case WINED3DFMT_R8G8B8:
1389 case WINED3DFMT_A8R8G8B8:
1390 case WINED3DFMT_A2R10G10B10:
1391 case WINED3DFMT_X1R5G5B5:
1392 case WINED3DFMT_A1R5G5B5:
1393 case WINED3DFMT_R5G6B5:
1394 case WINED3DFMT_R3G3B2:
1395 case WINED3DFMT_A8P8:
1396 case WINED3DFMT_P8:
1397 return TRUE;
1398 default:
1399 ERR("unsupported format %s\n", debug_d3dformat(Format));
1400 break;
1402 return FALSE;
1403 #endif
1406 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1407 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1408 int gl_test;
1409 int db, sb;
1411 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
1412 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
1414 switch (Format) {
1415 case WINED3DFMT_D16:
1416 case WINED3DFMT_D16_LOCKABLE:
1417 if (16 == db) return TRUE;
1418 break;
1419 case WINED3DFMT_D32:
1420 if (32 == db) return TRUE;
1421 break;
1422 case WINED3DFMT_D15S1:
1423 if (15 == db) return TRUE;
1424 break;
1425 case WINED3DFMT_D24S8:
1426 if (24 == db && 8 == sb) return TRUE;
1427 break;
1428 case WINED3DFMT_D24FS8:
1429 if (24 == db && 8 == sb) return TRUE;
1430 break;
1431 case WINED3DFMT_D24X8:
1432 if (24 == db) return TRUE;
1433 break;
1434 case WINED3DFMT_D24X4S4:
1435 if (24 == db && 4 == sb) return TRUE;
1436 break;
1437 case WINED3DFMT_D32F_LOCKABLE:
1438 if (32 == db) return TRUE;
1439 break;
1440 default:
1441 ERR("unsupported format %s\n", debug_d3dformat(Format));
1442 break;
1444 return FALSE;
1445 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1446 switch (Format) {
1447 case WINED3DFMT_D16:
1448 case WINED3DFMT_D16_LOCKABLE:
1449 case WINED3DFMT_D32:
1450 case WINED3DFMT_D15S1:
1451 case WINED3DFMT_D24S8:
1452 case WINED3DFMT_D24FS8:
1453 case WINED3DFMT_D24X8:
1454 case WINED3DFMT_D24X4S4:
1455 case WINED3DFMT_D32F_LOCKABLE:
1456 return TRUE;
1457 default:
1458 ERR("unsupported format %s\n", debug_d3dformat(Format));
1459 break;
1461 return FALSE;
1462 #endif
1465 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1466 WINED3DFORMAT AdapterFormat,
1467 WINED3DFORMAT RenderTargetFormat,
1468 WINED3DFORMAT DepthStencilFormat) {
1469 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1470 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1471 WineD3D_Context* ctx = NULL;
1472 GLXFBConfig* cfgs = NULL;
1473 int nCfgs = 0;
1474 int it;
1476 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1477 This, Adapter,
1478 DeviceType, debug_d3ddevicetype(DeviceType),
1479 AdapterFormat, debug_d3dformat(AdapterFormat),
1480 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1481 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1483 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1484 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1485 return WINED3DERR_INVALIDCALL;
1487 /* TODO: use the real context if it's available */
1488 ctx = WineD3D_CreateFakeGLContext();
1489 if(NULL != ctx) {
1490 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1491 } else {
1492 TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
1495 if (NULL != cfgs) {
1496 for (it = 0; it < nCfgs; ++it) {
1497 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
1498 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
1499 hr = WINED3D_OK;
1500 break ;
1504 XFree(cfgs);
1505 cfgs = NULL;
1506 } else {
1507 /* If there's a current context then we cannot create a fake one so pass everything */
1508 hr = WINED3D_OK;
1511 if (ctx != NULL)
1512 WineD3D_ReleaseFakeGLContext(ctx);
1514 if (hr != WINED3D_OK)
1515 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1517 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1518 return hr;
1521 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1522 WINED3DFORMAT SurfaceFormat,
1523 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1525 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1526 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1527 This,
1528 Adapter,
1529 DeviceType, debug_d3ddevicetype(DeviceType),
1530 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1531 Windowed,
1532 MultiSampleType,
1533 pQualityLevels);
1535 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1536 return WINED3DERR_INVALIDCALL;
1539 if (pQualityLevels != NULL) {
1540 static int s_single_shot = 0;
1541 if (!s_single_shot) {
1542 FIXME("Quality levels unsupported at present\n");
1543 s_single_shot = 1;
1545 *pQualityLevels = 1; /* Guess at a value! */
1548 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1549 return WINED3DERR_NOTAVAILABLE;
1552 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1553 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1555 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1556 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1557 This,
1558 Adapter,
1559 CheckType, debug_d3ddevicetype(CheckType),
1560 DisplayFormat, debug_d3dformat(DisplayFormat),
1561 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1562 Windowed);
1564 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1565 return WINED3DERR_INVALIDCALL;
1569 GLXFBConfig* cfgs = NULL;
1570 int nCfgs = 0;
1571 int it;
1572 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1574 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1575 if (NULL != ctx) {
1576 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1577 for (it = 0; it < nCfgs; ++it) {
1578 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1579 hr = WINED3D_OK;
1580 break ;
1583 XFree(cfgs);
1585 WineD3D_ReleaseFakeGLContext(ctx);
1586 return hr;
1590 return WINED3DERR_NOTAVAILABLE;
1593 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1594 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1595 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1596 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1597 This,
1598 Adapter,
1599 DeviceType, debug_d3ddevicetype(DeviceType),
1600 AdapterFormat, debug_d3dformat(AdapterFormat),
1601 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1602 RType, debug_d3dresourcetype(RType),
1603 CheckFormat, debug_d3dformat(CheckFormat));
1605 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1606 return WINED3DERR_INVALIDCALL;
1609 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1610 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1611 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1612 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1613 TRACE_(d3d_caps)("[FAILED]\n");
1614 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1617 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1618 switch (CheckFormat) {
1619 case WINED3DFMT_D16_LOCKABLE:
1620 case WINED3DFMT_D32:
1621 case WINED3DFMT_D15S1:
1622 case WINED3DFMT_D24S8:
1623 case WINED3DFMT_D24X8:
1624 case WINED3DFMT_D24X4S4:
1625 case WINED3DFMT_D16:
1626 case WINED3DFMT_L16:
1627 case WINED3DFMT_D32F_LOCKABLE:
1628 case WINED3DFMT_D24FS8:
1629 TRACE_(d3d_caps)("[OK]\n");
1630 return WINED3D_OK;
1631 default:
1632 TRACE_(d3d_caps)("[FAILED]\n");
1633 return WINED3DERR_NOTAVAILABLE;
1635 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1636 switch (CheckFormat) {
1637 case WINED3DFMT_R8G8B8:
1638 case WINED3DFMT_A8R8G8B8:
1639 case WINED3DFMT_X8R8G8B8:
1640 case WINED3DFMT_R5G6B5:
1641 case WINED3DFMT_X1R5G5B5:
1642 case WINED3DFMT_A1R5G5B5:
1643 case WINED3DFMT_A4R4G4B4:
1644 case WINED3DFMT_R3G3B2:
1645 case WINED3DFMT_X4R4G4B4:
1646 case WINED3DFMT_A8B8G8R8:
1647 case WINED3DFMT_X8B8G8R8:
1648 case WINED3DFMT_P8:
1649 TRACE_(d3d_caps)("[OK]\n");
1650 return WINED3D_OK;
1651 default:
1652 TRACE_(d3d_caps)("[FAILED]\n");
1653 return WINED3DERR_NOTAVAILABLE;
1657 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1658 switch (CheckFormat) {
1659 case WINED3DFMT_DXT1:
1660 case WINED3DFMT_DXT2:
1661 case WINED3DFMT_DXT3:
1662 case WINED3DFMT_DXT4:
1663 case WINED3DFMT_DXT5:
1664 TRACE_(d3d_caps)("[OK]\n");
1665 return WINED3D_OK;
1666 default:
1667 break; /* Avoid compiler warnings */
1671 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1673 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1675 switch (CheckFormat) {
1676 case WINED3DFMT_R16F:
1677 case WINED3DFMT_A16B16G16R16F:
1678 if (!half_pixel_support) break;
1679 case WINED3DFMT_R32F:
1680 case WINED3DFMT_A32B32G32R32F:
1681 TRACE_(d3d_caps)("[OK]\n");
1682 return WINED3D_OK;
1683 default:
1684 break; /* Avoid compiler warnings */
1688 /* This format is nothing special and it is supported perfectly.
1689 * However, ati and nvidia driver on windows do not mark this format as
1690 * supported (tested with the dxCapsViewer) and pretending to
1691 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1692 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1693 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1695 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1696 TRACE_(d3d_caps)("[FAILED]\n");
1697 return WINED3DERR_NOTAVAILABLE;
1700 switch (CheckFormat) {
1702 /*****
1703 * supported: RGB(A) formats
1705 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1706 case WINED3DFMT_A8R8G8B8:
1707 case WINED3DFMT_X8R8G8B8:
1708 case WINED3DFMT_R5G6B5:
1709 case WINED3DFMT_X1R5G5B5:
1710 case WINED3DFMT_A1R5G5B5:
1711 case WINED3DFMT_A4R4G4B4:
1712 case WINED3DFMT_R3G3B2:
1713 case WINED3DFMT_A8:
1714 case WINED3DFMT_A8R3G3B2:
1715 case WINED3DFMT_X4R4G4B4:
1716 case WINED3DFMT_A8B8G8R8:
1717 case WINED3DFMT_X8B8G8R8:
1718 case WINED3DFMT_A2R10G10B10:
1719 case WINED3DFMT_A2B10G10R10:
1720 TRACE_(d3d_caps)("[OK]\n");
1721 return WINED3D_OK;
1723 /*****
1724 * supported: Palettized
1726 case WINED3DFMT_P8:
1727 TRACE_(d3d_caps)("[OK]\n");
1728 return WINED3D_OK;
1730 /*****
1731 * Supported: (Alpha)-Luminance
1733 case WINED3DFMT_L8:
1734 case WINED3DFMT_A8L8:
1735 case WINED3DFMT_A4L4:
1736 TRACE_(d3d_caps)("[OK]\n");
1737 return WINED3D_OK;
1739 /*****
1740 * Not supported for now: Bump mapping formats
1741 * Enable some because games often fail when they are not available
1742 * and are still playable even without bump mapping
1744 case WINED3DFMT_V8U8:
1745 case WINED3DFMT_V16U16:
1746 case WINED3DFMT_L6V5U5:
1747 case WINED3DFMT_X8L8V8U8:
1748 case WINED3DFMT_Q8W8V8U8:
1749 case WINED3DFMT_W11V11U10:
1750 case WINED3DFMT_A2W10V10U10:
1751 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1752 return WINED3D_OK;
1754 /*****
1755 * DXTN Formats: Handled above
1756 * WINED3DFMT_DXT1
1757 * WINED3DFMT_DXT2
1758 * WINED3DFMT_DXT3
1759 * WINED3DFMT_DXT4
1760 * WINED3DFMT_DXT5
1763 /*****
1764 * Odd formats - not supported
1766 case WINED3DFMT_VERTEXDATA:
1767 case WINED3DFMT_INDEX16:
1768 case WINED3DFMT_INDEX32:
1769 case WINED3DFMT_Q16W16V16U16:
1770 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1771 return WINED3DERR_NOTAVAILABLE;
1773 /*****
1774 * Float formats: Not supported right now
1776 case WINED3DFMT_G16R16F:
1777 case WINED3DFMT_G32R32F:
1778 case WINED3DFMT_CxV8U8:
1779 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1780 return WINED3DERR_NOTAVAILABLE;
1782 /* Not supported */
1783 case WINED3DFMT_G16R16:
1784 case WINED3DFMT_A16B16G16R16:
1785 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1786 return WINED3DERR_NOTAVAILABLE;
1788 default:
1789 break;
1792 TRACE_(d3d_caps)("[FAILED]\n");
1793 return WINED3DERR_NOTAVAILABLE;
1796 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1797 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1798 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1800 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1801 This,
1802 Adapter,
1803 DeviceType, debug_d3ddevicetype(DeviceType),
1804 SourceFormat, debug_d3dformat(SourceFormat),
1805 TargetFormat, debug_d3dformat(TargetFormat));
1806 return WINED3D_OK;
1809 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1810 subset of a D3DCAPS9 structure. However, it has to come via a void *
1811 as the d3d8 interface cannot import the d3d9 header */
1812 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1814 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1815 int vs_selected_mode;
1816 int ps_selected_mode;
1818 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1820 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1821 return WINED3DERR_INVALIDCALL;
1824 /* FIXME: GL info should be per adapter */
1826 /* If we don't know the device settings, go query them now */
1827 if (!This->isGLInfoValid) {
1828 /* use the desktop window to fill gl caps */
1829 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1831 /* We are running off a real context, save the values */
1832 if (rc) This->isGLInfoValid = TRUE;
1834 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1836 /* This function should *not* be modifying GL caps
1837 * TODO: move the functionality where it belongs */
1838 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1840 /* ------------------------------------------------
1841 The following fields apply to both d3d8 and d3d9
1842 ------------------------------------------------ */
1843 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1844 *pCaps->AdapterOrdinal = Adapter;
1846 *pCaps->Caps = 0;
1847 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1848 WINED3DCAPS2_FULLSCREENGAMMA;
1849 *pCaps->Caps3 = 0;
1850 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1852 *pCaps->CursorCaps = 0;
1855 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1856 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1857 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1858 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1859 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1860 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1861 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1862 WINED3DDEVCAPS_PUREDEVICE |
1863 WINED3DDEVCAPS_HWRASTERIZATION |
1864 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1865 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1866 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1867 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1868 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1870 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1871 D3DPMISCCAPS_CULLCCW |
1872 D3DPMISCCAPS_CULLCW |
1873 D3DPMISCCAPS_COLORWRITEENABLE |
1874 D3DPMISCCAPS_CLIPTLVERTS |
1875 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1876 D3DPMISCCAPS_MASKZ |
1877 D3DPMISCCAPS_BLENDOP;
1878 /* TODO:
1879 D3DPMISCCAPS_NULLREFERENCE
1880 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1881 D3DPMISCCAPS_FOGANDSPECULARALPHA
1882 D3DPMISCCAPS_SEPARATEALPHABLEND
1883 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1884 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1885 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1887 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1888 #if 0
1889 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1890 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1891 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1892 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1893 #endif
1895 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1896 WINED3DPRASTERCAPS_PAT |
1897 WINED3DPRASTERCAPS_WFOG |
1898 WINED3DPRASTERCAPS_ZFOG |
1899 WINED3DPRASTERCAPS_FOGVERTEX |
1900 WINED3DPRASTERCAPS_FOGTABLE |
1901 WINED3DPRASTERCAPS_FOGRANGE |
1902 WINED3DPRASTERCAPS_STIPPLE |
1903 WINED3DPRASTERCAPS_SUBPIXEL |
1904 WINED3DPRASTERCAPS_ZTEST |
1905 WINED3DPRASTERCAPS_SCISSORTEST |
1906 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1907 WINED3DPRASTERCAPS_DEPTHBIAS;
1909 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1910 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1911 WINED3DPRASTERCAPS_ZBIAS |
1912 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1914 /* FIXME Add:
1915 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1916 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1917 WINED3DPRASTERCAPS_ANTIALIASEDGES
1918 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1919 WINED3DPRASTERCAPS_WBUFFER */
1921 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1922 D3DPCMPCAPS_EQUAL |
1923 D3DPCMPCAPS_GREATER |
1924 D3DPCMPCAPS_GREATEREQUAL |
1925 D3DPCMPCAPS_LESS |
1926 D3DPCMPCAPS_LESSEQUAL |
1927 D3DPCMPCAPS_NEVER |
1928 D3DPCMPCAPS_NOTEQUAL;
1930 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1931 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1932 D3DPBLENDCAPS_BOTHSRCALPHA |
1933 D3DPBLENDCAPS_DESTALPHA |
1934 D3DPBLENDCAPS_DESTCOLOR |
1935 D3DPBLENDCAPS_INVDESTALPHA |
1936 D3DPBLENDCAPS_INVDESTCOLOR |
1937 D3DPBLENDCAPS_INVSRCALPHA |
1938 D3DPBLENDCAPS_INVSRCCOLOR |
1939 D3DPBLENDCAPS_ONE |
1940 D3DPBLENDCAPS_SRCALPHA |
1941 D3DPBLENDCAPS_SRCALPHASAT |
1942 D3DPBLENDCAPS_SRCCOLOR |
1943 D3DPBLENDCAPS_ZERO;
1945 *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1946 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1947 D3DPBLENDCAPS_BOTHSRCALPHA |
1948 D3DPBLENDCAPS_DESTALPHA |
1949 D3DPBLENDCAPS_DESTCOLOR |
1950 D3DPBLENDCAPS_INVDESTALPHA |
1951 D3DPBLENDCAPS_INVDESTCOLOR |
1952 D3DPBLENDCAPS_INVSRCALPHA |
1953 D3DPBLENDCAPS_INVSRCCOLOR |
1954 D3DPBLENDCAPS_ONE |
1955 D3DPBLENDCAPS_SRCALPHA |
1956 D3DPBLENDCAPS_SRCALPHASAT |
1957 D3DPBLENDCAPS_SRCCOLOR |
1958 D3DPBLENDCAPS_ZERO;
1960 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1961 D3DPCMPCAPS_EQUAL |
1962 D3DPCMPCAPS_GREATER |
1963 D3DPCMPCAPS_GREATEREQUAL |
1964 D3DPCMPCAPS_LESS |
1965 D3DPCMPCAPS_LESSEQUAL |
1966 D3DPCMPCAPS_NEVER |
1967 D3DPCMPCAPS_NOTEQUAL;
1969 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1970 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1971 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1972 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1973 WINED3DPSHADECAPS_COLORFLATRGB |
1974 WINED3DPSHADECAPS_FOGFLAT |
1975 WINED3DPSHADECAPS_FOGGOURAUD |
1976 WINED3DPSHADECAPS_SPECULARFLATRGB;
1978 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1979 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1980 WINED3DPTEXTURECAPS_BORDER |
1981 WINED3DPTEXTURECAPS_MIPMAP |
1982 WINED3DPTEXTURECAPS_PROJECTED |
1983 WINED3DPTEXTURECAPS_PERSPECTIVE |
1984 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1986 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1987 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1988 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1989 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1992 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1993 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1994 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1995 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1999 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2000 WINED3DPTFILTERCAPS_MAGFPOINT |
2001 WINED3DPTFILTERCAPS_MINFLINEAR |
2002 WINED3DPTFILTERCAPS_MINFPOINT |
2003 WINED3DPTFILTERCAPS_MIPFLINEAR |
2004 WINED3DPTFILTERCAPS_MIPFPOINT |
2005 WINED3DPTFILTERCAPS_LINEAR |
2006 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2007 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2008 WINED3DPTFILTERCAPS_MIPLINEAR |
2009 WINED3DPTFILTERCAPS_MIPNEAREST |
2010 WINED3DPTFILTERCAPS_NEAREST;
2012 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2013 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2014 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2017 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2018 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2019 WINED3DPTFILTERCAPS_MAGFPOINT |
2020 WINED3DPTFILTERCAPS_MINFLINEAR |
2021 WINED3DPTFILTERCAPS_MINFPOINT |
2022 WINED3DPTFILTERCAPS_MIPFLINEAR |
2023 WINED3DPTFILTERCAPS_MIPFPOINT |
2024 WINED3DPTFILTERCAPS_LINEAR |
2025 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2026 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2027 WINED3DPTFILTERCAPS_MIPLINEAR |
2028 WINED3DPTFILTERCAPS_MIPNEAREST |
2029 WINED3DPTFILTERCAPS_NEAREST;
2031 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2032 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2033 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2035 } else
2036 *pCaps->CubeTextureFilterCaps = 0;
2038 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2039 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2040 WINED3DPTFILTERCAPS_MAGFPOINT |
2041 WINED3DPTFILTERCAPS_MINFLINEAR |
2042 WINED3DPTFILTERCAPS_MINFPOINT |
2043 WINED3DPTFILTERCAPS_MIPFLINEAR |
2044 WINED3DPTFILTERCAPS_MIPFPOINT |
2045 WINED3DPTFILTERCAPS_LINEAR |
2046 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2047 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2048 WINED3DPTFILTERCAPS_MIPLINEAR |
2049 WINED3DPTFILTERCAPS_MIPNEAREST |
2050 WINED3DPTFILTERCAPS_NEAREST;
2051 } else
2052 *pCaps->VolumeTextureFilterCaps = 0;
2054 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2055 D3DPTADDRESSCAPS_CLAMP |
2056 D3DPTADDRESSCAPS_WRAP;
2058 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2059 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2061 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2062 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2064 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2065 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2068 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2069 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2070 D3DPTADDRESSCAPS_CLAMP |
2071 D3DPTADDRESSCAPS_WRAP;
2072 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2073 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2075 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2076 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2078 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2079 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2081 } else
2082 *pCaps->VolumeTextureAddressCaps = 0;
2084 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2085 D3DLINECAPS_ZTEST;
2086 /* FIXME: Add
2087 D3DLINECAPS_BLEND
2088 D3DLINECAPS_ALPHACMP
2089 D3DLINECAPS_FOG */
2091 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2092 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2094 if(GL_SUPPORT(EXT_TEXTURE3D))
2095 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2096 else
2097 *pCaps->MaxVolumeExtent = 0;
2099 *pCaps->MaxTextureRepeat = 32768;
2100 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2101 *pCaps->MaxVertexW = 1.0;
2103 *pCaps->GuardBandLeft = 0;
2104 *pCaps->GuardBandTop = 0;
2105 *pCaps->GuardBandRight = 0;
2106 *pCaps->GuardBandBottom = 0;
2108 *pCaps->ExtentsAdjust = 0;
2110 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2111 D3DSTENCILCAPS_INCRSAT |
2112 D3DSTENCILCAPS_INVERT |
2113 D3DSTENCILCAPS_KEEP |
2114 D3DSTENCILCAPS_REPLACE |
2115 D3DSTENCILCAPS_ZERO;
2116 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2117 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2118 D3DSTENCILCAPS_INCR;
2120 if ( This->dxVersion > 8 &&
2121 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2122 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2123 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2126 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2128 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2129 D3DTEXOPCAPS_ADDSIGNED |
2130 D3DTEXOPCAPS_ADDSIGNED2X |
2131 D3DTEXOPCAPS_MODULATE |
2132 D3DTEXOPCAPS_MODULATE2X |
2133 D3DTEXOPCAPS_MODULATE4X |
2134 D3DTEXOPCAPS_SELECTARG1 |
2135 D3DTEXOPCAPS_SELECTARG2 |
2136 D3DTEXOPCAPS_DISABLE;
2138 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2139 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2140 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2141 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2142 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2143 D3DTEXOPCAPS_BLENDFACTORALPHA |
2144 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2145 D3DTEXOPCAPS_LERP |
2146 D3DTEXOPCAPS_SUBTRACT;
2148 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2149 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2150 D3DTEXOPCAPS_MULTIPLYADD |
2151 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2152 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2153 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2155 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2156 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2158 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2159 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2160 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2164 #if 0
2165 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2166 /* FIXME: Add
2167 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2168 D3DTEXOPCAPS_PREMODULATE */
2169 #endif
2171 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2172 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2173 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2174 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2178 #if 0 /* TODO: Blends support in drawprim */
2179 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2180 #else
2181 *pCaps->MaxVertexBlendMatrices = 0;
2182 #endif
2183 *pCaps->MaxVertexBlendMatrixIndex = 1;
2185 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2186 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2189 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2190 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2191 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2192 WINED3DVTXPCAPS_LOCALVIEWER |
2193 WINED3DVTXPCAPS_VERTEXFOG |
2194 WINED3DVTXPCAPS_TEXGEN;
2195 /* FIXME: Add
2196 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2198 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2199 *pCaps->MaxVertexIndex = 0xFFFFF;
2200 *pCaps->MaxStreams = MAX_STREAMS;
2201 *pCaps->MaxStreamStride = 1024;
2203 if (vs_selected_mode == SHADER_GLSL) {
2204 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2205 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2206 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2207 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2208 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2209 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2210 else
2211 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2212 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2213 } else if (vs_selected_mode == SHADER_ARB) {
2214 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2215 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2216 } else if (vs_selected_mode == SHADER_SW) {
2217 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2218 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2219 } else {
2220 *pCaps->VertexShaderVersion = 0;
2221 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2224 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2226 if (ps_selected_mode == SHADER_GLSL) {
2227 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2228 in case of GeforceFX cards. */
2229 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2230 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2231 else
2232 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2233 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2234 *pCaps->PixelShader1xMaxValue = 1.0;
2235 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2236 } else if (ps_selected_mode == SHADER_ARB) {
2237 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2238 *pCaps->PixelShader1xMaxValue = 1.0;
2239 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2240 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2241 } else if (ps_selected_mode = SHADER_SW) {
2242 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2243 *pCaps->PixelShader1xMaxValue = 1.0;
2244 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2245 } else {
2246 *pCaps->PixelShaderVersion = 0;
2247 *pCaps->PixelShader1xMaxValue = 0.0;
2248 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2251 /* ------------------------------------------------
2252 The following fields apply to d3d9 only
2253 ------------------------------------------------ */
2254 if (This->dxVersion > 8) {
2255 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
2256 *pCaps->DevCaps2 = 0;
2257 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES and VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2258 *pCaps->MaxNpatchTessellationLevel = 0;
2259 *pCaps->MasterAdapterOrdinal = 0;
2260 *pCaps->AdapterOrdinalInGroup = 0;
2261 *pCaps->NumberOfAdaptersInGroup = 1;
2263 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2264 /* OpenGL supports all formats below, perhaps not always without conversion but it supports them.
2265 Further GLSL doesn't seem to have an official unsigned type as I'm not sure how we handle it
2266 don't advertise it yet. We might need to add some clamping in the shader engine to support it.
2267 TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2268 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2269 D3DDTCAPS_UBYTE4N |
2270 D3DDTCAPS_SHORT2N |
2271 D3DDTCAPS_SHORT4N |
2272 D3DDTCAPS_FLOAT16_2 |
2273 D3DDTCAPS_FLOAT16_4;
2275 } else
2276 *pCaps->DeclTypes = 0;
2278 #if 0 /* We don't properly support multiple render targets yet, so disable this for now */
2279 if (GL_SUPPORT(ARB_DRAWBUFFERS)) {
2280 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2281 } else
2282 #endif
2283 *pCaps->NumSimultaneousRTs = 1;
2285 *pCaps->StretchRectFilterCaps = 0;
2286 *pCaps->VertexTextureFilterCaps = 0;
2288 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2289 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2290 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2291 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2292 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2293 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2294 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2296 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2297 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2298 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2299 *pCaps->VS20Caps.Caps = 0;
2300 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2301 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2302 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2304 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2305 *pCaps->MaxVertexShader30InstructionSlots = 0;
2306 } else { /* VS 1.x */
2307 *pCaps->VS20Caps.Caps = 0;
2308 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2309 *pCaps->VS20Caps.NumTemps = 0;
2310 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2312 *pCaps->MaxVShaderInstructionsExecuted = 0;
2313 *pCaps->MaxVertexShader30InstructionSlots = 0;
2316 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2317 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2318 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2320 /* 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 */
2321 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2322 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2323 D3DPS20CAPS_PREDICATION |
2324 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2325 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2326 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2327 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2328 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2329 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2331 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2332 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2333 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2334 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2335 *pCaps->PS20Caps.Caps = 0;
2336 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2337 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2338 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2339 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2341 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2342 *pCaps->MaxPixelShader30InstructionSlots = 0;
2343 } else { /* PS 1.x */
2344 *pCaps->PS20Caps.Caps = 0;
2345 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2346 *pCaps->PS20Caps.NumTemps = 0;
2347 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2348 *pCaps->PS20Caps.NumInstructionSlots = 0;
2350 *pCaps->MaxPShaderInstructionsExecuted = 0;
2351 *pCaps->MaxPixelShader30InstructionSlots = 0;
2355 return WINED3D_OK;
2359 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2360 and fields being inserted in the middle, a new structure is used in place */
2361 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2362 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2363 IUnknown *parent) {
2365 IWineD3DDeviceImpl *object = NULL;
2366 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2367 HDC hDC;
2368 HRESULT temp_result;
2370 /* Validate the adapter number */
2371 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2372 return WINED3DERR_INVALIDCALL;
2375 /* Create a WineD3DDevice object */
2376 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2377 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2378 TRACE("Created WineD3DDevice object @ %p\n", object);
2379 if (NULL == object) {
2380 return WINED3DERR_OUTOFVIDEOMEMORY;
2383 /* Set up initial COM information */
2384 object->lpVtbl = &IWineD3DDevice_Vtbl;
2385 object->ref = 1;
2386 object->wineD3D = iface;
2387 IWineD3D_AddRef(object->wineD3D);
2388 object->parent = parent;
2390 /* Set the state up as invalid until the device is fully created */
2391 object->state = WINED3DERR_DRIVERINTERNALERROR;
2393 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2394 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2396 /* Save the creation parameters */
2397 object->createParms.AdapterOrdinal = Adapter;
2398 object->createParms.DeviceType = DeviceType;
2399 object->createParms.hFocusWindow = hFocusWindow;
2400 object->createParms.BehaviorFlags = BehaviourFlags;
2402 /* Initialize other useful values */
2403 object->adapterNo = Adapter;
2404 object->devType = DeviceType;
2406 TRACE("(%p) : Creating stateblock\n", This);
2407 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2408 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2409 WINED3DSBT_INIT,
2410 (IWineD3DStateBlock **)&object->stateBlock,
2411 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2412 WARN("Failed to create stateblock\n");
2413 goto create_device_error;
2415 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2416 object->updateStateBlock = object->stateBlock;
2417 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2418 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2420 /* Setup some defaults for creating the implicit swapchain */
2421 ENTER_GL();
2422 /* FIXME: GL info should be per adapter */
2423 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2424 LEAVE_GL();
2425 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2427 /* This function should *not* be modifying GL caps
2428 * TODO: move the functionality where it belongs */
2429 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2431 temp_result = allocate_shader_constants(object->updateStateBlock);
2432 if (WINED3D_OK != temp_result)
2433 return temp_result;
2435 /* set the state of the device to valid */
2436 object->state = WINED3D_OK;
2438 /* Get the initial screen setup for ddraw */
2439 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2440 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2441 hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
2442 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2443 DeleteDC(hDC);
2445 return WINED3D_OK;
2446 create_device_error:
2448 /* Set the device state to error */
2449 object->state = WINED3DERR_DRIVERINTERNALERROR;
2451 if (object->updateStateBlock != NULL) {
2452 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2453 object->updateStateBlock = NULL;
2455 if (object->stateBlock != NULL) {
2456 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2457 object->stateBlock = NULL;
2459 if (object->renderTarget != NULL) {
2460 IWineD3DSurface_Release(object->renderTarget);
2461 object->renderTarget = NULL;
2463 if (object->stencilBufferTarget != NULL) {
2464 IWineD3DSurface_Release(object->stencilBufferTarget);
2465 object->stencilBufferTarget = NULL;
2467 if (object->stencilBufferTarget != NULL) {
2468 IWineD3DSurface_Release(object->stencilBufferTarget);
2469 object->stencilBufferTarget = NULL;
2471 HeapFree(GetProcessHeap(), 0, object);
2472 *ppReturnedDeviceInterface = NULL;
2473 return WINED3DERR_INVALIDCALL;
2477 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2478 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2479 IUnknown_AddRef(This->parent);
2480 *pParent = This->parent;
2481 return WINED3D_OK;
2484 /**********************************************************
2485 * IWineD3D VTbl follows
2486 **********************************************************/
2488 const IWineD3DVtbl IWineD3D_Vtbl =
2490 /* IUnknown */
2491 IWineD3DImpl_QueryInterface,
2492 IWineD3DImpl_AddRef,
2493 IWineD3DImpl_Release,
2494 /* IWineD3D */
2495 IWineD3DImpl_GetParent,
2496 IWineD3DImpl_GetAdapterCount,
2497 IWineD3DImpl_RegisterSoftwareDevice,
2498 IWineD3DImpl_GetAdapterMonitor,
2499 IWineD3DImpl_GetAdapterModeCount,
2500 IWineD3DImpl_EnumAdapterModes,
2501 IWineD3DImpl_GetAdapterDisplayMode,
2502 IWineD3DImpl_GetAdapterIdentifier,
2503 IWineD3DImpl_CheckDeviceMultiSampleType,
2504 IWineD3DImpl_CheckDepthStencilMatch,
2505 IWineD3DImpl_CheckDeviceType,
2506 IWineD3DImpl_CheckDeviceFormat,
2507 IWineD3DImpl_CheckDeviceFormatConversion,
2508 IWineD3DImpl_GetDeviceCaps,
2509 IWineD3DImpl_CreateDevice