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