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