wined3d: Comparing BOOLs against FALSE is redundant.
[wine.git] / dlls / wined3d / directx.c
blobfdde6ea7bdcf415f5b86a292e7a1d63534ef2fc7
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 %ld\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 %ld\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(WineD3D_GL_Info *gl_info) {
243 switch (wined3d_settings.vs_selected_mode) {
244 case SHADER_GLSL:
245 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
246 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I - 1;
247 break;
248 case SHADER_ARB:
249 /* We have to subtract any other PARAMs that we might use in our shader programs.
250 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
251 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
252 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
253 break;
254 case SHADER_SW:
255 gl_info->max_vshader_constantsF = 96; /* TODO: Fixup software shaders */
256 break;
257 default:
258 gl_info->max_vshader_constantsF = 0;
259 break;
262 switch (wined3d_settings.ps_selected_mode) {
263 case SHADER_GLSL:
264 /* Subtract the other potential uniforms from the max available (bools & ints) */
265 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
266 break;
267 case SHADER_ARB:
268 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
269 break;
270 case SHADER_SW:
271 gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */
272 break;
273 default:
274 gl_info->max_pshader_constantsF = 0;
275 break;
279 /**********************************************************
280 * IWineD3D parts follows
281 **********************************************************/
283 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
284 IWineD3DImpl *This = (IWineD3DImpl *)iface;
285 WineD3D_GL_Info *gl_info = &This->gl_info;
287 const char *GL_Extensions = NULL;
288 const char *GLX_Extensions = NULL;
289 const char *gl_string = NULL;
290 const char *gl_string_cursor = NULL;
291 GLint gl_max;
292 GLfloat gl_floatv[2];
293 Bool test = 0;
294 int major, minor;
295 WineD3D_Context *fake_ctx = NULL;
296 BOOL gotContext = FALSE;
297 int i;
299 /* Make sure that we've got a context */
300 if (glXGetCurrentContext() == NULL) {
301 /* TODO: CreateFakeGLContext should really take a display as a parameter */
302 fake_ctx = WineD3D_CreateFakeGLContext();
303 if (NULL != fake_ctx) gotContext = TRUE;
304 } else {
305 gotContext = TRUE;
308 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
310 gl_string = (const char *) glGetString(GL_RENDERER);
311 if (NULL == gl_string)
312 gl_string = "None";
313 strcpy(gl_info->gl_renderer, gl_string);
315 /* Fill in the GL info retrievable depending on the display */
316 if (NULL != display) {
317 test = glXQueryVersion(display, &major, &minor);
318 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
319 } else {
320 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
322 gl_string = (const char *) glGetString(GL_VENDOR);
324 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
325 if (gl_string != NULL) {
326 /* Fill in the GL vendor */
327 if (strstr(gl_string, "NVIDIA")) {
328 gl_info->gl_vendor = VENDOR_NVIDIA;
329 } else if (strstr(gl_string, "ATI")) {
330 gl_info->gl_vendor = VENDOR_ATI;
331 } else if (strstr(gl_string, "Intel(R)") ||
332 strstr(gl_info->gl_renderer, "Intel(R)")) {
333 gl_info->gl_vendor = VENDOR_INTEL;
334 } else if (strstr(gl_string, "Mesa")) {
335 gl_info->gl_vendor = VENDOR_MESA;
336 } else {
337 gl_info->gl_vendor = VENDOR_WINE;
339 } else {
340 gl_info->gl_vendor = VENDOR_WINE;
344 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
346 /* Parse the GL_VERSION field into major and minor information */
347 gl_string = (const char *) glGetString(GL_VERSION);
348 if (gl_string != NULL) {
350 switch (gl_info->gl_vendor) {
351 case VENDOR_NVIDIA:
352 gl_string_cursor = strstr(gl_string, "NVIDIA");
353 if (!gl_string_cursor) {
354 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
355 break;
358 gl_string_cursor = strstr(gl_string_cursor, " ");
359 if (!gl_string_cursor) {
360 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
361 break;
364 while (*gl_string_cursor == ' ') {
365 ++gl_string_cursor;
368 if (!*gl_string_cursor) {
369 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
370 break;
373 major = atoi(gl_string_cursor);
374 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
375 ++gl_string_cursor;
378 if (*gl_string_cursor++ != '.') {
379 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
380 break;
383 minor = atoi(gl_string_cursor);
384 minor = major*100+minor;
385 major = 10;
387 break;
389 case VENDOR_ATI:
390 major = minor = 0;
391 gl_string_cursor = strchr(gl_string, '-');
392 if (gl_string_cursor) {
393 int error = 0;
394 gl_string_cursor++;
396 /* Check if version number is of the form x.y.z */
397 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
398 error = 1;
399 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
400 error = 1;
401 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
402 error = 1;
403 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
404 error = 1;
406 /* Mark version number as malformed */
407 if (error)
408 gl_string_cursor = 0;
411 if (!gl_string_cursor)
412 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
413 else {
414 major = *gl_string_cursor - '0';
415 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
417 break;
419 case VENDOR_INTEL:
420 case VENDOR_MESA:
421 gl_string_cursor = strstr(gl_string, "Mesa");
422 gl_string_cursor = strstr(gl_string_cursor, " ");
423 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
424 if (*gl_string_cursor) {
425 char tmp[16];
426 int cursor = 0;
428 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
429 tmp[cursor++] = *gl_string_cursor;
430 ++gl_string_cursor;
432 tmp[cursor] = 0;
433 major = atoi(tmp);
435 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
436 ++gl_string_cursor;
438 cursor = 0;
439 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
440 tmp[cursor++] = *gl_string_cursor;
441 ++gl_string_cursor;
443 tmp[cursor] = 0;
444 minor = atoi(tmp);
446 break;
448 default:
449 major = 0;
450 minor = 9;
452 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
453 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08lx)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
456 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
459 * Initialize openGL extension related variables
460 * with Default values
462 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
463 gl_info->max_buffers = 1;
464 gl_info->max_textures = 1;
465 gl_info->max_texture_stages = 1;
466 gl_info->max_samplers = 1;
467 gl_info->max_sampler_stages = 1;
468 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
469 gl_info->ps_arb_max_temps = 0;
470 gl_info->ps_arb_max_instructions = 0;
471 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
472 gl_info->vs_arb_max_temps = 0;
473 gl_info->vs_arb_max_instructions = 0;
474 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
475 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
476 gl_info->vs_glsl_constantsF = 0;
477 gl_info->ps_glsl_constantsF = 0;
478 gl_info->vs_arb_constantsF = 0;
479 gl_info->ps_arb_constantsF = 0;
481 /* Now work out what GL support this card really has */
482 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
483 GL_EXT_FUNCS_GEN;
484 GLX_EXT_FUNCS_GEN;
485 #undef USE_GL_FUNC
487 /* Retrieve opengl defaults */
488 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
489 gl_info->max_clipplanes = min(D3DMAXUSERCLIPPLANES, gl_max);
490 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
492 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
493 gl_info->max_lights = gl_max;
494 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
496 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
497 gl_info->max_texture_size = gl_max;
498 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
500 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
501 gl_info->max_pointsize = gl_floatv[1];
502 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
504 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
505 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
506 TRACE_(d3d_caps)("GL_Extensions reported:\n");
508 if (NULL == GL_Extensions) {
509 ERR(" GL_Extensions returns NULL\n");
510 } else {
511 while (*GL_Extensions != 0x00) {
512 const char *Start = GL_Extensions;
513 char ThisExtn[256];
515 memset(ThisExtn, 0x00, sizeof(ThisExtn));
516 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
517 GL_Extensions++;
519 memcpy(ThisExtn, Start, (GL_Extensions - Start));
520 TRACE_(d3d_caps)("- %s\n", ThisExtn);
523 * ARB
525 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
526 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
527 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
528 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
529 gl_info->max_buffers = gl_max;
530 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
531 gl_info->ps_arb_version = PS_VERSION_11;
532 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
533 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
534 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
535 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
536 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
537 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
538 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
539 gl_info->ps_arb_constantsF = gl_max;
540 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
541 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
542 gl_info->ps_arb_max_temps = gl_max;
543 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
544 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
545 gl_info->ps_arb_max_instructions = gl_max;
546 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
547 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
548 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
549 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
550 gl_info->ps_glsl_constantsF = gl_max;
551 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
552 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
553 gl_info->supported[ARB_IMAGING] = TRUE;
554 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
555 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
556 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
557 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
558 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
559 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
560 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
561 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
562 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
563 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
564 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
565 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
566 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
567 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
568 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
569 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
570 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
571 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
572 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
573 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
574 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
575 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
576 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
577 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
578 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
579 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
580 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
581 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
582 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
583 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
584 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
585 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
586 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
587 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
588 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
589 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
590 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
591 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
592 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
593 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
594 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
595 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
596 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
597 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
598 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
599 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
600 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
601 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
602 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
603 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
604 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
605 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
606 gl_info->vs_arb_version = VS_VERSION_11;
607 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
608 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
609 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
610 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
611 gl_info->vs_arb_constantsF = gl_max;
612 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
613 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
614 gl_info->vs_arb_max_temps = gl_max;
615 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
616 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
617 gl_info->vs_arb_max_instructions = gl_max;
618 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
619 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
620 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
621 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
622 gl_info->vs_glsl_constantsF = gl_max;
623 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
624 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
625 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
626 gl_info->max_blends = gl_max;
627 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
628 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
629 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
630 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
631 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
632 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
633 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
634 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
635 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
636 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
638 * EXT
640 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
641 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
642 gl_info->supported[EXT_FOG_COORD] = TRUE;
643 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
644 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
645 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
646 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
647 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
648 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
649 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
650 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
651 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
652 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
653 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
654 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
655 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
656 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
657 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
658 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
659 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
660 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
661 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
662 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
663 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
664 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
665 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
666 gl_info->supported[EXT_TEXTURE3D] = TRUE;
667 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
668 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
669 gl_info->max_texture3d_size = gl_max;
670 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
671 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
672 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
673 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
674 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
675 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
676 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
677 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
678 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
679 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
680 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
681 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
682 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
683 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
684 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
685 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
686 gl_info->max_anisotropy = gl_max;
687 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
688 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
689 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
690 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
691 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
692 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
693 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
694 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
695 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
698 * NVIDIA
700 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
701 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
702 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
703 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
704 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
705 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
706 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
707 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
708 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
709 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
710 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
711 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
712 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
713 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
714 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
715 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
716 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
717 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
718 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
719 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
720 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
721 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
722 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
723 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
724 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
725 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
726 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
727 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
728 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
729 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
730 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
731 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
732 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
733 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
734 gl_info->vs_nv_version = VS_VERSION_30;
735 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
736 gl_info->vs_nv_version = VS_VERSION_20;
737 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
738 gl_info->vs_nv_version = VS_VERSION_11;
739 else
740 gl_info->vs_nv_version = VS_VERSION_10;
741 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
742 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
745 * ATI
747 /** TODO */
748 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
749 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
750 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
751 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
752 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
753 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
754 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
755 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
756 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
757 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
758 gl_info->vs_ati_version = VS_VERSION_11;
759 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
760 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
764 if (*GL_Extensions == ' ') GL_Extensions++;
767 checkGLcall("extension detection\n");
769 /* In some cases the number of texture stages can be larger than the number
770 * of samplers. The GF4 for example can use only 2 samplers (no fragment
771 * shaders), but 8 texture stages (register combiners). */
772 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
774 /* We can only use NP2_NATIVE when the hardware supports it. */
775 if (wined3d_settings.nonpower2_mode == NP2_NATIVE && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
776 WARN_(d3d_caps)("GL_ARB_texture_non_power_of_two not supported, falling back to NP2_NONE NPOT mode.\n");
777 wined3d_settings.nonpower2_mode = NP2_NONE;
780 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
781 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
782 * in case of the latest videocards in the number of pixel/vertex pipelines.
784 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
785 * rendering. Various games use this information to get a rough estimation of the features of the card
786 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
787 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
788 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
789 * not the PCI id.
791 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
792 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
793 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
794 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
795 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
796 * is used for rendering which is not always the case). This would work but it is not very portable. Second
797 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
798 * is limited.
800 * As said most games only use the PCI id to get an indication of the capabilities of the card.
801 * It doesn't really matter if the given id is the correct one if we return the id of a card with
802 * similar 3d features.
804 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
805 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
806 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
807 * won't pass we return a default card. This way is better than maintaining a full card database as even
808 * without a full database we can return a card with similar features. Second the size of the database
809 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
810 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
811 * to distinguishes between different models from that family.
813 switch (gl_info->gl_vendor) {
814 case VENDOR_NVIDIA:
815 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
816 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
818 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
819 if (strstr(gl_info->gl_renderer, "7800") ||
820 strstr(gl_info->gl_renderer, "7900") ||
821 strstr(gl_info->gl_renderer, "7950") ||
822 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
823 strstr(gl_info->gl_renderer, "Quadro FX 5"))
824 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
825 else if(strstr(gl_info->gl_renderer, "6800") ||
826 strstr(gl_info->gl_renderer, "7600"))
827 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
828 else if(strstr(gl_info->gl_renderer, "6600") ||
829 strstr(gl_info->gl_renderer, "6610") ||
830 strstr(gl_info->gl_renderer, "6700"))
831 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
832 else
833 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
834 } else if(WINE_D3D9_CAPABLE(gl_info)) {
835 if (strstr(gl_info->gl_renderer, "5800") ||
836 strstr(gl_info->gl_renderer, "5900") ||
837 strstr(gl_info->gl_renderer, "5950") ||
838 strstr(gl_info->gl_renderer, "Quadro FX"))
839 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
840 else if(strstr(gl_info->gl_renderer, "5600") ||
841 strstr(gl_info->gl_renderer, "5650") ||
842 strstr(gl_info->gl_renderer, "5700") ||
843 strstr(gl_info->gl_renderer, "5750"))
844 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
845 else
846 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
847 } else if(WINE_D3D8_CAPABLE(gl_info)) {
848 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
849 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
850 else
851 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
852 } else if(WINE_D3D7_CAPABLE(gl_info)) {
853 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
854 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
855 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
856 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
857 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
858 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
859 else
860 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
861 } else {
862 if (strstr(gl_info->gl_renderer, "TNT2"))
863 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
864 else
865 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
867 break;
868 case VENDOR_ATI:
869 if(WINE_D3D9_CAPABLE(gl_info)) {
870 /* Radeon R5xx */
871 if (strstr(gl_info->gl_renderer, "X1600") ||
872 strstr(gl_info->gl_renderer, "X1800") ||
873 strstr(gl_info->gl_renderer, "X1900") ||
874 strstr(gl_info->gl_renderer, "X1950"))
875 gl_info->gl_card = CARD_ATI_RADEON_X1600;
876 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
877 else if(strstr(gl_info->gl_renderer, "X700") ||
878 strstr(gl_info->gl_renderer, "X800") ||
879 strstr(gl_info->gl_renderer, "X850") ||
880 strstr(gl_info->gl_renderer, "X1300") ||
881 strstr(gl_info->gl_renderer, "X1400"))
882 gl_info->gl_card = CARD_ATI_RADEON_X700;
883 /* Radeon R3xx */
884 else
885 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
886 } else if(WINE_D3D8_CAPABLE(gl_info)) {
887 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
888 } else if(WINE_D3D7_CAPABLE(gl_info)) {
889 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
890 } else
891 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
892 break;
893 case VENDOR_INTEL:
894 if (strstr(gl_info->gl_renderer, "915GM")) {
895 gl_info->gl_card = CARD_INTEL_I915GM;
896 } else if (strstr(gl_info->gl_renderer, "915G")) {
897 gl_info->gl_card = CARD_INTEL_I915G;
898 } else if (strstr(gl_info->gl_renderer, "865G")) {
899 gl_info->gl_card = CARD_INTEL_I865G;
900 } else if (strstr(gl_info->gl_renderer, "855G")) {
901 gl_info->gl_card = CARD_INTEL_I855G;
902 } else if (strstr(gl_info->gl_renderer, "830G")) {
903 gl_info->gl_card = CARD_INTEL_I830G;
904 } else {
905 gl_info->gl_card = CARD_INTEL_I915G;
907 break;
908 case VENDOR_MESA:
909 case VENDOR_WINE:
910 default:
911 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
912 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
913 * them a good generic choice.
915 gl_info->gl_vendor = VENDOR_NVIDIA;
916 if(WINE_D3D9_CAPABLE(gl_info))
917 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
918 else if(WINE_D3D8_CAPABLE(gl_info))
919 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
920 else if(WINE_D3D7_CAPABLE(gl_info))
921 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
922 else if(WINE_D3D6_CAPABLE(gl_info))
923 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
924 else
925 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
927 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
929 /* Load all the lookup tables
930 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
931 minLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_WRAP;
932 maxLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_MIRRORONCE;
934 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
935 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
938 for (i = 0; i < MAX_LOOKUPS; i++) {
939 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
942 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
943 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
944 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
945 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
946 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
947 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
948 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
949 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
950 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
951 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
953 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
954 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
955 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
956 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
957 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
960 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
961 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
962 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
963 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
964 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
965 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
966 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
967 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
968 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
969 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
970 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
971 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
972 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
974 /* TODO: config lookups */
976 if (display != NULL) {
977 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
978 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
980 if (NULL == GLX_Extensions) {
981 ERR(" GLX_Extensions returns NULL\n");
982 } else {
983 while (*GLX_Extensions != 0x00) {
984 const char *Start = GLX_Extensions;
985 char ThisExtn[256];
987 memset(ThisExtn, 0x00, sizeof(ThisExtn));
988 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
989 GLX_Extensions++;
991 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
992 TRACE_(d3d_caps)("- %s\n", ThisExtn);
993 if (*GLX_Extensions == ' ') GLX_Extensions++;
998 /* If we created a dummy context, throw it away */
999 if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
1001 /* Only save the values obtained when a display is provided */
1002 if (fake_ctx == NULL) {
1003 return TRUE;
1004 } else {
1005 return FALSE;
1009 /**********************************************************
1010 * IWineD3D implementation follows
1011 **********************************************************/
1013 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1014 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1016 /* FIXME: Set to one for now to imply the display */
1017 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1018 return 1;
1021 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1022 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1023 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1024 return WINED3D_OK;
1027 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1028 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1029 POINT pt = { -1, -1 };
1031 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1032 return NULL;
1035 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1036 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1039 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1040 of the same bpp but different resolutions */
1042 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1043 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1044 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1045 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1047 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1048 return 0;
1051 if (Adapter == 0) { /* Display */
1052 int i = 0;
1053 int j = 0;
1054 #if !defined( DEBUG_SINGLE_MODE )
1055 DEVMODEW DevModeW;
1057 /* Work out the current screen bpp */
1058 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1059 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1060 DeleteDC(hdc);
1062 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1063 j++;
1064 switch (Format)
1066 case D3DFMT_UNKNOWN:
1067 i++;
1068 break;
1069 case D3DFMT_X8R8G8B8:
1070 case D3DFMT_A8R8G8B8:
1071 if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
1072 if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
1073 break;
1074 case D3DFMT_X1R5G5B5:
1075 case D3DFMT_A1R5G5B5:
1076 case D3DFMT_R5G6B5:
1077 if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
1078 break;
1079 default:
1080 /* Skip other modes as they do not match the requested format */
1081 break;
1084 #else
1085 i = 1;
1086 j = 1;
1087 #endif
1088 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1089 return i;
1090 } else {
1091 FIXME_(d3d_caps)("Adapter not primary display\n");
1093 return 0;
1096 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1097 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1098 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1099 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1101 /* Validate the parameters as much as possible */
1102 if (NULL == pMode ||
1103 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1104 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1105 return WINED3DERR_INVALIDCALL;
1108 if (Adapter == 0) { /* Display */
1109 #if !defined( DEBUG_SINGLE_MODE )
1110 DEVMODEW DevModeW;
1111 int ModeIdx = 0;
1113 /* Work out the current screen bpp */
1114 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1115 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1116 DeleteDC(hdc);
1118 /* If we are filtering to a specific format, then need to skip all unrelated
1119 modes, but if mode is irrelevant, then we can use the index directly */
1120 if (Format == D3DFMT_UNKNOWN)
1122 ModeIdx = Mode;
1123 } else {
1124 int i = 0;
1125 int j = 0;
1126 DEVMODEW DevModeWtmp;
1129 while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
1130 j++;
1131 switch (Format)
1133 case D3DFMT_UNKNOWN:
1134 i++;
1135 break;
1136 case D3DFMT_X8R8G8B8:
1137 case D3DFMT_A8R8G8B8:
1138 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
1139 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
1140 break;
1141 case D3DFMT_X1R5G5B5:
1142 case D3DFMT_A1R5G5B5:
1143 case D3DFMT_R5G6B5:
1144 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
1145 break;
1146 default:
1147 /* Skip other modes as they do not match requested format */
1148 break;
1151 ModeIdx = j;
1154 /* Now get the display mode via the calculated index */
1155 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
1157 pMode->Width = DevModeW.dmPelsWidth;
1158 pMode->Height = DevModeW.dmPelsHeight;
1159 bpp = min(DevModeW.dmBitsPerPel, bpp);
1160 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1161 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1163 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1166 if (Format == D3DFMT_UNKNOWN)
1168 switch (bpp) {
1169 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1170 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1171 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
1172 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1173 default: pMode->Format = D3DFMT_UNKNOWN;
1175 } else {
1176 pMode->Format = Format;
1179 else
1181 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1182 return WINED3DERR_INVALIDCALL;
1185 #else
1186 /* Return one setting of the format requested */
1187 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1188 pMode->Width = 800;
1189 pMode->Height = 600;
1190 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1191 pMode->Format = (Format == D3DFMT_UNKNOWN) ? D3DFMT_A8R8G8B8 : Format;
1192 bpp = 32;
1193 #endif
1194 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1195 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
1197 } else {
1198 FIXME_(d3d_caps)("Adapter not primary display\n");
1201 return WINED3D_OK;
1204 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1205 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1206 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1208 if (NULL == pMode ||
1209 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1210 return WINED3DERR_INVALIDCALL;
1213 if (Adapter == 0) { /* Display */
1214 int bpp = 0;
1215 DEVMODEW DevModeW;
1217 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1218 pMode->Width = DevModeW.dmPelsWidth;
1219 pMode->Height = DevModeW.dmPelsHeight;
1220 bpp = DevModeW.dmBitsPerPel;
1221 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1222 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1224 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1227 switch (bpp) {
1228 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1229 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1230 case 24: pMode->Format = D3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1231 case 32: pMode->Format = D3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1232 default: pMode->Format = D3DFMT_UNKNOWN;
1235 } else {
1236 FIXME_(d3d_caps)("Adapter not primary display\n");
1239 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1240 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1241 return WINED3D_OK;
1244 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1245 Display *display;
1246 HDC device_context;
1247 /* only works with one adapter at the moment... */
1249 /* Get the display */
1250 device_context = GetDC(0);
1251 display = get_display(device_context);
1252 ReleaseDC(0, device_context);
1253 return display;
1256 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1257 and fields being inserted in the middle, a new structure is used in place */
1258 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1259 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1260 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1262 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1264 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1265 return WINED3DERR_INVALIDCALL;
1268 if (Adapter == 0) { /* Display - only device supported for now */
1270 BOOL isGLInfoValid = This->isGLInfoValid;
1272 /* FillGLCaps updates gl_info, but we only want to store and
1273 reuse the values once we have a context which is valid. Values from
1274 a temporary context may differ from the final ones */
1275 if (!isGLInfoValid) {
1276 WineD3D_Context *fake_ctx = NULL;
1277 if (glXGetCurrentContext() == NULL) fake_ctx = WineD3D_CreateFakeGLContext();
1278 /* If we don't know the device settings, go query them now */
1279 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1280 if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
1283 /* If it worked, return the information requested */
1284 if (isGLInfoValid) {
1285 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1286 strcpy(pIdentifier->Driver, "Display");
1287 strcpy(pIdentifier->Description, "Direct3D HAL");
1289 /* Note dx8 doesn't supply a DeviceName */
1290 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1291 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1292 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1293 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1294 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1295 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1296 *(pIdentifier->SubSysId) = 0;
1297 *(pIdentifier->Revision) = 0;
1299 } else {
1301 /* If it failed, return dummy values from an NVidia driver */
1302 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1303 strcpy(pIdentifier->Driver, "Display");
1304 strcpy(pIdentifier->Description, "Direct3D HAL");
1305 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1306 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1307 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1308 /* 71.74 is a current Linux Nvidia driver version */
1309 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1310 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1311 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1312 *(pIdentifier->SubSysId) = 0;
1313 *(pIdentifier->Revision) = 0;
1316 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1317 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1318 *(pIdentifier->WHQLLevel) = 0;
1319 } else {
1320 *(pIdentifier->WHQLLevel) = 1;
1323 } else {
1324 FIXME_(d3d_caps)("Adapter not primary display\n");
1327 return WINED3D_OK;
1330 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1331 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1332 int gl_test;
1333 int rb, gb, bb, ab, type, buf_sz;
1335 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE, &rb);
1336 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
1337 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE, &bb);
1338 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
1339 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
1340 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1342 switch (Format) {
1343 case WINED3DFMT_X8R8G8B8:
1344 case WINED3DFMT_R8G8B8:
1345 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1346 break;
1347 case WINED3DFMT_A8R8G8B8:
1348 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1349 break;
1350 case WINED3DFMT_A2R10G10B10:
1351 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1352 break;
1353 case WINED3DFMT_X1R5G5B5:
1354 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1355 break;
1356 case WINED3DFMT_A1R5G5B5:
1357 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1358 break;
1359 case WINED3DFMT_X4R4G4B4:
1360 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1361 break;
1362 case WINED3DFMT_R5G6B5:
1363 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1364 break;
1365 case WINED3DFMT_R3G3B2:
1366 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1367 break;
1368 case WINED3DFMT_A8P8:
1369 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1370 break;
1371 case WINED3DFMT_P8:
1372 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1373 break;
1374 default:
1375 ERR("unsupported format %s\n", debug_d3dformat(Format));
1376 break;
1378 return FALSE;
1379 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1380 switch (Format) {
1381 case WINED3DFMT_X8R8G8B8:
1382 case WINED3DFMT_R8G8B8:
1383 case WINED3DFMT_A8R8G8B8:
1384 case WINED3DFMT_A2R10G10B10:
1385 case WINED3DFMT_X1R5G5B5:
1386 case WINED3DFMT_A1R5G5B5:
1387 case WINED3DFMT_R5G6B5:
1388 case WINED3DFMT_R3G3B2:
1389 case WINED3DFMT_A8P8:
1390 case WINED3DFMT_P8:
1391 return TRUE;
1392 default:
1393 ERR("unsupported format %s\n", debug_d3dformat(Format));
1394 break;
1396 return FALSE;
1397 #endif
1400 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1401 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1402 int gl_test;
1403 int db, sb;
1405 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
1406 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
1408 switch (Format) {
1409 case WINED3DFMT_D16:
1410 case WINED3DFMT_D16_LOCKABLE:
1411 if (16 == db) return TRUE;
1412 break;
1413 case WINED3DFMT_D32:
1414 if (32 == db) return TRUE;
1415 break;
1416 case WINED3DFMT_D15S1:
1417 if (15 == db) return TRUE;
1418 break;
1419 case WINED3DFMT_D24S8:
1420 if (24 == db && 8 == sb) return TRUE;
1421 break;
1422 case WINED3DFMT_D24FS8:
1423 if (24 == db && 8 == sb) return TRUE;
1424 break;
1425 case WINED3DFMT_D24X8:
1426 if (24 == db) return TRUE;
1427 break;
1428 case WINED3DFMT_D24X4S4:
1429 if (24 == db && 4 == sb) return TRUE;
1430 break;
1431 case WINED3DFMT_D32F_LOCKABLE:
1432 if (32 == db) return TRUE;
1433 break;
1434 default:
1435 ERR("unsupported format %s\n", debug_d3dformat(Format));
1436 break;
1438 return FALSE;
1439 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1440 switch (Format) {
1441 case WINED3DFMT_D16:
1442 case WINED3DFMT_D16_LOCKABLE:
1443 case WINED3DFMT_D32:
1444 case WINED3DFMT_D15S1:
1445 case WINED3DFMT_D24S8:
1446 case WINED3DFMT_D24FS8:
1447 case WINED3DFMT_D24X8:
1448 case WINED3DFMT_D24X4S4:
1449 case WINED3DFMT_D32F_LOCKABLE:
1450 return TRUE;
1451 default:
1452 ERR("unsupported format %s\n", debug_d3dformat(Format));
1453 break;
1455 return FALSE;
1456 #endif
1459 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1460 WINED3DFORMAT AdapterFormat,
1461 WINED3DFORMAT RenderTargetFormat,
1462 WINED3DFORMAT DepthStencilFormat) {
1463 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1464 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1465 WineD3D_Context* ctx = NULL;
1466 GLXFBConfig* cfgs = NULL;
1467 int nCfgs = 0;
1468 int it;
1470 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1471 This, Adapter,
1472 DeviceType, debug_d3ddevicetype(DeviceType),
1473 AdapterFormat, debug_d3dformat(AdapterFormat),
1474 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1475 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1477 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1478 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1479 return WINED3DERR_INVALIDCALL;
1481 /* TODO: use the real context if it's available */
1482 ctx = WineD3D_CreateFakeGLContext();
1483 if(NULL != ctx) {
1484 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1485 } else {
1486 TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
1489 if (NULL != cfgs) {
1490 for (it = 0; it < nCfgs; ++it) {
1491 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
1492 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
1493 hr = WINED3D_OK;
1494 break ;
1498 XFree(cfgs);
1499 cfgs = NULL;
1500 } else {
1501 /* If there's a current context then we cannot create a fake one so pass everything */
1502 hr = WINED3D_OK;
1505 if (ctx != NULL)
1506 WineD3D_ReleaseFakeGLContext(ctx);
1508 if (hr != WINED3D_OK)
1509 TRACE_(d3d_caps)("Failed to match stencil format to device\b");
1511 TRACE_(d3d_caps)("(%p) : Returning %lx\n", This, hr);
1512 return hr;
1515 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1516 WINED3DFORMAT SurfaceFormat,
1517 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1519 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1520 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1521 This,
1522 Adapter,
1523 DeviceType, debug_d3ddevicetype(DeviceType),
1524 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1525 Windowed,
1526 MultiSampleType,
1527 pQualityLevels);
1529 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1530 return WINED3DERR_INVALIDCALL;
1533 if (pQualityLevels != NULL) {
1534 static int s_single_shot = 0;
1535 if (!s_single_shot) {
1536 FIXME("Quality levels unsupported at present\n");
1537 s_single_shot = 1;
1539 *pQualityLevels = 1; /* Guess at a value! */
1542 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1543 return WINED3DERR_NOTAVAILABLE;
1546 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1547 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1549 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1550 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1551 This,
1552 Adapter,
1553 CheckType, debug_d3ddevicetype(CheckType),
1554 DisplayFormat, debug_d3dformat(DisplayFormat),
1555 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1556 Windowed);
1558 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1559 return WINED3DERR_INVALIDCALL;
1563 GLXFBConfig* cfgs = NULL;
1564 int nCfgs = 0;
1565 int it;
1566 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1568 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1569 if (NULL != ctx) {
1570 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1571 for (it = 0; it < nCfgs; ++it) {
1572 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1573 hr = WINED3D_OK;
1574 break ;
1577 XFree(cfgs);
1579 WineD3D_ReleaseFakeGLContext(ctx);
1580 return hr;
1584 return WINED3DERR_NOTAVAILABLE;
1587 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1588 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1589 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1590 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
1591 This,
1592 Adapter,
1593 DeviceType, debug_d3ddevicetype(DeviceType),
1594 AdapterFormat, debug_d3dformat(AdapterFormat),
1595 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1596 RType, debug_d3dresourcetype(RType),
1597 CheckFormat, debug_d3dformat(CheckFormat));
1599 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1600 return WINED3DERR_INVALIDCALL;
1603 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1604 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1605 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1606 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1607 TRACE_(d3d_caps)("[FAILED]\n");
1608 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1611 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1612 switch (CheckFormat) {
1613 case WINED3DFMT_D16_LOCKABLE:
1614 case WINED3DFMT_D32:
1615 case WINED3DFMT_D15S1:
1616 case WINED3DFMT_D24S8:
1617 case WINED3DFMT_D24X8:
1618 case WINED3DFMT_D24X4S4:
1619 case WINED3DFMT_D16:
1620 case WINED3DFMT_L16:
1621 case WINED3DFMT_D32F_LOCKABLE:
1622 case WINED3DFMT_D24FS8:
1623 TRACE_(d3d_caps)("[OK]\n");
1624 return WINED3D_OK;
1625 default:
1626 TRACE_(d3d_caps)("[FAILED]\n");
1627 return WINED3DERR_NOTAVAILABLE;
1629 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1630 switch (CheckFormat) {
1631 case WINED3DFMT_R8G8B8:
1632 case WINED3DFMT_A8R8G8B8:
1633 case WINED3DFMT_X8R8G8B8:
1634 case WINED3DFMT_R5G6B5:
1635 case WINED3DFMT_X1R5G5B5:
1636 case WINED3DFMT_A1R5G5B5:
1637 case WINED3DFMT_A4R4G4B4:
1638 case WINED3DFMT_R3G3B2:
1639 case WINED3DFMT_X4R4G4B4:
1640 case WINED3DFMT_A8B8G8R8:
1641 case WINED3DFMT_X8B8G8R8:
1642 case WINED3DFMT_P8:
1643 TRACE_(d3d_caps)("[OK]\n");
1644 return WINED3D_OK;
1645 default:
1646 TRACE_(d3d_caps)("[FAILED]\n");
1647 return WINED3DERR_NOTAVAILABLE;
1651 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1652 switch (CheckFormat) {
1653 case D3DFMT_DXT1:
1654 case D3DFMT_DXT2:
1655 case D3DFMT_DXT3:
1656 case D3DFMT_DXT4:
1657 case D3DFMT_DXT5:
1658 TRACE_(d3d_caps)("[OK]\n");
1659 return WINED3D_OK;
1660 default:
1661 break; /* Avoid compiler warnings */
1665 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1667 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1669 switch (CheckFormat) {
1670 case D3DFMT_R16F:
1671 case D3DFMT_A16B16G16R16F:
1672 if (!half_pixel_support) break;
1673 case D3DFMT_R32F:
1674 case D3DFMT_A32B32G32R32F:
1675 TRACE_(d3d_caps)("[OK]\n");
1676 return WINED3D_OK;
1677 default:
1678 break; /* Avoid compiler warnings */
1682 /* This format is nothing special and it is supported perfectly.
1683 * However, ati and nvidia driver on windows do not mark this format as
1684 * supported (tested with the dxCapsViewer) and pretending to
1685 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1686 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1687 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1689 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1690 TRACE_(d3d_caps)("[FAILED]\n");
1691 return WINED3DERR_NOTAVAILABLE;
1694 switch (CheckFormat) {
1696 /*****
1697 * supported: RGB(A) formats
1699 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1700 case WINED3DFMT_A8R8G8B8:
1701 case WINED3DFMT_X8R8G8B8:
1702 case WINED3DFMT_R5G6B5:
1703 case WINED3DFMT_X1R5G5B5:
1704 case WINED3DFMT_A1R5G5B5:
1705 case WINED3DFMT_A4R4G4B4:
1706 case WINED3DFMT_R3G3B2:
1707 case WINED3DFMT_A8:
1708 case WINED3DFMT_A8R3G3B2:
1709 case WINED3DFMT_X4R4G4B4:
1710 case WINED3DFMT_A8B8G8R8:
1711 case WINED3DFMT_X8B8G8R8:
1712 case WINED3DFMT_A2R10G10B10:
1713 case WINED3DFMT_A2B10G10R10:
1714 TRACE_(d3d_caps)("[OK]\n");
1715 return WINED3D_OK;
1717 /*****
1718 * supported: Palettized
1720 case WINED3DFMT_P8:
1721 TRACE_(d3d_caps)("[OK]\n");
1722 return WINED3D_OK;
1724 /*****
1725 * Supported: (Alpha)-Luminance
1727 case WINED3DFMT_L8:
1728 case WINED3DFMT_A8L8:
1729 case WINED3DFMT_A4L4:
1730 TRACE_(d3d_caps)("[OK]\n");
1731 return WINED3D_OK;
1733 /*****
1734 * Not supported for now: Bump mapping formats
1735 * Enable some because games often fail when they are not available
1736 * and are still playable even without bump mapping
1738 case WINED3DFMT_V8U8:
1739 case WINED3DFMT_V16U16:
1740 case WINED3DFMT_L6V5U5:
1741 case WINED3DFMT_X8L8V8U8:
1742 case WINED3DFMT_Q8W8V8U8:
1743 case WINED3DFMT_W11V11U10:
1744 case WINED3DFMT_A2W10V10U10:
1745 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1746 return WINED3D_OK;
1748 /*****
1749 * DXTN Formats: Handled above
1750 * WINED3DFMT_DXT1
1751 * WINED3DFMT_DXT2
1752 * WINED3DFMT_DXT3
1753 * WINED3DFMT_DXT4
1754 * WINED3DFMT_DXT5
1757 /*****
1758 * Odd formats - not supported
1760 case WINED3DFMT_VERTEXDATA:
1761 case WINED3DFMT_INDEX16:
1762 case WINED3DFMT_INDEX32:
1763 case WINED3DFMT_Q16W16V16U16:
1764 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1765 return WINED3DERR_NOTAVAILABLE;
1767 /*****
1768 * Float formats: Not supported right now
1770 case WINED3DFMT_G16R16F:
1771 case WINED3DFMT_G32R32F:
1772 case WINED3DFMT_CxV8U8:
1773 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1774 return WINED3DERR_NOTAVAILABLE;
1776 /* Not supported */
1777 case WINED3DFMT_G16R16:
1778 case WINED3DFMT_A16B16G16R16:
1779 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1780 return WINED3DERR_NOTAVAILABLE;
1782 default:
1783 break;
1786 TRACE_(d3d_caps)("[FAILED]\n");
1787 return WINED3DERR_NOTAVAILABLE;
1790 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1791 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1792 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1794 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1795 This,
1796 Adapter,
1797 DeviceType, debug_d3ddevicetype(DeviceType),
1798 SourceFormat, debug_d3dformat(SourceFormat),
1799 TargetFormat, debug_d3dformat(TargetFormat));
1800 return WINED3D_OK;
1803 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1804 subset of a D3DCAPS9 structure. However, it has to come via a void *
1805 as the d3d8 interface cannot import the d3d9 header */
1806 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1808 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1810 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1812 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1813 return WINED3DERR_INVALIDCALL;
1816 /* FIXME: both the gl_info and the shader_mode should be made per adapter */
1818 /* If we don't know the device settings, go query them now */
1819 if (!This->isGLInfoValid) {
1820 /* use the desktop window to fill gl caps */
1821 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1823 /* We are running off a real context, save the values */
1824 if (rc) This->isGLInfoValid = TRUE;
1826 select_shader_mode(&This->gl_info, DeviceType,
1827 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
1828 select_shader_max_constants(&This->gl_info);
1830 /* ------------------------------------------------
1831 The following fields apply to both d3d8 and d3d9
1832 ------------------------------------------------ */
1833 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1834 *pCaps->AdapterOrdinal = Adapter;
1836 *pCaps->Caps = 0;
1837 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1838 WINED3DCAPS2_FULLSCREENGAMMA;
1839 *pCaps->Caps3 = 0;
1840 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1842 *pCaps->CursorCaps = 0;
1845 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1846 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1847 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1848 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1849 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1850 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1851 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1852 WINED3DDEVCAPS_PUREDEVICE |
1853 WINED3DDEVCAPS_HWRASTERIZATION |
1854 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1855 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1856 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1857 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1858 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1860 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1861 D3DPMISCCAPS_CULLCCW |
1862 D3DPMISCCAPS_CULLCW |
1863 D3DPMISCCAPS_COLORWRITEENABLE |
1864 D3DPMISCCAPS_CLIPTLVERTS |
1865 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1866 D3DPMISCCAPS_MASKZ |
1867 D3DPMISCCAPS_BLENDOP;
1868 /* TODO:
1869 D3DPMISCCAPS_NULLREFERENCE
1870 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1871 D3DPMISCCAPS_FOGANDSPECULARALPHA
1872 D3DPMISCCAPS_SEPARATEALPHABLEND
1873 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1874 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1875 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1877 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1878 #if 0
1879 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1880 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1881 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1882 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1883 #endif
1885 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1886 WINED3DPRASTERCAPS_PAT |
1887 WINED3DPRASTERCAPS_WFOG |
1888 WINED3DPRASTERCAPS_ZFOG |
1889 WINED3DPRASTERCAPS_FOGVERTEX |
1890 WINED3DPRASTERCAPS_FOGTABLE |
1891 WINED3DPRASTERCAPS_FOGRANGE |
1892 WINED3DPRASTERCAPS_STIPPLE |
1893 WINED3DPRASTERCAPS_SUBPIXEL |
1894 WINED3DPRASTERCAPS_ZTEST |
1895 WINED3DPRASTERCAPS_SCISSORTEST |
1896 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1897 WINED3DPRASTERCAPS_DEPTHBIAS;
1899 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1900 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1901 WINED3DPRASTERCAPS_ZBIAS |
1902 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1904 /* FIXME Add:
1905 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1906 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1907 WINED3DPRASTERCAPS_ANTIALIASEDGES
1908 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1909 WINED3DPRASTERCAPS_WBUFFER */
1911 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1912 D3DPCMPCAPS_EQUAL |
1913 D3DPCMPCAPS_GREATER |
1914 D3DPCMPCAPS_GREATEREQUAL |
1915 D3DPCMPCAPS_LESS |
1916 D3DPCMPCAPS_LESSEQUAL |
1917 D3DPCMPCAPS_NEVER |
1918 D3DPCMPCAPS_NOTEQUAL;
1920 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1921 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1922 D3DPBLENDCAPS_BOTHSRCALPHA |
1923 D3DPBLENDCAPS_DESTALPHA |
1924 D3DPBLENDCAPS_DESTCOLOR |
1925 D3DPBLENDCAPS_INVDESTALPHA |
1926 D3DPBLENDCAPS_INVDESTCOLOR |
1927 D3DPBLENDCAPS_INVSRCALPHA |
1928 D3DPBLENDCAPS_INVSRCCOLOR |
1929 D3DPBLENDCAPS_ONE |
1930 D3DPBLENDCAPS_SRCALPHA |
1931 D3DPBLENDCAPS_SRCALPHASAT |
1932 D3DPBLENDCAPS_SRCCOLOR |
1933 D3DPBLENDCAPS_ZERO;
1935 *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1936 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1937 D3DPBLENDCAPS_BOTHSRCALPHA |
1938 D3DPBLENDCAPS_DESTALPHA |
1939 D3DPBLENDCAPS_DESTCOLOR |
1940 D3DPBLENDCAPS_INVDESTALPHA |
1941 D3DPBLENDCAPS_INVDESTCOLOR |
1942 D3DPBLENDCAPS_INVSRCALPHA |
1943 D3DPBLENDCAPS_INVSRCCOLOR |
1944 D3DPBLENDCAPS_ONE |
1945 D3DPBLENDCAPS_SRCALPHA |
1946 D3DPBLENDCAPS_SRCALPHASAT |
1947 D3DPBLENDCAPS_SRCCOLOR |
1948 D3DPBLENDCAPS_ZERO;
1950 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1951 D3DPCMPCAPS_EQUAL |
1952 D3DPCMPCAPS_GREATER |
1953 D3DPCMPCAPS_GREATEREQUAL |
1954 D3DPCMPCAPS_LESS |
1955 D3DPCMPCAPS_LESSEQUAL |
1956 D3DPCMPCAPS_NEVER |
1957 D3DPCMPCAPS_NOTEQUAL;
1959 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1960 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1961 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1962 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1963 WINED3DPSHADECAPS_COLORFLATRGB |
1964 WINED3DPSHADECAPS_FOGFLAT |
1965 WINED3DPSHADECAPS_FOGGOURAUD |
1966 WINED3DPSHADECAPS_SPECULARFLATRGB;
1968 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1969 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1970 WINED3DPTEXTURECAPS_BORDER |
1971 WINED3DPTEXTURECAPS_MIPMAP |
1972 WINED3DPTEXTURECAPS_PROJECTED |
1973 WINED3DPTEXTURECAPS_PERSPECTIVE |
1974 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1976 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1977 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1978 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1979 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1982 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1983 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1984 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1985 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1989 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1990 WINED3DPTFILTERCAPS_MAGFPOINT |
1991 WINED3DPTFILTERCAPS_MINFLINEAR |
1992 WINED3DPTFILTERCAPS_MINFPOINT |
1993 WINED3DPTFILTERCAPS_MIPFLINEAR |
1994 WINED3DPTFILTERCAPS_MIPFPOINT |
1995 WINED3DPTFILTERCAPS_LINEAR |
1996 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1997 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1998 WINED3DPTFILTERCAPS_MIPLINEAR |
1999 WINED3DPTFILTERCAPS_MIPNEAREST |
2000 WINED3DPTFILTERCAPS_NEAREST;
2002 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2003 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2004 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2007 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2008 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2009 WINED3DPTFILTERCAPS_MAGFPOINT |
2010 WINED3DPTFILTERCAPS_MINFLINEAR |
2011 WINED3DPTFILTERCAPS_MINFPOINT |
2012 WINED3DPTFILTERCAPS_MIPFLINEAR |
2013 WINED3DPTFILTERCAPS_MIPFPOINT |
2014 WINED3DPTFILTERCAPS_LINEAR |
2015 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2016 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2017 WINED3DPTFILTERCAPS_MIPLINEAR |
2018 WINED3DPTFILTERCAPS_MIPNEAREST |
2019 WINED3DPTFILTERCAPS_NEAREST;
2021 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2022 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2023 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2025 } else
2026 *pCaps->CubeTextureFilterCaps = 0;
2028 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2029 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2030 WINED3DPTFILTERCAPS_MAGFPOINT |
2031 WINED3DPTFILTERCAPS_MINFLINEAR |
2032 WINED3DPTFILTERCAPS_MINFPOINT |
2033 WINED3DPTFILTERCAPS_MIPFLINEAR |
2034 WINED3DPTFILTERCAPS_MIPFPOINT |
2035 WINED3DPTFILTERCAPS_LINEAR |
2036 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2037 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2038 WINED3DPTFILTERCAPS_MIPLINEAR |
2039 WINED3DPTFILTERCAPS_MIPNEAREST |
2040 WINED3DPTFILTERCAPS_NEAREST;
2041 } else
2042 *pCaps->VolumeTextureFilterCaps = 0;
2044 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2045 D3DPTADDRESSCAPS_CLAMP |
2046 D3DPTADDRESSCAPS_WRAP;
2048 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2049 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2051 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2052 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2054 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2055 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2058 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2059 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2060 D3DPTADDRESSCAPS_CLAMP |
2061 D3DPTADDRESSCAPS_WRAP;
2062 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2063 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2065 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2066 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2068 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2069 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2071 } else
2072 *pCaps->VolumeTextureAddressCaps = 0;
2074 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2075 D3DLINECAPS_ZTEST;
2076 /* FIXME: Add
2077 D3DLINECAPS_BLEND
2078 D3DLINECAPS_ALPHACMP
2079 D3DLINECAPS_FOG */
2081 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2082 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2084 if(GL_SUPPORT(EXT_TEXTURE3D))
2085 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2086 else
2087 *pCaps->MaxVolumeExtent = 0;
2089 *pCaps->MaxTextureRepeat = 32768;
2090 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2091 *pCaps->MaxVertexW = 1.0;
2093 *pCaps->GuardBandLeft = 0;
2094 *pCaps->GuardBandTop = 0;
2095 *pCaps->GuardBandRight = 0;
2096 *pCaps->GuardBandBottom = 0;
2098 *pCaps->ExtentsAdjust = 0;
2100 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2101 D3DSTENCILCAPS_INCRSAT |
2102 D3DSTENCILCAPS_INVERT |
2103 D3DSTENCILCAPS_KEEP |
2104 D3DSTENCILCAPS_REPLACE |
2105 D3DSTENCILCAPS_ZERO;
2106 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2107 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2108 D3DSTENCILCAPS_INCR;
2110 if ( This->dxVersion > 8 &&
2111 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2112 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2113 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2116 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2118 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2119 D3DTEXOPCAPS_ADDSIGNED |
2120 D3DTEXOPCAPS_ADDSIGNED2X |
2121 D3DTEXOPCAPS_MODULATE |
2122 D3DTEXOPCAPS_MODULATE2X |
2123 D3DTEXOPCAPS_MODULATE4X |
2124 D3DTEXOPCAPS_SELECTARG1 |
2125 D3DTEXOPCAPS_SELECTARG2 |
2126 D3DTEXOPCAPS_DISABLE;
2128 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2129 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2130 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2131 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2132 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2133 D3DTEXOPCAPS_BLENDFACTORALPHA |
2134 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2135 D3DTEXOPCAPS_LERP |
2136 D3DTEXOPCAPS_SUBTRACT;
2138 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2139 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2140 D3DTEXOPCAPS_MULTIPLYADD |
2141 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2142 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2143 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2145 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2146 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2148 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2149 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2150 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2154 #if 0
2155 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2156 /* FIXME: Add
2157 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2158 D3DTEXOPCAPS_PREMODULATE */
2159 #endif
2161 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2162 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2163 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2164 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2168 #if 0 /* TODO: Blends support in drawprim */
2169 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2170 #else
2171 *pCaps->MaxVertexBlendMatrices = 0;
2172 #endif
2173 *pCaps->MaxVertexBlendMatrixIndex = 1;
2175 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2176 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2179 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2180 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2181 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2182 WINED3DVTXPCAPS_LOCALVIEWER |
2183 WINED3DVTXPCAPS_VERTEXFOG |
2184 WINED3DVTXPCAPS_TEXGEN;
2185 /* FIXME: Add
2186 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2188 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2189 *pCaps->MaxVertexIndex = 0xFFFFF;
2190 *pCaps->MaxStreams = MAX_STREAMS;
2191 *pCaps->MaxStreamStride = 1024;
2193 /* FIXME: the shader mode should be per adapter */
2194 if (wined3d_settings.vs_selected_mode == SHADER_GLSL) {
2195 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2196 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2197 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2198 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2199 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2200 *pCaps->VertexShaderVersion = D3DVS_VERSION(2,0);
2201 else
2202 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2203 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2204 } else if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
2205 *pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
2206 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2207 } else if (wined3d_settings.vs_selected_mode == SHADER_SW) {
2208 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2209 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2210 } else {
2211 *pCaps->VertexShaderVersion = 0;
2212 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2215 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2217 /* FIXME: the shader mode should be per adapter */
2218 if (wined3d_settings.ps_selected_mode == SHADER_GLSL) {
2219 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2220 in case of GeforceFX cards. */
2221 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2222 *pCaps->PixelShaderVersion = D3DPS_VERSION(2,0);
2223 else
2224 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2225 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2226 *pCaps->PixelShader1xMaxValue = 1.0;
2227 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2228 } else if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
2229 *pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
2230 *pCaps->PixelShader1xMaxValue = 1.0;
2231 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2232 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2233 } else if (wined3d_settings.ps_selected_mode = SHADER_SW) {
2234 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2235 *pCaps->PixelShader1xMaxValue = 1.0;
2236 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2237 } else {
2238 *pCaps->PixelShaderVersion = 0;
2239 *pCaps->PixelShader1xMaxValue = 0.0;
2240 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2243 /* ------------------------------------------------
2244 The following fields apply to d3d9 only
2245 ------------------------------------------------ */
2246 if (This->dxVersion > 8) {
2247 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
2248 *pCaps->DevCaps2 = 0;
2249 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES and VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2250 *pCaps->MaxNpatchTessellationLevel = 0;
2251 *pCaps->MasterAdapterOrdinal = 0;
2252 *pCaps->AdapterOrdinalInGroup = 0;
2253 *pCaps->NumberOfAdaptersInGroup = 1;
2255 if(*pCaps->VertexShaderVersion >= D3DVS_VERSION(2,0)) {
2256 /* OpenGL supports all formats below, perhaps not always without conversion but it supports them.
2257 Further GLSL doesn't seem to have an official unsigned type as I'm not sure how we handle it
2258 don't advertise it yet. We might need to add some clamping in the shader engine to support it.
2259 TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2260 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2261 D3DDTCAPS_UBYTE4N |
2262 D3DDTCAPS_SHORT2N |
2263 D3DDTCAPS_SHORT4N |
2264 D3DDTCAPS_FLOAT16_2 |
2265 D3DDTCAPS_FLOAT16_4;
2267 } else
2268 *pCaps->DeclTypes = 0;
2270 #if 0 /* We don't properly support multiple render targets yet, so disable this for now */
2271 if (GL_SUPPORT(ARB_DRAWBUFFERS)) {
2272 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2273 } else
2274 #endif
2275 *pCaps->NumSimultaneousRTs = 1;
2277 *pCaps->StretchRectFilterCaps = 0;
2278 *pCaps->VertexTextureFilterCaps = 0;
2280 if(*pCaps->VertexShaderVersion == D3DVS_VERSION(3,0)) {
2281 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2282 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2283 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2284 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2285 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2286 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2288 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2289 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2290 } else if(*pCaps->VertexShaderVersion == D3DVS_VERSION(2,0)) {
2291 *pCaps->VS20Caps.Caps = 0;
2292 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2293 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2294 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2296 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2297 *pCaps->MaxVertexShader30InstructionSlots = 0;
2298 } else { /* VS 1.x */
2299 *pCaps->VS20Caps.Caps = 0;
2300 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2301 *pCaps->VS20Caps.NumTemps = 0;
2302 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2304 *pCaps->MaxVShaderInstructionsExecuted = 0;
2305 *pCaps->MaxVertexShader30InstructionSlots = 0;
2308 if(*pCaps->PixelShaderVersion == D3DPS_VERSION(3,0)) {
2309 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2310 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2312 /* 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 */
2313 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2314 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2315 D3DPS20CAPS_PREDICATION |
2316 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2317 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2318 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2319 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2320 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2321 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2323 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2324 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2325 } else if(*pCaps->PixelShaderVersion == D3DPS_VERSION(2,0)) {
2326 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2327 *pCaps->PS20Caps.Caps = 0;
2328 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2329 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2330 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2331 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2333 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2334 *pCaps->MaxPixelShader30InstructionSlots = 0;
2335 } else { /* PS 1.x */
2336 *pCaps->PS20Caps.Caps = 0;
2337 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2338 *pCaps->PS20Caps.NumTemps = 0;
2339 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2340 *pCaps->PS20Caps.NumInstructionSlots = 0;
2342 *pCaps->MaxPShaderInstructionsExecuted = 0;
2343 *pCaps->MaxPixelShader30InstructionSlots = 0;
2347 return WINED3D_OK;
2351 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2352 and fields being inserted in the middle, a new structure is used in place */
2353 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2354 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2355 IUnknown *parent) {
2357 IWineD3DDeviceImpl *object = NULL;
2358 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2359 HDC hDC;
2360 HRESULT temp_result;
2362 /* Validate the adapter number */
2363 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2364 return WINED3DERR_INVALIDCALL;
2367 /* Create a WineD3DDevice object */
2368 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2369 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2370 TRACE("Created WineD3DDevice object @ %p\n", object);
2371 if (NULL == object) {
2372 return WINED3DERR_OUTOFVIDEOMEMORY;
2375 /* Set up initial COM information */
2376 object->lpVtbl = &IWineD3DDevice_Vtbl;
2377 object->ref = 1;
2378 object->wineD3D = iface;
2379 IWineD3D_AddRef(object->wineD3D);
2380 object->parent = parent;
2382 /* Set the state up as invalid until the device is fully created */
2383 object->state = WINED3DERR_DRIVERINTERNALERROR;
2385 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, RetDevInt: %p)\n", This, Adapter, DeviceType,
2386 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2388 /* Save the creation parameters */
2389 object->createParms.AdapterOrdinal = Adapter;
2390 object->createParms.DeviceType = DeviceType;
2391 object->createParms.hFocusWindow = hFocusWindow;
2392 object->createParms.BehaviorFlags = BehaviourFlags;
2394 /* Initialize other useful values */
2395 object->adapterNo = Adapter;
2396 object->devType = DeviceType;
2398 TRACE("(%p) : Creating stateblock\n", This);
2399 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2400 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2401 WINED3DSBT_INIT,
2402 (IWineD3DStateBlock **)&object->stateBlock,
2403 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2404 WARN("Failed to create stateblock\n");
2405 goto create_device_error;
2407 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2408 object->updateStateBlock = object->stateBlock;
2409 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2410 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2412 /* Setup some defaults for creating the implicit swapchain */
2413 ENTER_GL();
2414 /* FIXME: both of those should be made per adapter */
2415 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2416 LEAVE_GL();
2417 select_shader_mode(&This->gl_info, DeviceType,
2418 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
2419 select_shader_max_constants(&This->gl_info);
2421 temp_result = allocate_shader_constants(object->updateStateBlock);
2422 if (WINED3D_OK != temp_result)
2423 return temp_result;
2425 /* set the state of the device to valid */
2426 object->state = WINED3D_OK;
2428 /* Get the initial screen setup for ddraw */
2429 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2430 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2431 hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
2432 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2433 DeleteDC(hDC);
2435 return WINED3D_OK;
2436 create_device_error:
2438 /* Set the device state to error */
2439 object->state = WINED3DERR_DRIVERINTERNALERROR;
2441 if (object->updateStateBlock != NULL) {
2442 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2443 object->updateStateBlock = NULL;
2445 if (object->stateBlock != NULL) {
2446 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2447 object->stateBlock = NULL;
2449 if (object->renderTarget != NULL) {
2450 IWineD3DSurface_Release(object->renderTarget);
2451 object->renderTarget = NULL;
2453 if (object->stencilBufferTarget != NULL) {
2454 IWineD3DSurface_Release(object->stencilBufferTarget);
2455 object->stencilBufferTarget = NULL;
2457 if (object->stencilBufferTarget != NULL) {
2458 IWineD3DSurface_Release(object->stencilBufferTarget);
2459 object->stencilBufferTarget = NULL;
2461 HeapFree(GetProcessHeap(), 0, object);
2462 *ppReturnedDeviceInterface = NULL;
2463 return WINED3DERR_INVALIDCALL;
2467 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2468 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2469 IUnknown_AddRef(This->parent);
2470 *pParent = This->parent;
2471 return WINED3D_OK;
2474 /**********************************************************
2475 * IWineD3D VTbl follows
2476 **********************************************************/
2478 const IWineD3DVtbl IWineD3D_Vtbl =
2480 /* IUnknown */
2481 IWineD3DImpl_QueryInterface,
2482 IWineD3DImpl_AddRef,
2483 IWineD3DImpl_Release,
2484 /* IWineD3D */
2485 IWineD3DImpl_GetParent,
2486 IWineD3DImpl_GetAdapterCount,
2487 IWineD3DImpl_RegisterSoftwareDevice,
2488 IWineD3DImpl_GetAdapterMonitor,
2489 IWineD3DImpl_GetAdapterModeCount,
2490 IWineD3DImpl_EnumAdapterModes,
2491 IWineD3DImpl_GetAdapterDisplayMode,
2492 IWineD3DImpl_GetAdapterIdentifier,
2493 IWineD3DImpl_CheckDeviceMultiSampleType,
2494 IWineD3DImpl_CheckDepthStencilMatch,
2495 IWineD3DImpl_CheckDeviceType,
2496 IWineD3DImpl_CheckDeviceFormat,
2497 IWineD3DImpl_CheckDeviceFormatConversion,
2498 IWineD3DImpl_GetDeviceCaps,
2499 IWineD3DImpl_CreateDevice